Added FLA export - show export time

Fixed #2136 FLA export - optimized Shape fixer speed, repeated shape on timeline not exported twice
This commit is contained in:
Jindra Petřík
2023-12-30 18:06:08 +01:00
parent bd82522f16
commit 4ce90c776b
6 changed files with 271 additions and 141 deletions
+3
View File
@@ -26,6 +26,7 @@ All notable changes to this project will be documented in this file.
- ExportAssets tag - show first item as description in the tree when there is only single item - ExportAssets tag - show first item as description in the tree when there is only single item
- [#2134] FLA Export - split main timeline into scenes when DefineSceneAndFrameLabelData tag is present - [#2134] FLA Export - split main timeline into scenes when DefineSceneAndFrameLabelData tag is present
- [#2132] Show and export streamed sound (SoundStreamHead/SoundStreamBlock) in frame ranges - [#2132] Show and export streamed sound (SoundStreamHead/SoundStreamBlock) in frame ranges
- FLA export - show export time
### Fixed ### Fixed
- [#2021], [#2000] Caret position in editors when using tabs and / or unicode - [#2021], [#2000] Caret position in editors when using tabs and / or unicode
@@ -66,6 +67,7 @@ All notable changes to this project will be documented in this file.
- [#2133] Linux/Mac - ffdec.sh not correctly parsing java build number on javas without it - [#2133] Linux/Mac - ffdec.sh not correctly parsing java build number on javas without it
- [#2135] FLA Export - framescripts handling when addFrameScript uses Multinames instead of QNames - [#2135] FLA Export - framescripts handling when addFrameScript uses Multinames instead of QNames
- [#1194] FLA Export - stream sound export - [#1194] FLA Export - stream sound export
- [#2136] FLA export - optimized Shape fixer speed, repeated shape on timeline not exported twice
### Changed ### Changed
- [#2120] Exported assets no longer take names from assigned classes if there is more than 1 assigned class - [#2120] Exported assets no longer take names from assigned classes if there is more than 1 assigned class
@@ -3339,6 +3341,7 @@ Major version of SWF to XML export changed to 2.
[#2133]: https://www.free-decompiler.com/flash/issues/2133 [#2133]: https://www.free-decompiler.com/flash/issues/2133
[#2135]: https://www.free-decompiler.com/flash/issues/2135 [#2135]: https://www.free-decompiler.com/flash/issues/2135
[#1194]: https://www.free-decompiler.com/flash/issues/1194 [#1194]: https://www.free-decompiler.com/flash/issues/1194
[#2136]: https://www.free-decompiler.com/flash/issues/2136
[#2120]: https://www.free-decompiler.com/flash/issues/2120 [#2120]: https://www.free-decompiler.com/flash/issues/2120
[#1130]: https://www.free-decompiler.com/flash/issues/1130 [#1130]: https://www.free-decompiler.com/flash/issues/1130
[#1220]: https://www.free-decompiler.com/flash/issues/1220 [#1220]: https://www.free-decompiler.com/flash/issues/1220
@@ -17,10 +17,6 @@
package com.jpexs.decompiler.flash.math; package com.jpexs.decompiler.flash.math;
import com.jpexs.helpers.Reference; import com.jpexs.helpers.Reference;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.io.Serializable; import java.io.Serializable;
@@ -38,10 +34,21 @@ import java.util.Stack;
*/ */
public class BezierEdge implements Serializable { public class BezierEdge implements Serializable {
public List<Point2D> points = new ArrayList<>(); public List<Point2D> points = new ArrayList<>(3);
private List<Point2D> revPoints = new ArrayList<>();
private int hash;
private int revHash;
private Rectangle2D bbox;
private boolean empty;
public BezierEdge(List<Point2D> points) { public BezierEdge(List<Point2D> points) {
this.points = points; this.points = points;
calcParams();
} }
@Override @Override
@@ -50,24 +57,20 @@ public class BezierEdge implements Serializable {
} }
public boolean isEmpty() { public boolean isEmpty() {
Point2D p1 = getBeginPoint(); return empty;
for (int i = 1; i < points.size(); i++) {
if (!points.get(i).equals(p1)) {
return false;
}
}
return true;
} }
public BezierEdge(double x0, double y0, double x1, double y1) { public BezierEdge(double x0, double y0, double x1, double y1) {
points.add(new Point2D.Double(x0, y0)); points.add(new Point2D.Double(x0, y0));
points.add(new Point2D.Double(x1, y1)); points.add(new Point2D.Double(x1, y1));
calcParams();
} }
public BezierEdge(double x0, double y0, double cx, double cy, double x1, double y1) { public BezierEdge(double x0, double y0, double cx, double cy, double x1, double y1) {
points.add(new Point2D.Double(x0, y0)); points.add(new Point2D.Double(x0, y0));
points.add(new Point2D.Double(cx, cy)); points.add(new Point2D.Double(cx, cy));
points.add(new Point2D.Double(x1, y1)); points.add(new Point2D.Double(x1, y1));
calcParams();
} }
public Point2D getBeginPoint() { public Point2D getBeginPoint() {
@@ -80,10 +83,12 @@ public class BezierEdge implements Serializable {
public void setBeginPoint(Point2D p) { public void setBeginPoint(Point2D p) {
points.set(0, p); points.set(0, p);
calcParams();
} }
public void setEndPoint(Point2D p) { public void setEndPoint(Point2D p) {
points.set(points.size() - 1, p); points.set(points.size() - 1, p);
calcParams();
} }
public Point2D pointAt(double t) { public Point2D pointAt(double t) {
@@ -102,14 +107,12 @@ public class BezierEdge implements Serializable {
return new Point2D.Double(x, y); return new Point2D.Double(x, y);
} }
public Rectangle2D bbox() { private void calcParams() {
double minX = Double.MAX_VALUE; double minX = Double.MAX_VALUE;
double minY = Double.MAX_VALUE; double minY = Double.MAX_VALUE;
double maxX = -Double.MAX_VALUE; double maxX = -Double.MAX_VALUE;
double maxY = -Double.MAX_VALUE; double maxY = -Double.MAX_VALUE;
//System.err.println("calculating bbox");
for (Point2D p : points) { for (Point2D p : points) {
//System.err.println(" point " + p);
if (p.getX() < minX) { if (p.getX() < minX) {
minX = p.getX(); minX = p.getX();
} }
@@ -124,11 +127,29 @@ public class BezierEdge implements Serializable {
} }
} }
Rectangle2D b = new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
/*System.err.println(" bbox = "+b); this.bbox = new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
System.err.println(" maxx = "+maxX); this.hash = points.hashCode();
System.err.println(" maxy = "+maxY);*/
return b; revPoints = new ArrayList<>();
for (int i = points.size() - 1; i >= 0; i--) {
revPoints.add(points.get(i));
}
this.revHash = revPoints.hashCode();
empty = true;
Point2D p1 = getBeginPoint();
for (int i = 1; i < points.size(); i++) {
if (!points.get(i).equals(p1)) {
empty = false;
break;
}
}
}
public Rectangle2D bbox() {
return bbox;
} }
private final double MIN_SIZE = 0.5; private final double MIN_SIZE = 0.5;
@@ -166,6 +187,9 @@ public class BezierEdge implements Serializable {
} }
public List<Point2D> getIntersections(BezierEdge b2) { public List<Point2D> getIntersections(BezierEdge b2) {
if (!Intersections.rectIntersection(bbox, b2.bbox)) {
return new ArrayList<>();
}
if (points.size() == 2) { if (points.size() == 2) {
if (b2.points.size() == 2) { if (b2.points.size() == 2) {
return Intersections.intersectLineLine(points.get(0), points.get(1), b2.points.get(0), b2.points.get(1), true); return Intersections.intersectLineLine(points.get(0), points.get(1), b2.points.get(0), b2.points.get(1), true);
@@ -375,10 +399,6 @@ public class BezierEdge implements Serializable {
} }
public BezierEdge reverse() { public BezierEdge reverse() {
List<Point2D> revPoints = new ArrayList<>();
for (int i = points.size() - 1; i >= 0; i--) {
revPoints.add(points.get(i));
}
return new BezierEdge(revPoints); return new BezierEdge(revPoints);
} }
@@ -389,6 +409,7 @@ public class BezierEdge implements Serializable {
Math.round(this.points.get(i).getY()) Math.round(this.points.get(i).getY())
)); ));
} }
calcParams();
} }
public void roundHalf() { public void roundHalf() {
@@ -398,12 +419,13 @@ public class BezierEdge implements Serializable {
Math.round(this.points.get(i).getY() * 2.0) / 2.0 Math.round(this.points.get(i).getY() * 2.0) / 2.0
)); ));
} }
calcParams();
} }
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 7; int hash = 7;
hash = 41 * hash + Objects.hashCode(this.points); hash = 41 * hash + this.hash;
return hash; return hash;
} }
@@ -419,9 +441,27 @@ public class BezierEdge implements Serializable {
return false; return false;
} }
final BezierEdge other = (BezierEdge) obj; final BezierEdge other = (BezierEdge) obj;
if (other.hash != hash) {
return false;
}
return Objects.equals(this.points, other.points); return Objects.equals(this.points, other.points);
} }
public boolean equalsReverse(BezierEdge other) {
if (hash != other.revHash) {
return false;
}
if (other.points.size() != points.size()) {
return false;
}
for (int i = 0; i < points.size(); i++) {
if (!points.get(i).equals(other.points.get(points.size() - 1 - i))) {
return false;
}
}
return true;
}
public static void main(String[] args) { public static void main(String[] args) {
List<Double> t1 = new ArrayList<>(); List<Double> t1 = new ArrayList<>();
List<Double> t2 = new ArrayList<>(); List<Double> t2 = new ArrayList<>();
@@ -17,6 +17,7 @@
package com.jpexs.decompiler.flash.math; package com.jpexs.decompiler.flash.math;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -165,6 +166,47 @@ public class Intersections {
return intersectPolylinePolyline(a, b); return intersectPolylinePolyline(a, b);
} }
public static boolean rectIntersection(Rectangle2D r1, Rectangle2D r2) {
double xmin = Math.max(r1.getX(), r2.getX());
double xmax1 = r1.getX() + r1.getWidth();
double xmax2 = r2.getX() + r2.getWidth();
double xmax = Math.min(xmax1, xmax2);
if (Double.compare(xmax, xmin) >= 0) {
double ymin = Math.max(r1.getY(), r2.getY());
double ymax1 = r1.getY() + r1.getHeight();
double ymax2 = r2.getY() + r2.getHeight();
double ymax = Math.min(ymax1, ymax2);
if (Double.compare(ymax, ymin) >= 0) {
return true;
}
}
return false;
}
public static Rectangle2D getBBox(Point2D ...points) {
double minX = Double.MAX_VALUE;
double minY = Double.MAX_VALUE;
double maxX = -Double.MAX_VALUE;
double maxY = -Double.MAX_VALUE;
for (Point2D p : points) {
if (p.getX() < minX) {
minX = p.getX();
}
if (p.getX() > maxX) {
maxX = p.getX();
}
if (p.getY() < minY) {
minY = p.getY();
}
if (p.getY() > maxY) {
maxY = p.getY();
}
}
return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
}
public static List<Point2D> intersectBezier2Bezier2(Point2D a1, Point2D a2, Point2D a3, Point2D b1, Point2D b2, Point2D b3) { public static List<Point2D> intersectBezier2Bezier2(Point2D a1, Point2D a2, Point2D a3, Point2D b1, Point2D b2, Point2D b3) {
Point2D pa; Point2D pa;
Point2D pb; Point2D pb;
@@ -1846,13 +1846,21 @@ public class XFLConverter {
int characterId = character.getCharacterId(); int characterId = character.getCharacterId();
if ((character instanceof ShapeTag) && (nonLibraryShapes.contains(characterId))) { if ((character instanceof ShapeTag) && (nonLibraryShapes.contains(characterId))) {
ShapeTag shape = (ShapeTag) character; ShapeTag shape = (ShapeTag) character;
statusStack.pushStatus(character.toString());
convertShape(swf, characters, matrix, shape.getShapeNum(), shape.getShapes().shapeRecords, shape.getShapes().fillStyles, shape.getShapes().lineStyles, false, false, recCharWriter); convertShape(swf, characters, matrix, shape.getShapeNum(), shape.getShapes().shapeRecords, shape.getShapes().fillStyles, shape.getShapes().lineStyles, false, false, recCharWriter);
statusStack.popStatus();
} else if (character instanceof TextTag) { } else if (character instanceof TextTag) {
statusStack.pushStatus(character.toString());
convertText(null, (TextTag) character, matrix, filters, null, recCharWriter); convertText(null, (TextTag) character, matrix, filters, null, recCharWriter);
statusStack.popStatus();
} else if (character instanceof DefineVideoStreamTag) { } else if (character instanceof DefineVideoStreamTag) {
statusStack.pushStatus(character.toString());
convertVideoInstance(null, matrix, (DefineVideoStreamTag) character, null, recCharWriter); convertVideoInstance(null, matrix, (DefineVideoStreamTag) character, null, recCharWriter);
statusStack.popStatus();
} else if (character instanceof ImageTag) { } else if (character instanceof ImageTag) {
statusStack.pushStatus(character.toString());
convertImageInstance(null, matrix, (ImageTag) character, null, recCharWriter); convertImageInstance(null, matrix, (ImageTag) character, null, recCharWriter);
statusStack.popStatus();
} else { } else {
convertSymbolInstance(null, matrix, colorTransformAlpha, false, blendMode, filters, true, null, null, null, characters.get(rec.characterId), characters, tags, flaVersion, recCharWriter); convertSymbolInstance(null, matrix, colorTransformAlpha, false, blendMode, filters, true, null, null, null, characters.get(rec.characterId), characters, tags, flaVersion, recCharWriter);
} }
@@ -2718,9 +2726,16 @@ public class XFLConverter {
convertSymbolInstance(instanceName, standaloneShapeTweenerMatrix, colorTransForm, cacheAsBitmap, blendMode, filters, isVisible, backGroundColor, clipActions, metadata, standaloneShapeTweener, characters, tags, flaVersion, elementsWriter); convertSymbolInstance(instanceName, standaloneShapeTweenerMatrix, colorTransForm, cacheAsBitmap, blendMode, filters, isVisible, backGroundColor, clipActions, metadata, standaloneShapeTweener, characters, tags, flaVersion, elementsWriter);
standaloneShapeTweener = null; standaloneShapeTweener = null;
} else if ((character instanceof ShapeTag) && (nonLibraryShapes.contains(characterId))) { // || shapeTweener != null)) { } else if ((character instanceof ShapeTag) && (nonLibraryShapes.contains(characterId))) { // || shapeTweener != null)) {
ShapeTag shape = (ShapeTag) character; if (lastCharacter == character && Objects.equals(matrix, lastMatrix)) {
convertShape(swf, characters, matrix, shape.getShapeNum(), shape.getShapes().shapeRecords, shape.getShapes().fillStyles, shape.getShapes().lineStyles, false, false, elementsWriter); elementsWriter.writeCharactersRaw(lastElements);
} else {
ShapeTag shape = (ShapeTag) character;
statusStack.pushStatus(character.toString());
convertShape(swf, characters, matrix, shape.getShapeNum(), shape.getShapes().shapeRecords, shape.getShapes().fillStyles, shape.getShapes().lineStyles, false, false, elementsWriter);
statusStack.popStatus();
}
lastCharacter = character;
lastMatrix = matrix;
shapeTween = false; shapeTween = false;
shapeTweener = null; shapeTweener = null;
} else if (character != null) { } else if (character != null) {
@@ -186,9 +186,24 @@ public class ShapeFixer {
//------------------- detecting overlapping edges -------------------- //------------------- detecting overlapping edges --------------------
List<BezierPair> splittedPairs = new ArrayList<>(); List<BezierPair> splittedPairs = new ArrayList<>();
//long t1 = System.currentTimeMillis();
//int oldpct = 0;
loopi1: loopi1:
for (int i1 = 0; i1 < shapes.size(); i1++) { for (int i1 = 0; i1 < shapes.size(); i1++) {
layer = layers.get(i1); layer = layers.get(i1);
/*if (i1 % 10 == 0) {
int pct = i1 * 100 / shapes.size();
if (oldpct != pct) {
//System.err.println("pct: " + pct + "%");
if (pct == 10) {
long t2 = System.currentTimeMillis();
long dt = t2 - t1;
System.err.println("Time per 10%: " + Helper.formatTimeSec(dt));
}
}
oldpct = pct;
}*/
loopj1: loopj1:
for (int j1 = 0; j1 < shapes.get(i1).size(); j1++) { for (int j1 = 0; j1 < shapes.get(i1).size(); j1++) {
BezierEdge be1 = shapes.get(i1).get(j1); BezierEdge be1 = shapes.get(i1).get(j1);
@@ -222,7 +237,7 @@ public class ShapeFixer {
} }
//duplicated edge //duplicated edge
if (be1.equals(be2) || be1.equals(be2.reverse())) { if (be1.equals(be2) || be1.equalsReverse(be2)) {
shapes.get(i2).remove(j2); shapes.get(i2).remove(j2);
if (i1 == i2 && j1 > j2) { if (i1 == i2 && j1 > j2) {
j1--; j1--;
@@ -248,128 +263,136 @@ public class ShapeFixer {
} }
boolean isint = be1.intersects(be2, t1Ref, t2Ref, intPoints); boolean isint = be1.intersects(be2, t1Ref, t2Ref, intPoints);
if (DEBUG_PRINT) { if (!isint) {
//System.err.println(" " + isint); continue;
} }
if (!t1Ref.isEmpty()) { if (t1Ref.isEmpty()) {
continue;
}
if ((be1.getBeginPoint().equals(be2.getBeginPoint()) if ((be1.getBeginPoint().equals(be2.getBeginPoint())
|| be1.getBeginPoint().equals(be2.getEndPoint()) || be1.getBeginPoint().equals(be2.getEndPoint())
|| be1.getEndPoint().equals(be2.getBeginPoint()) || be1.getEndPoint().equals(be2.getBeginPoint())
|| be1.getEndPoint().equals(be2.getEndPoint())) && (t1Ref.size() == 1)) { || be1.getEndPoint().equals(be2.getEndPoint())) && (t1Ref.size() == 1)) {
continue;
}
if (t1Ref.size() == 2) {
if ((t1Ref.get(0) == 0 || t1Ref.get(0) == 1)
&& (t2Ref.get(0) == 0 || t2Ref.get(0) == 1)) {
continue; continue;
} }
}
if (DEBUG_PRINT) { if (DEBUG_PRINT) {
System.err.println("intersects " + be1.toSvg() + " " + be2.toSvg()); System.err.println("intersects " + be1.toSvg() + " " + be2.toSvg());
System.err.println(" fillstyle0: " + fillStyles0.get(i1) + " , " + fillStyles0.get(i2)); System.err.println(" fillstyle0: " + fillStyles0.get(i1) + " , " + fillStyles0.get(i2));
System.err.println(" fillstyle1: " + fillStyles1.get(i1) + " , " + fillStyles1.get(i2)); System.err.println(" fillstyle1: " + fillStyles1.get(i1) + " , " + fillStyles1.get(i2));
System.err.println(" linestyle: " + lineStyles.get(i1) + " , " + lineStyles.get(i2)); System.err.println(" linestyle: " + lineStyles.get(i1) + " , " + lineStyles.get(i2));
for (int n = 0; n < t1Ref.size(); n++) { for (int n = 0; n < t1Ref.size(); n++) {
System.err.println("- " + t1Ref.get(n) + " , " + t2Ref.get(n) + " : " + intPoints.get(n)); System.err.println("- " + t1Ref.get(n) + " , " + t2Ref.get(n) + " : " + intPoints.get(n));
}
} }
}
if ((t1Ref.size() == 2) && !((t1Ref.get(0) == 0 || t1Ref.get(0) == 1) if ((t1Ref.size() == 2) && !((t1Ref.get(0) == 0 || t1Ref.get(0) == 1)
&& (t2Ref.get(0) == 0 || t2Ref.get(0) == 1))) { && (t2Ref.get(0) == 0 || t2Ref.get(0) == 1))) {
t1Ref.add(0, t1Ref.remove(1)); t1Ref.add(0, t1Ref.remove(1));
t2Ref.add(0, t2Ref.remove(1)); t2Ref.add(0, t2Ref.remove(1));
intPoints.add(0, intPoints.remove(1)); intPoints.add(0, intPoints.remove(1));
} }
int splitPointIndex = 0; int splitPointIndex = 0;
if (intPoints.size() > 1) { if (intPoints.size() > 1) {
splitPointIndex = 1; splitPointIndex = 1;
} }
splittedPairs.add(pair); splittedPairs.add(pair);
Reference<BezierEdge> be1LRef = new Reference<>(null); Reference<BezierEdge> be1LRef = new Reference<>(null);
Reference<BezierEdge> be1RRef = new Reference<>(null); Reference<BezierEdge> be1RRef = new Reference<>(null);
be1.split(t1Ref.get(splitPointIndex), be1LRef, be1RRef); be1.split(t1Ref.get(splitPointIndex), be1LRef, be1RRef);
Reference<BezierEdge> be2LRef = new Reference<>(null); Reference<BezierEdge> be2LRef = new Reference<>(null);
Reference<BezierEdge> be2RRef = new Reference<>(null); Reference<BezierEdge> be2RRef = new Reference<>(null);
be2.split(t2Ref.get(splitPointIndex), be2LRef, be2RRef); be2.split(t2Ref.get(splitPointIndex), be2LRef, be2RRef);
BezierEdge be1L = be1LRef.getVal(); BezierEdge be1L = be1LRef.getVal();
BezierEdge be1R = be1RRef.getVal(); BezierEdge be1R = be1RRef.getVal();
BezierEdge be2L = be2LRef.getVal(); BezierEdge be2L = be2LRef.getVal();
BezierEdge be2R = be2RRef.getVal(); BezierEdge be2R = be2RRef.getVal();
Point2D intP = intPoints.get(splitPointIndex); Point2D intP = intPoints.get(splitPointIndex);
be1L.setEndPoint(intP); be1L.setEndPoint(intP);
be1R.setBeginPoint(intP); be1R.setBeginPoint(intP);
be2L.setEndPoint(intP); be2L.setEndPoint(intP);
be2R.setBeginPoint(intP); be2R.setBeginPoint(intP);
be1L.roundHalf(); be1L.roundHalf();
be1R.roundHalf(); be1R.roundHalf();
be2L.roundHalf(); be2L.roundHalf();
be2R.roundHalf(); be2R.roundHalf();
if (i1 == i2) { if (i1 == i2) {
if (j1 < j2) { if (j1 < j2) {
shapes.get(i1).remove(j2); shapes.get(i1).remove(j2);
shapes.get(i2).remove(j1); shapes.get(i2).remove(j1);
j2--; j2--;
} else {
shapes.get(i1).remove(j1);
shapes.get(i2).remove(j2);
j1--;
}
} else { } else {
shapes.get(i1).remove(j1); shapes.get(i1).remove(j1);
shapes.get(i2).remove(j2); shapes.get(i2).remove(j2);
j1--;
} }
int n1 = j1; } else {
int n2 = j2; shapes.get(i1).remove(j1);
shapes.get(i2).remove(j2);
if (!be1L.isEmpty()) {
shapes.get(i1).add(n1, be1L);
if (DEBUG_PRINT) {
System.err.println("added " + be1L.toSvg() + " to j1=" + n1);
}
if (i1 == i2 && n2 >= n1) {
n2++;
}
n1++;
}
if (!be1R.isEmpty()) {
shapes.get(i1).add(n1, be1R);
if (DEBUG_PRINT) {
System.err.println("added " + be1R.toSvg() + " to j1=" + n1);
}
if (i1 == i2 && n2 >= n1) {
n2++;
}
n1++;
}
if (!be2L.isEmpty()) {
shapes.get(i2).add(n2, be2L);
if (DEBUG_PRINT) {
System.err.println("added " + be2L.toSvg() + " to j2=" + n2);
}
n2++;
}
if (!be2R.isEmpty()) {
shapes.get(i2).add(n2, be2R);
if (DEBUG_PRINT) {
System.err.println("added " + be2R.toSvg() + " to j2=" + n2);
}
n2++;
}
j1--;
continue loopj1;
} }
int n1 = j1;
int n2 = j2;
if (!be1L.isEmpty()) {
shapes.get(i1).add(n1, be1L);
if (DEBUG_PRINT) {
System.err.println("added " + be1L.toSvg() + " to j1=" + n1);
}
if (i1 == i2 && n2 >= n1) {
n2++;
}
n1++;
}
if (!be1R.isEmpty()) {
shapes.get(i1).add(n1, be1R);
if (DEBUG_PRINT) {
System.err.println("added " + be1R.toSvg() + " to j1=" + n1);
}
if (i1 == i2 && n2 >= n1) {
n2++;
}
n1++;
}
if (!be2L.isEmpty()) {
shapes.get(i2).add(n2, be2L);
if (DEBUG_PRINT) {
System.err.println("added " + be2L.toSvg() + " to j2=" + n2);
}
n2++;
}
if (!be2R.isEmpty()) {
shapes.get(i2).add(n2, be2R);
if (DEBUG_PRINT) {
System.err.println("added " + be2R.toSvg() + " to j2=" + n2);
}
n2++;
}
j1--;
continue loopj1;
} }
} }
} }
@@ -3402,6 +3402,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
path += compressed ? ".fla" : ".xfl"; path += compressed ? ".fla" : ".xfl";
final FLAVersion selectedVersion = versions.get(compressed ? flaFilters.indexOf(selectedFilter) : xflFilters.indexOf(selectedFilter)); final FLAVersion selectedVersion = versions.get(compressed ? flaFilters.indexOf(selectedFilter) : xflFilters.indexOf(selectedFilter));
final File selfile = new File(path); final File selfile = new File(path);
long timeBefore = System.currentTimeMillis();
new CancellableWorker() { new CancellableWorker() {
@Override @Override
protected Void doInBackground() throws Exception { protected Void doInBackground() throws Exception {
@@ -3442,6 +3443,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
@Override @Override
protected void done() { protected void done() {
Main.stopWork();
long timeAfter = System.currentTimeMillis();
final long timeMs = timeAfter - timeBefore;
View.execInEventDispatch(() -> {
setStatus(translate("export.finishedin").replace("%time%", Helper.formatTimeSec(timeMs)));
});
if (Configuration.openFolderAfterFlaExport.get()) { if (Configuration.openFolderAfterFlaExport.get()) {
try { try {
Desktop.getDesktop().open(selfile.getAbsoluteFile().getParentFile()); Desktop.getDesktop().open(selfile.getAbsoluteFile().getParentFile());
@@ -3449,8 +3458,6 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);
} }
} }
Main.stopWork();
} }
}.execute(); }.execute();
} }