Added #1501 Bulk import shapes

This commit is contained in:
Jindra Petřík
2022-11-18 20:09:18 +01:00
parent 337ebb2991
commit 3b0f8acb68
11 changed files with 168 additions and 4 deletions

View File

@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
- [#1280] AS3 Direct editation of traits with the same name
- [#1743] GFX - Adding DefineExternalImage2 and DefineSubImage tags
- [#1822], [#1803] AS3 direct editation - optional using AIR (airglobal.swc) to compile
- [#1501] Bulk import shapes
### Fixed
- [#1869] Replace references now replaces all references, not just PlaceObject
@@ -30,6 +31,7 @@ All notable changes to this project will be documented in this file.
- [#1840] AS3 Direct editation - Type mismatched for a trait
- [#1840] Proper if..continue..break handling
- [#1877] Recalculate dependent characters and frames on removing / editing item
- DefineShape4 SVG import NullPointerException
### Changed
- GFX - DefineExternalImage2 no longer handled as character
@@ -2611,6 +2613,7 @@ All notable changes to this project will be documented in this file.
[#1743]: https://www.free-decompiler.com/flash/issues/1743
[#1822]: https://www.free-decompiler.com/flash/issues/1822
[#1803]: https://www.free-decompiler.com/flash/issues/1803
[#1501]: https://www.free-decompiler.com/flash/issues/1501
[#1869]: https://www.free-decompiler.com/flash/issues/1869
[#1872]: https://www.free-decompiler.com/flash/issues/1872
[#1692]: https://www.free-decompiler.com/flash/issues/1692

View File

@@ -798,6 +798,10 @@ public final class Configuration {
@ConfigurationFile(".*\\.swc$")
public static ConfigurationItem<String> airLibLocation = null;
@ConfigurationDefaultBoolean(true)
@ConfigurationCategory("ui")
public static ConfigurationItem<Boolean> showImportShapeInfo = null;
private enum OSId {
WINDOWS, OSX, UNIX
}

View File

@@ -294,7 +294,21 @@ public abstract class MainFrameMenu implements MenuBuilder {
}
mainFrame.getPanel().importImage(swf);
}
protected void importShapesActionPerformed(ActionEvent evt) {
if (Main.isWorking()) {
return;
}
mainFrame.getPanel().importShape(swf, false);
}
protected void importShapesNoFillActionPerformed(ActionEvent evt) {
if (Main.isWorking()) {
return;
}
mainFrame.getPanel().importShape(swf, true);
}
protected void importSymbolClassActionPerformed(ActionEvent evt) {
if (Main.isWorking()) {
return;
@@ -932,6 +946,8 @@ public abstract class MainFrameMenu implements MenuBuilder {
addMenuItem("/file/import/importScript", translate("menu.file.import.script"), "importscript32", this::importScriptActionPerformed, PRIORITY_MEDIUM, null, true, null, false);
addMenuItem("/file/import/importOther", translate("menu.file.import.other"), "importother32", null, PRIORITY_MEDIUM, null, false, null, false);
addMenuItem("/file/import/importOther/importImages", translate("menu.file.import.image"), "importimage32", this::importImagesActionPerformed, PRIORITY_MEDIUM, null, true, null, false);
addMenuItem("/file/import/importOther/importShapes", translate("menu.file.import.shape"), "importshape32", this::importShapesActionPerformed, PRIORITY_MEDIUM, null, true, null, false);
addMenuItem("/file/import/importOther/importShapesNoFill", translate("menu.file.import.shapeNoFill"), "importshape32", this::importShapesNoFillActionPerformed, PRIORITY_MEDIUM, null, true, null, false);
addMenuItem("/file/import/importOther/importSymbolClass", translate("menu.file.import.symbolClass"), "importsymbolclass32", this::importSymbolClassActionPerformed, PRIORITY_MEDIUM, null, true, null, false);
finishMenu("/file/import/importOther");
finishMenu("/file/import");

View File

@@ -2799,6 +2799,99 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
}
public void importShape(final SWF swf, boolean noFill) {
ViewMessages.showMessageDialog(MainPanel.this, translate("message.info.importShapes"), translate("message.info"), JOptionPane.INFORMATION_MESSAGE, Configuration.showImportShapeInfo);
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get()));
chooser.setDialogTitle(translate("import.select.directory"));
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath();
File shapesDir = new File(Path.combine(selFile, ShapeExportSettings.EXPORT_FOLDER_NAME));
ShapeImporter shapeImporter = new ShapeImporter();
SvgImporter svgImporter = new SvgImporter();
final long timeBefore = System.currentTimeMillis();
new CancellableWorker<Void>() {
private int count = 0;
@Override
public Void doInBackground() throws Exception {
try {
Map<Integer, CharacterTag> characters = swf.getCharacters();
List<String> extensions = Arrays.asList("svg", "png", "jpg", "jpeg", "gif", "bmp");
for (int characterId : characters.keySet()) {
CharacterTag tag = characters.get(characterId);
if (tag instanceof ShapeTag) {
ShapeTag shapeTag = (ShapeTag) tag;
List<File> existingFilesForImageTag = new ArrayList<>();
for (String ext : extensions) {
File sourceFile = new File(Path.combine(shapesDir.getPath(), "" + characterId + "." + ext));
if (sourceFile.exists()) {
existingFilesForImageTag.add(sourceFile);
}
}
if (existingFilesForImageTag.isEmpty()) {
continue;
}
if (existingFilesForImageTag.size() > 1) {
Logger.getLogger(MainPanel.class.getName()).log(Level.WARNING, "Multiple matching files for shape tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForImageTag.get(0).getName()});
}
File sourceFile = existingFilesForImageTag.get(0);
try {
if (sourceFile.getAbsolutePath().toLowerCase().endsWith(".svg")) {
svgImporter.importSvg(shapeTag, Helper.readTextFile(sourceFile.getAbsolutePath()), !noFill);
} else {
shapeImporter.importImage(shapeTag, Helper.readFile(sourceFile.getAbsolutePath()), 0, !noFill);
}
count++;
} catch (IOException ex) {
Logger.getLogger(MainPanel.class.getName()).log(Level.WARNING, "Cannot import shape " + characterId + " from file " + sourceFile.getName(), ex);
}
if (Thread.currentThread().isInterrupted()) {
break;
}
}
}
swf.clearImageCache();
swf.clearShapeCache();
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error during import", ex);
ViewMessages.showMessageDialog(null, translate("error.import") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage());
}
return null;
}
@Override
protected void onStart() {
Main.startWork(translate("work.importing") + "...", this);
}
@Override
protected void done() {
Main.stopWork();
long timeAfter = System.currentTimeMillis();
final long timeMs = timeAfter - timeBefore;
View.execInEventDispatch(() -> {
refreshTree(swf);
setStatus(translate("import.finishedin").replace("%time%", Helper.formatTimeSec(timeMs)));
ViewMessages.showMessageDialog(MainPanel.this, translate("import.shape.result").replace("%count%", Integer.toString(count)));
if (count != 0) {
reload(true);
}
});
}
}.execute();
}
}
public void importImage(final SWF swf) {
ViewMessages.showMessageDialog(MainPanel.this, translate("message.info.importImages"), translate("message.info"), JOptionPane.INFORMATION_MESSAGE, Configuration.showImportImageInfo);
JFileChooser chooser = new JFileChooser();

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -608,3 +608,6 @@ config.description.maxCachedTime = Maximum time in milliseconds before item (whi
config.name.airLibLocation = 6) AIR library path (airglobal.swc)
config.description.airLibLocation = Location of airglobal.swc AIR library. It can be used mostly for AS3 compilation.
config.name.showImportShapeInfo = Show information before importing shapes
config.description.showImportShapeInfo = Displays some info about how importing shapes works after clicking Import shapes in the menu.

View File

@@ -595,3 +595,6 @@ config.description.maxCachedTime = Maxim\u00e1ln\u00ed \u010das v milisekund\u00
config.name.airLibLocation = 6) Cesta ke knihovn\u011b AIR (airglobal.swc)
config.description.airLibLocation = Um\u00edst\u011bn\u00ed knihovny AIR s n\u00e1zvem "airglobal.swc". M\u016f\u017ee b\u00fdt pou\u017eitou zejm\u00e9na pro AS3 kompilaci.
config.name.showImportShapeInfo = Zobrazit informaci p\u0159ed importem tvar\u016f
config.description.showImportShapeInfo = Zobraz\u00ed n\u011bjak\u00e9 informace o tom jak import tvar\u016f funguje po kliku na import tvar\u016f v menu.

View File

@@ -960,3 +960,12 @@ button.freeze = Freeze (Do not animate subsprites)
library = Library:
message.airpath.lib.notset = AirGlobal (.SWC) not found. Please configure its path in Advanced Settings / Paths (6).
message.action.airglobal.title = AirGlobal library needed
menu.file.import.shape = Import shapes
menu.file.import.shapeNoFill = Import shapes - update bounds
message.info.importShapes = During importing shapes, you need to select a FOLDER.\r\n \
The folder must contain "shapes" subfolder and filenames inside must match existing shapes in current selected SWF.\r\n \
The best way to get the structure right is to export shapes in current SWF file first.
import.shape.result = %count% shapes imported.

View File

@@ -453,7 +453,7 @@ message.confirm.experimental.function = Tato funkce je EXPERIMENT\u00c1LN\u00cd.
message.confirm.donotshowagain = P\u0159\u00ed\u0161t\u011b nezobrazovat
menu.import = Import
menu.file.import.text = Import textu
menu.file.import.text = Importovat text
import.select.directory = Vyberte adres\u00e1\u0159 pro import
error.text.import = Chyba b\u011bhem importu textu. Chcete pokra\u010dovat?
@@ -569,7 +569,7 @@ text.align.translatex.increase = Zv\u00fd\u0161it TranslateX
selectPreviousTag = Vybrat p\u0159edchoz\u00ed tag
selectNextTag = Vybrat dal\u0161\u00ed tag
button.ignoreAll = Ignorovat V\u0161e
menu.file.import.symbolClass = Import Symbol-Class
menu.file.import.symbolClass = Importovat Symbol-Class
text.toggleCase = P\u0159epnout mal\u00e1/velk\u00e1
#after version 5.0.2
@@ -814,7 +814,7 @@ message.info.importScripts = B\u011bhem importu skript\u016f mus\u00edte vybrat
message.info.importTexts = B\u011bhem importu text\u016f mus\u00edte vybrat SLO\u017dKU.\r\n \
Slo\u017eka mus\u00ed obsahovat podslo\u017eku "texts" a n\u00e1zvy soubor\u016f v n\u00ed mus\u00ed souhlasit s existuj\u00edc\u00edmi texty v pr\u00e1v\u011b vybran\u00e9m SWF.\r\n \
Nejlep\u0161\u00ed zp\u016fsob jak m\u00edt tuto strukturu spr\u00e1vn\u011b je nejprve exportovat texty v aktu\u00e1ln\u00edm SWF souboru.
Nejlep\u0161\u00ed zp\u016fsob jak m\u00edt tuto strukturu spr\u00e1vn\u011b je nejprve exportovat texty v aktu\u00e1ln\u00edm SWF souboru.
message.info.importSymbolClass = B\u011bhem importu Symbol-Class mus\u00edte vybrat SLO\u017dKU obsahuj\u00edc\u00ed soubor "%file%".\r\n \
To je stejn\u00fd n\u00e1zev jako se pou\u017e\u00edv\u00e1 p\u0159i exportu.
@@ -902,7 +902,7 @@ menu.file.import.image = Importovat obr\u00e1zky
message.info.importImages = B\u011bhem importu text\u016f mus\u00edte vybrat SLO\u017dKU.\r\n \
Slo\u017eka mus\u00ed obsahovat podslo\u017eku "images" a n\u00e1zvy soubor\u016f v n\u00ed mus\u00ed souhlasit s existuj\u00edc\u00edmi obr\u00e1zky v pr\u00e1v\u011b vybran\u00e9m SWF.\r\n \
Nejlep\u0161\u00ed zp\u016fsob jak m\u00edt tuto strukturu spr\u00e1vn\u011b je nejprve exportovat obr\u00e1zky v aktu\u00e1ln\u00edm SWF souboru.
Nejlep\u0161\u00ed zp\u016fsob jak m\u00edt tuto strukturu spr\u00e1vn\u011b je nejprve exportovat obr\u00e1zky v aktu\u00e1ln\u00edm SWF souboru.
work.importing = Importov\u00e1n\u00ed
@@ -932,3 +932,12 @@ button.freeze = Zmrazit (Neanimovat podsprity)
library = Knihovna:
message.airpath.lib.notset = AirGlobal (.SWC) nenalezen. Pros\u00edm nastavte cestu k n\u011bmu v Pokro\u010dil\u00e1 nastaven\u00ed / Cesty (6).
message.action.airglobal.title = Vy\u017eadov\u00e1na knihovna AirGlobal
menu.file.import.shape = Importovat tvary
menu.file.import.shapeNoFill = Importovat tvary - aktualizovat hranice
message.info.importShapes = B\u011bhem importu tvar\u016f mus\u00edte vybrat SLO\u017dKU.\r\n \
Slo\u017eka mus\u00ed obsahovat podslo\u017eku "shapes" a n\u00e1zvy soubor\u016f v n\u00ed mus\u00ed souhlasit s existuj\u00edc\u00edmi tvary v pr\u00e1v\u011b vybran\u00e9m SWF.\r\n \
Nejlep\u0161\u00ed zp\u016fsob jak m\u00edt tuto strukturu spr\u00e1vn\u011b je nejprve exportovat tvary v aktu\u00e1ln\u00edm SWF souboru.
import.shape.result = %count% tvar\u016f importov\u00e1no.

View File

@@ -159,6 +159,10 @@ public class TagTreeContextMenu extends JPopupMenu {
private JMenuItem importImagesMenuItem;
private JMenuItem importShapesMenuItem;
private JMenuItem importShapesNoFillMenuItem;
private JMenuItem importSymbolClassMenuItem;
private JMenuItem closeMenuItem;
@@ -332,6 +336,16 @@ public class TagTreeContextMenu extends JPopupMenu {
importImagesMenuItem.addActionListener(this::importImagesActionPerformed);
importImagesMenuItem.setIcon(View.getIcon("importimage16"));
add(importImagesMenuItem);
importShapesMenuItem = new JMenuItem(mainPanel.translate("menu.file.import.shape"));
importShapesMenuItem.addActionListener(this::importShapesActionPerformed);
importShapesMenuItem.setIcon(View.getIcon("importshape16"));
add(importShapesMenuItem);
importShapesNoFillMenuItem = new JMenuItem(mainPanel.translate("menu.file.import.shapeNoFill"));
importShapesNoFillMenuItem.addActionListener(this::importShapesNoFillActionPerformed);
importShapesNoFillMenuItem.setIcon(View.getIcon("importshape16"));
add(importShapesNoFillMenuItem);
importSymbolClassMenuItem = new JMenuItem(mainPanel.translate("menu.file.import.symbolClass"));
importSymbolClassMenuItem.addActionListener(this::importSymbolClassActionPerformed);
@@ -2975,6 +2989,16 @@ public class TagTreeContextMenu extends JPopupMenu {
SWF swf = getTree().getCurrentTreeItem().getSwf();
mainPanel.importImage(swf);
}
public void importShapesActionPerformed(ActionEvent evt) {
SWF swf = getTree().getCurrentTreeItem().getSwf();
mainPanel.importShape(swf, false);
}
public void importShapesNoFillActionPerformed(ActionEvent evt) {
SWF swf = getTree().getCurrentTreeItem().getSwf();
mainPanel.importShape(swf, true);
}
public void importSymbolClassActionPerformed(ActionEvent evt) {
SWF swf = getTree().getCurrentTreeItem().getSwf();