mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-24 21:40:46 +00:00
Replacing morphshape from start/end shape.
Fixed Display of morphshape end shape to be exactly at 65535 ratio
This commit is contained in:
+2
-1
@@ -13,7 +13,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- [#2105] GFX - Basic tag info
|
- [#2105] GFX - Basic tag info
|
||||||
- Context menu items to create new tags (shape, morphshape, sprite, image, movie, sound, binaryData) from files
|
- Context menu items to create new tags (shape, morphshape, sprite, image, movie, sound, binaryData) from files
|
||||||
and using font embed dialog for fonts
|
and using font embed dialog for fonts
|
||||||
- Replacing morphshapes (currently only same shape for start/end)
|
- Replacing morphshapes
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- [#1306], [#1768] Maximizing window on other than main monitor
|
- [#1306], [#1768] Maximizing window on other than main monitor
|
||||||
@@ -24,6 +24,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- [#2104] Empty texts import
|
- [#2104] Empty texts import
|
||||||
- Centered start playing triangle (Playing on demand)
|
- Centered start playing triangle (Playing on demand)
|
||||||
- miterLimitFactor is FIXED8 value in MORPHLINESTYLE2
|
- miterLimitFactor is FIXED8 value in MORPHLINESTYLE2
|
||||||
|
- Display of morphshape end shape to be exactly at 65535 ratio
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Basic tag info panel always visible even when nothing to display (to avoid flickering)
|
- Basic tag info panel always visible even when nothing to display (to avoid flickering)
|
||||||
|
|||||||
@@ -966,12 +966,7 @@ public final class Configuration {
|
|||||||
|
|
||||||
@ConfigurationDefaultBoolean(true)
|
@ConfigurationDefaultBoolean(true)
|
||||||
@ConfigurationCategory("ui")
|
@ConfigurationCategory("ui")
|
||||||
public static ConfigurationItem<Boolean> displayAs3PCodePanel = null;
|
public static ConfigurationItem<Boolean> displayAs3PCodePanel = null;
|
||||||
|
|
||||||
@ConfigurationDefaultBoolean(true)
|
|
||||||
@ConfigurationName("warning.replace.morphshape")
|
|
||||||
@ConfigurationCategory("ui")
|
|
||||||
public static ConfigurationItem<Boolean> warningReplaceMorphShape = null;
|
|
||||||
|
|
||||||
private enum OSId {
|
private enum OSId {
|
||||||
WINDOWS, OSX, UNIX
|
WINDOWS, OSX, UNIX
|
||||||
|
|||||||
@@ -45,9 +45,19 @@ public class CurvedEdge extends StraightEdge implements IEdge {
|
|||||||
return new CurvedEdge(toX, toY, controlX, controlY, fromX, fromY, lineStyleIdx, newFillStyleIdx);
|
return new CurvedEdge(toX, toY, controlX, controlY, fromX, fromY, lineStyleIdx, newFillStyleIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IEdge sameWithNewFillStyle(int newFillStyleIdx) {
|
||||||
|
return new CurvedEdge(fromX, fromY, controlX, controlY, toX, toY, lineStyleIdx, newFillStyleIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "curved[" + fromX / 20f + "," + fromY / 20f + " -> " + toX / 20f + "," + toY / 20f + " control:" + controlX / 20f + "," + controlY / 20f + "]";
|
return "curved[" + fromX / 20f + "," + fromY / 20f + " -> " + toX / 20f + "," + toY / 20f + " control:" + controlX / 20f + "," + controlY / 20f + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IEdge reverse() {
|
||||||
|
return new CurvedEdge(toX, toY, controlX, controlY, fromX, fromY, lineStyleIdx, getFillStyleIdx());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,4 +35,8 @@ public interface IEdge {
|
|||||||
public int getFillStyleIdx();
|
public int getFillStyleIdx();
|
||||||
|
|
||||||
public IEdge reverseWithNewFillStyle(int newFillStyleIdx);
|
public IEdge reverseWithNewFillStyle(int newFillStyleIdx);
|
||||||
|
|
||||||
|
public IEdge reverse();
|
||||||
|
|
||||||
|
public IEdge sameWithNewFillStyle(int newFillStyleIdx);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -64,10 +64,8 @@ public abstract class ShapeExporterBase implements IShapeExporter {
|
|||||||
private final ColorTransform colorTransform;
|
private final ColorTransform colorTransform;
|
||||||
|
|
||||||
private boolean canUseSmoothing = true;
|
private boolean canUseSmoothing = true;
|
||||||
|
|
||||||
protected int windingRule;
|
protected int windingRule;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ShapeExporterBase(int windingRule, int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform) {
|
public ShapeExporterBase(int windingRule, int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform) {
|
||||||
this.shape = shape;
|
this.shape = shape;
|
||||||
|
|||||||
@@ -83,4 +83,15 @@ public class StraightEdge implements IEdge {
|
|||||||
return "straight[" + fromX / 20f + "," + fromY / 20f + " -> " + toX / 20f + "," + toY / 20f + "]";
|
return "straight[" + fromX / 20f + "," + fromY / 20f + " -> " + toX / 20f + "," + toY / 20f + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IEdge sameWithNewFillStyle(int newFillStyleIdx) {
|
||||||
|
return new StraightEdge(fromX, fromY, toX, toY, lineStyleIdx, newFillStyleIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IEdge reverse() {
|
||||||
|
return new StraightEdge(toX, toY, fromX, fromY, lineStyleIdx, getFillStyleIdx());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+335
@@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2023 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.importers.morphshape;
|
||||||
|
|
||||||
|
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||||
|
import com.jpexs.decompiler.flash.math.BezierEdge;
|
||||||
|
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||||
|
import com.jpexs.decompiler.flash.types.FILLSTYLE;
|
||||||
|
import com.jpexs.decompiler.flash.types.LINESTYLE2;
|
||||||
|
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE;
|
||||||
|
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY;
|
||||||
|
import com.jpexs.decompiler.flash.types.MORPHLINESTYLE2;
|
||||||
|
import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY;
|
||||||
|
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||||
|
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
|
||||||
|
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
|
||||||
|
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||||
|
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
|
||||||
|
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||||
|
import com.jpexs.helpers.Helper;
|
||||||
|
import com.jpexs.helpers.Reference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author JPEXS
|
||||||
|
*/
|
||||||
|
public class MorphShapeGenerator {
|
||||||
|
|
||||||
|
public void generate(DefineMorphShape2Tag morphShape, ShapeTag startShape, ShapeTag endShape) throws StyleMismatchException {
|
||||||
|
ShapeForMorphExporter startExport = new ShapeForMorphExporter(startShape);
|
||||||
|
startExport.export();
|
||||||
|
ShapeForMorphExporter endExport = new ShapeForMorphExporter(endShape);
|
||||||
|
endExport.export();
|
||||||
|
|
||||||
|
List<List<BezierEdge>> startBeziers = new ArrayList<>();
|
||||||
|
List<List<BezierEdge>> endBeziers = new ArrayList<>();
|
||||||
|
List<FILLSTYLE> startFillStyles = new ArrayList<>();
|
||||||
|
List<Integer> startFillstyleIndices = new ArrayList<>();
|
||||||
|
List<LINESTYLE2> startLineStyles = new ArrayList<>();
|
||||||
|
List<Integer> startLineStyleIndices = new ArrayList<>();
|
||||||
|
|
||||||
|
List<FILLSTYLE> endFillStyles = new ArrayList<>();
|
||||||
|
List<LINESTYLE2> endLineStyles = new ArrayList<>();
|
||||||
|
|
||||||
|
Set<Integer> usedBs = new HashSet<>();
|
||||||
|
|
||||||
|
List<Integer> startShapeIndices = new ArrayList<>();
|
||||||
|
List<Integer> endShapeIndices = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int a = 0; a < startExport.shapes.size(); a++) {
|
||||||
|
double minDistance = Double.MAX_VALUE;
|
||||||
|
double minDistanceNoUsed = Double.MAX_VALUE;
|
||||||
|
int selectedB = -1;
|
||||||
|
int selectedBNoUsed = -1;
|
||||||
|
|
||||||
|
int startFillStyleIndex = startExport.fillStyleIndices.get(a);
|
||||||
|
FILLSTYLE startFillStyle = startFillStyleIndex == -1 ? null : startExport.fillStyles.get(startFillStyleIndex);
|
||||||
|
int startLineStyleIndex = startExport.lineStyleIndices.get(a);
|
||||||
|
LINESTYLE2 startLineStyle = startLineStyleIndex == -1 ? null : startExport.lineStyles.get(startLineStyleIndex);
|
||||||
|
|
||||||
|
for (int b = 0; b < endExport.shapes.size(); b++) {
|
||||||
|
int endFillStyleIndex = endExport.fillStyleIndices.get(b);
|
||||||
|
FILLSTYLE endFillStyle = endFillStyleIndex == -1 ? null : endExport.fillStyles.get(endFillStyleIndex);
|
||||||
|
int endLineStyleIndex = endExport.lineStyleIndices.get(b);
|
||||||
|
LINESTYLE2 endLineStyle = endLineStyleIndex == -1 ? null : endExport.lineStyles.get(endLineStyleIndex);
|
||||||
|
|
||||||
|
if (((endFillStyle == null && startFillStyle == null)
|
||||||
|
|| (startFillStyle != null
|
||||||
|
&& endFillStyle != null
|
||||||
|
&& startFillStyle.isCompatibleFillStyle(endFillStyle)))
|
||||||
|
&& ((endLineStyle == null && startLineStyle == null)
|
||||||
|
|| (startLineStyle != null
|
||||||
|
&& endLineStyle != null
|
||||||
|
&& startLineStyle.isCompatibleLineStyle(endLineStyle)))) {
|
||||||
|
double distance = startExport.centralPos.get(a).distance(endExport.centralPos.get(b));
|
||||||
|
if (distance < minDistance) {
|
||||||
|
minDistance = distance;
|
||||||
|
selectedB = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distance < minDistanceNoUsed && !usedBs.contains(b)) {
|
||||||
|
minDistanceNoUsed = distance;
|
||||||
|
selectedBNoUsed = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedB == -1) {
|
||||||
|
throw new StyleMismatchException();
|
||||||
|
}
|
||||||
|
if (selectedBNoUsed != -1) {
|
||||||
|
selectedB = selectedBNoUsed;
|
||||||
|
}
|
||||||
|
startShapeIndices.add(a);
|
||||||
|
endShapeIndices.add(selectedB);
|
||||||
|
usedBs.add(selectedB);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usedBs.size() < endExport.shapes.size()) {
|
||||||
|
for (int b = 0; b < endExport.shapes.size(); b++) {
|
||||||
|
if (!usedBs.contains(b)) {
|
||||||
|
|
||||||
|
double minDistance = Double.MAX_VALUE;
|
||||||
|
int selectedA = -1;
|
||||||
|
|
||||||
|
int endFillStyleIndex = endExport.fillStyleIndices.get(b);
|
||||||
|
FILLSTYLE endFillStyle = endFillStyleIndex == -1 ? null : endExport.fillStyles.get(endFillStyleIndex);
|
||||||
|
int endLineStyleIndex = endExport.lineStyleIndices.get(b);
|
||||||
|
LINESTYLE2 endLineStyle = endLineStyleIndex == -1 ? null : endExport.lineStyles.get(endLineStyleIndex);
|
||||||
|
|
||||||
|
for (int a = 0; a < startExport.shapes.size(); a++) {
|
||||||
|
int startFillStyleIndex = startExport.fillStyleIndices.get(a);
|
||||||
|
FILLSTYLE startFillStyle = startFillStyleIndex == -1 ? null : startExport.fillStyles.get(startFillStyleIndex);
|
||||||
|
int startLineStyleIndex = startExport.lineStyleIndices.get(a);
|
||||||
|
LINESTYLE2 startLineStyle = startLineStyleIndex == -1 ? null : startExport.lineStyles.get(startLineStyleIndex);
|
||||||
|
|
||||||
|
if (((endFillStyle == null && startFillStyle == null)
|
||||||
|
|| (startFillStyle != null
|
||||||
|
&& endFillStyle != null
|
||||||
|
&& startFillStyle.isCompatibleFillStyle(endFillStyle)))
|
||||||
|
&& ((endLineStyle == null && startLineStyle == null)
|
||||||
|
|| (startLineStyle != null
|
||||||
|
&& endLineStyle != null
|
||||||
|
&& startLineStyle.isCompatibleLineStyle(endLineStyle)))) {
|
||||||
|
double distance = startExport.centralPos.get(a).distance(endExport.centralPos.get(b));
|
||||||
|
if (distance < minDistance) {
|
||||||
|
minDistance = distance;
|
||||||
|
selectedA = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedA == -1) {
|
||||||
|
throw new StyleMismatchException();
|
||||||
|
}
|
||||||
|
|
||||||
|
startShapeIndices.add(selectedA);
|
||||||
|
endShapeIndices.add(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < startShapeIndices.size(); i++) {
|
||||||
|
int a = startShapeIndices.get(i);
|
||||||
|
int b = endShapeIndices.get(i);
|
||||||
|
|
||||||
|
List<BezierEdge> shapeStart = Helper.deepCopy(startExport.shapes.get(a));
|
||||||
|
split(shapeStart, startExport.pointsPosPercent.get(a), endExport.pointsPosPercent.get(b));
|
||||||
|
List<BezierEdge> shapeEnd = Helper.deepCopy(endExport.shapes.get(b));
|
||||||
|
split(shapeEnd, endExport.pointsPosPercent.get(b), startExport.pointsPosPercent.get(a));
|
||||||
|
|
||||||
|
startBeziers.add(shapeStart);
|
||||||
|
endBeziers.add(shapeEnd);
|
||||||
|
|
||||||
|
if (startExport.fillStyleIndices.get(a) != -1) {
|
||||||
|
startFillStyles.add(startExport.fillStyles.get(startExport.fillStyleIndices.get(a)));
|
||||||
|
}
|
||||||
|
startFillstyleIndices.add(startExport.fillStyleIndices.get(a));
|
||||||
|
if (startExport.lineStyleIndices.get(a) != -1) {
|
||||||
|
startLineStyles.add(startExport.lineStyles.get(startExport.lineStyleIndices.get(a)));
|
||||||
|
}
|
||||||
|
startLineStyleIndices.add(startExport.lineStyleIndices.get(a));
|
||||||
|
|
||||||
|
if (endExport.fillStyleIndices.get(b) != -1) {
|
||||||
|
endFillStyles.add(endExport.fillStyles.get(endExport.fillStyleIndices.get(b)));
|
||||||
|
}
|
||||||
|
if (endExport.lineStyleIndices.get(b) != -1) {
|
||||||
|
endLineStyles.add(endExport.lineStyles.get(endExport.lineStyleIndices.get(b)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List<SHAPERECORD> startRecords = new ArrayList<>();
|
||||||
|
List<SHAPERECORD> endRecords = new ArrayList<>();
|
||||||
|
|
||||||
|
MORPHFILLSTYLEARRAY morphFillStyleArray = new MORPHFILLSTYLEARRAY();
|
||||||
|
morphFillStyleArray.fillStyles = new MORPHFILLSTYLE[startFillStyles.size()];
|
||||||
|
|
||||||
|
MORPHLINESTYLEARRAY morphLineStyleArray = new MORPHLINESTYLEARRAY();
|
||||||
|
morphLineStyleArray.lineStyles2 = new MORPHLINESTYLE2[startLineStyles.size()];
|
||||||
|
|
||||||
|
for (int i = 0; i < startFillStyles.size(); i++) {
|
||||||
|
FILLSTYLE fsStart = startFillStyles.get(i);
|
||||||
|
FILLSTYLE fsEnd = endFillStyles.get(i);
|
||||||
|
MORPHFILLSTYLE morphFillStyle = fsStart.toMorphStyle(fsEnd);
|
||||||
|
if (morphFillStyle == null) {
|
||||||
|
throw new StyleMismatchException();
|
||||||
|
}
|
||||||
|
morphFillStyleArray.fillStyles[i] = morphFillStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < startLineStyles.size(); i++) {
|
||||||
|
LINESTYLE2 lsStart = startLineStyles.get(i);
|
||||||
|
LINESTYLE2 lsEnd = endLineStyles.get(i);
|
||||||
|
MORPHLINESTYLE2 morphLineStyle = lsStart.toMorphLineStyle2(lsEnd);
|
||||||
|
if (morphLineStyle == null) {
|
||||||
|
throw new StyleMismatchException();
|
||||||
|
}
|
||||||
|
morphLineStyleArray.lineStyles2[i] = morphLineStyle;
|
||||||
|
if (morphLineStyle.noHScaleFlag || morphLineStyle.noVScaleFlag) {
|
||||||
|
morphShape.usesNonScalingStrokes = true;
|
||||||
|
}
|
||||||
|
if (!morphLineStyle.noHScaleFlag && !morphLineStyle.noVScaleFlag) {
|
||||||
|
morphShape.usesScalingStrokes = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < startBeziers.size(); i++) {
|
||||||
|
List<BezierEdge> beList = startBeziers.get(i);
|
||||||
|
StyleChangeRecord scr = new StyleChangeRecord();
|
||||||
|
scr.stateFillStyle0 = true;
|
||||||
|
if (startFillstyleIndices.get(i) != -1) {
|
||||||
|
scr.fillStyle0 = startFillstyleIndices.get(i) + 1;
|
||||||
|
} else {
|
||||||
|
scr.fillStyle0 = 0;
|
||||||
|
}
|
||||||
|
scr.stateLineStyle = true;
|
||||||
|
if (startLineStyleIndices.get(i) != -1) {
|
||||||
|
scr.lineStyle = startLineStyleIndices.get(i) + 1;
|
||||||
|
} else {
|
||||||
|
scr.lineStyle = 0;
|
||||||
|
}
|
||||||
|
startRecords.add(scr);
|
||||||
|
|
||||||
|
BezierEdge firstBe = beList.get(0);
|
||||||
|
StyleChangeRecord scrMove = new StyleChangeRecord();
|
||||||
|
scrMove.stateMoveTo = true;
|
||||||
|
scrMove.moveDeltaX = (int) Math.round(firstBe.getBeginPoint().getX());
|
||||||
|
scrMove.moveDeltaY = (int) Math.round(firstBe.getBeginPoint().getY());
|
||||||
|
startRecords.add(scrMove);
|
||||||
|
|
||||||
|
for (BezierEdge be : beList) {
|
||||||
|
SHAPERECORD rec = bezierToRecord(be);
|
||||||
|
startRecords.add(rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startRecords.add(new EndShapeRecord());
|
||||||
|
|
||||||
|
for (int i = 0; i < endBeziers.size(); i++) {
|
||||||
|
List<BezierEdge> beList = endBeziers.get(i);
|
||||||
|
BezierEdge firstBe = beList.get(0);
|
||||||
|
StyleChangeRecord scrMove = new StyleChangeRecord();
|
||||||
|
scrMove.stateMoveTo = true;
|
||||||
|
scrMove.moveDeltaX = (int) Math.round(firstBe.getBeginPoint().getX());
|
||||||
|
scrMove.moveDeltaY = (int) Math.round(firstBe.getBeginPoint().getY());
|
||||||
|
endRecords.add(scrMove);
|
||||||
|
for (BezierEdge be : beList) {
|
||||||
|
SHAPERECORD rec = bezierToRecord(be);
|
||||||
|
endRecords.add(rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endRecords.add(new EndShapeRecord());
|
||||||
|
|
||||||
|
morphShape.morphFillStyles = morphFillStyleArray;
|
||||||
|
morphShape.morphLineStyles = morphLineStyleArray;
|
||||||
|
morphShape.startEdges = new SHAPE();
|
||||||
|
morphShape.startEdges.shapeRecords = startRecords;
|
||||||
|
morphShape.startEdges.numFillBits = SWFOutputStream.getNeededBitsU(morphFillStyleArray.fillStyles.length);
|
||||||
|
morphShape.startEdges.numLineBits = SWFOutputStream.getNeededBitsU(morphLineStyleArray.lineStyles2.length);
|
||||||
|
|
||||||
|
morphShape.endEdges = new SHAPE();
|
||||||
|
morphShape.endEdges.numFillBits = 0;
|
||||||
|
morphShape.endEdges.numLineBits = 0;
|
||||||
|
morphShape.endEdges.shapeRecords = endRecords;
|
||||||
|
|
||||||
|
morphShape.setModified(true);
|
||||||
|
morphShape.updateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void split(List<BezierEdge> shape, List<Double> originalPointsPosPercent, List<Double> newPointPosPercent) {
|
||||||
|
List<Double> pointPointsPercent = new ArrayList<>(originalPointsPosPercent);
|
||||||
|
|
||||||
|
int nppPos = 0;
|
||||||
|
for (int i = 0; i < shape.size() && nppPos < newPointPosPercent.size(); i++) {
|
||||||
|
BezierEdge be = shape.get(i);
|
||||||
|
double pointPosPct = pointPointsPercent.get(i);
|
||||||
|
double pointPosNextPct = pointPointsPercent.get(i + 1);
|
||||||
|
|
||||||
|
double pct = newPointPosPercent.get(nppPos);
|
||||||
|
if (pct > pointPosPct && pct < pointPosNextPct) {
|
||||||
|
double deltaPct = pointPosNextPct - pointPosPct;
|
||||||
|
double newPct = pct - pointPosPct;
|
||||||
|
double insidePct = newPct / deltaPct;
|
||||||
|
Reference<BezierEdge> leftRef = new Reference<>(null);
|
||||||
|
Reference<BezierEdge> rightRef = new Reference<>(null);
|
||||||
|
be.split(insidePct, leftRef, rightRef);
|
||||||
|
shape.remove(i);
|
||||||
|
shape.add(i, leftRef.getVal());
|
||||||
|
shape.add(i + 1, rightRef.getVal());
|
||||||
|
pointPointsPercent.add(i + 1, pct);
|
||||||
|
nppPos++;
|
||||||
|
} else if (pct == pointPosPct) {
|
||||||
|
nppPos++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SHAPERECORD bezierToRecord(BezierEdge be) {
|
||||||
|
if (be.points.size() == 2) {
|
||||||
|
StraightEdgeRecord ser = new StraightEdgeRecord();
|
||||||
|
ser.deltaX = (int) Math.round(be.points.get(1).getX() - be.points.get(0).getX());
|
||||||
|
ser.deltaY = (int) Math.round(be.points.get(1).getY() - be.points.get(0).getY());
|
||||||
|
ser.generalLineFlag = true;
|
||||||
|
ser.simplify();
|
||||||
|
return ser;
|
||||||
|
}
|
||||||
|
if (be.points.size() == 3) {
|
||||||
|
CurvedEdgeRecord cer = new CurvedEdgeRecord();
|
||||||
|
cer.controlDeltaX = (int) Math.round(be.points.get(1).getX() - be.points.get(0).getX());
|
||||||
|
cer.controlDeltaY = (int) Math.round(be.points.get(1).getY() - be.points.get(0).getY());
|
||||||
|
cer.anchorDeltaX = (int) Math.round(be.points.get(2).getX() - be.points.get(1).getX());
|
||||||
|
cer.anchorDeltaY = (int) Math.round(be.points.get(2).getY() - be.points.get(1).getY());
|
||||||
|
return cer;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+430
@@ -0,0 +1,430 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2023 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.importers.morphshape;
|
||||||
|
|
||||||
|
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||||
|
import com.jpexs.decompiler.flash.exporters.shape.ShapeExporterBase;
|
||||||
|
import com.jpexs.decompiler.flash.math.BezierEdge;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||||
|
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||||
|
import com.jpexs.decompiler.flash.types.FILLSTYLE;
|
||||||
|
import com.jpexs.decompiler.flash.types.FOCALGRADIENT;
|
||||||
|
import com.jpexs.decompiler.flash.types.GRADIENT;
|
||||||
|
import com.jpexs.decompiler.flash.types.GRADRECORD;
|
||||||
|
import com.jpexs.decompiler.flash.types.LINESTYLE2;
|
||||||
|
import com.jpexs.decompiler.flash.types.RGB;
|
||||||
|
import com.jpexs.decompiler.flash.types.RGBA;
|
||||||
|
import com.jpexs.helpers.Helper;
|
||||||
|
import com.jpexs.helpers.Reference;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author JPEXS
|
||||||
|
*/
|
||||||
|
public class ShapeForMorphExporter extends ShapeExporterBase {
|
||||||
|
|
||||||
|
public List<List<BezierEdge>> shapes = new ArrayList<>();
|
||||||
|
public List<Integer> fillStyleIndices = new ArrayList<>();
|
||||||
|
public List<Integer> lineStyleIndices = new ArrayList<>();
|
||||||
|
public List<List<Double>> pointsPosPercent = new ArrayList<>();
|
||||||
|
public List<Point2D.Double> centralPos = new ArrayList<>();
|
||||||
|
private final List<Point2D.Double> pointsSum = new ArrayList<>();
|
||||||
|
private final List<Integer> segmentCount = new ArrayList<>();
|
||||||
|
private final List<List<Double>> bezierLengths = new ArrayList<>();
|
||||||
|
|
||||||
|
private List<BezierEdge> currentShape = new ArrayList<>();
|
||||||
|
private List<Double> currentBezierLengths = new ArrayList<>();
|
||||||
|
private Point2D.Double currentPointsSum = new Point2D.Double();
|
||||||
|
private int currentSegmentCount = 0;
|
||||||
|
private int currentLineStyle = -1;
|
||||||
|
private int currentFillStyle = -1;
|
||||||
|
|
||||||
|
double currentShapeLen = 0;
|
||||||
|
|
||||||
|
public List<FILLSTYLE> fillStyles = new ArrayList<>();
|
||||||
|
public List<LINESTYLE2> lineStyles = new ArrayList<>();
|
||||||
|
|
||||||
|
private double lastX = 0;
|
||||||
|
private double lastY = 0;
|
||||||
|
|
||||||
|
public ShapeForMorphExporter(ShapeTag shape) {
|
||||||
|
super(ShapeTag.WIND_EVEN_ODD, shape.getShapeNum(), shape.getSwf(), shape.shapes, new ColorTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginShape() {
|
||||||
|
shapes = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endShape() {
|
||||||
|
endCurrent();
|
||||||
|
|
||||||
|
for (int i = 0; i < segmentCount.size(); i++) {
|
||||||
|
Point2D.Double center = new Point2D.Double();
|
||||||
|
center.x = pointsSum.get(i).x / (double) segmentCount.get(i);
|
||||||
|
center.y = pointsSum.get(i).y / (double) segmentCount.get(i);
|
||||||
|
centralPos.add(center);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < shapes.size(); i++) {
|
||||||
|
List<BezierEdge> shape = shapes.get(i);
|
||||||
|
List<Point2D> points = new ArrayList<>();
|
||||||
|
BezierEdge be = null;
|
||||||
|
for (int j = 0; j < shape.size(); j++) {
|
||||||
|
be = shape.get(j);
|
||||||
|
points.add(new Point2D.Double(
|
||||||
|
be.getBeginPoint().getX() - centralPos.get(i).getX(),
|
||||||
|
be.getBeginPoint().getY() - centralPos.get(i).getY()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
points.add(new Point2D.Double(
|
||||||
|
be.getEndPoint().getX() - centralPos.get(i).getX(),
|
||||||
|
be.getEndPoint().getY() - centralPos.get(i).getY()
|
||||||
|
));
|
||||||
|
|
||||||
|
double w = 0;
|
||||||
|
for (int j = 0; j < points.size(); j++) {
|
||||||
|
int secondPoint = j + 1 == points.size() ? 0 : j + 1;
|
||||||
|
double x = points.get(j).getX();
|
||||||
|
double xp1 = points.get(secondPoint).getX();
|
||||||
|
double y = points.get(j).getY();
|
||||||
|
double yp1 = points.get(secondPoint).getY();
|
||||||
|
|
||||||
|
if (y * yp1 < 0) {
|
||||||
|
double r = x + ((y * (xp1 - x)) / (y - yp1));
|
||||||
|
if (r > 0) {
|
||||||
|
if (y < 0) {
|
||||||
|
w = w + 1;
|
||||||
|
} else {
|
||||||
|
w = w - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((y == 0) && (x > 0)) {
|
||||||
|
if (yp1 > 0) {
|
||||||
|
w = w + .5;
|
||||||
|
} else {
|
||||||
|
w = w - .5;
|
||||||
|
}
|
||||||
|
} else if ((yp1 == 0) && (xp1 > 0)) {
|
||||||
|
if (y < 0) {
|
||||||
|
w = w + .5;
|
||||||
|
} else {
|
||||||
|
w = w - .5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w > 0) {
|
||||||
|
//clockwise
|
||||||
|
} else {
|
||||||
|
//counter clock wise
|
||||||
|
List<BezierEdge> newShape = new ArrayList<>();
|
||||||
|
List<Double> newBeLength = new ArrayList<>();
|
||||||
|
for (int j = shape.size() - 1; j >= 0; j--) {
|
||||||
|
newShape.add(shape.get(j).reverse());
|
||||||
|
newBeLength.add(bezierLengths.get(i).get(j));
|
||||||
|
}
|
||||||
|
shape.clear();
|
||||||
|
shape.addAll(newShape);
|
||||||
|
bezierLengths.get(i).clear();
|
||||||
|
bezierLengths.get(i).addAll(newBeLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < shapes.size(); i++) {
|
||||||
|
List<BezierEdge> shape = shapes.get(i);
|
||||||
|
//closed shape
|
||||||
|
if (shape.get(0).getBeginPoint().equals(shape.get(shape.size() - 1).getEndPoint())) {
|
||||||
|
|
||||||
|
//Find most top left point
|
||||||
|
double minX = Double.MAX_VALUE;
|
||||||
|
double minY = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
for (int j = 0; j < shape.size(); j++) {
|
||||||
|
if (shape.get(j).getBeginPoint().getX() < minX) {
|
||||||
|
minX = shape.get(j).getBeginPoint().getX();
|
||||||
|
}
|
||||||
|
if (shape.get(j).getBeginPoint().getY() < minY) {
|
||||||
|
minY = shape.get(j).getBeginPoint().getY();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double minDist = Double.MAX_VALUE;
|
||||||
|
int minPos = -1;
|
||||||
|
for (int j = 0; j < shape.size(); j++) {
|
||||||
|
double dist = shape.get(j).getBeginPoint().distance(minX, minY);
|
||||||
|
if (dist < minDist) {
|
||||||
|
minDist = dist;
|
||||||
|
minPos = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (minPos > -1) {
|
||||||
|
//Rearange shape to start with the top left point
|
||||||
|
for (int j = 0; j < minPos; j++) {
|
||||||
|
shape.add(shape.remove(0));
|
||||||
|
bezierLengths.get(i).add(bezierLengths.get(i).remove(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (List<Double> pp : bezierLengths) {
|
||||||
|
List<Double> ppPercent = new ArrayList<>();
|
||||||
|
double len = 0.0;
|
||||||
|
for (double bLength : pp) {
|
||||||
|
len += bLength;
|
||||||
|
}
|
||||||
|
double pos = 0;
|
||||||
|
for (double bLength : pp) {
|
||||||
|
double pct = roundPct(pos / len);
|
||||||
|
pos += bLength;
|
||||||
|
ppPercent.add(pct);
|
||||||
|
}
|
||||||
|
ppPercent.add(1.0);
|
||||||
|
pointsPosPercent.add(ppPercent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginAliasedFills() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginFills() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endFills() {
|
||||||
|
endCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginLines() {
|
||||||
|
currentShape = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endLines(boolean close) {
|
||||||
|
endCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginFill(RGB color) {
|
||||||
|
endCurrent();
|
||||||
|
currentShape = new ArrayList<>();
|
||||||
|
currentFillStyle = fillStyles.size();
|
||||||
|
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.SOLID;
|
||||||
|
fillStyle.color = color;
|
||||||
|
fillStyles.add(fillStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) {
|
||||||
|
endCurrent();
|
||||||
|
currentShape = new ArrayList<>();
|
||||||
|
currentFillStyle = fillStyles.size();
|
||||||
|
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||||
|
fillStyle.fillStyleType = type;
|
||||||
|
fillStyle.gradient = focalPointRatio == 0 ? new FOCALGRADIENT() : new GRADIENT();
|
||||||
|
fillStyle.gradient.gradientRecords = Helper.deepCopy(gradientRecords);
|
||||||
|
fillStyle.gradientMatrix = matrix.toMATRIX();
|
||||||
|
fillStyle.gradient.spreadMode = spreadMethod;
|
||||||
|
fillStyle.gradient.interpolationMode = interpolationMethod;
|
||||||
|
if (focalPointRatio != 0) {
|
||||||
|
((FOCALGRADIENT) fillStyle.gradient).focalPoint = focalPointRatio;
|
||||||
|
}
|
||||||
|
fillStyles.add(fillStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beginBitmapFill(int bitmapId, Matrix matrix, boolean repeat, boolean smooth, ColorTransform colorTransform) {
|
||||||
|
endCurrent();
|
||||||
|
currentShape = new ArrayList<>();
|
||||||
|
currentFillStyle = fillStyles.size();
|
||||||
|
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||||
|
if (repeat) {
|
||||||
|
if (smooth) {
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.REPEATING_BITMAP;
|
||||||
|
} else {
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (smooth) {
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.CLIPPED_BITMAP;
|
||||||
|
} else {
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fillStyle.bitmapMatrix = matrix.toMATRIX();
|
||||||
|
fillStyle.bitmapId = bitmapId;
|
||||||
|
fillStyles.add(fillStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endFill() {
|
||||||
|
endCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void endCurrent() {
|
||||||
|
if (currentShape != null && !currentShape.isEmpty()) {
|
||||||
|
shapes.add(currentShape);
|
||||||
|
bezierLengths.add(currentBezierLengths);
|
||||||
|
pointsSum.add(currentPointsSum);
|
||||||
|
segmentCount.add(currentSegmentCount);
|
||||||
|
fillStyleIndices.add(currentFillStyle);
|
||||||
|
lineStyleIndices.add(currentLineStyle);
|
||||||
|
}
|
||||||
|
currentShapeLen = 0;
|
||||||
|
currentShape = new ArrayList<>();
|
||||||
|
currentBezierLengths = new ArrayList<>();
|
||||||
|
currentPointsSum = new Point2D.Double();
|
||||||
|
currentSegmentCount = 0;
|
||||||
|
currentFillStyle = -1;
|
||||||
|
currentLineStyle = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, float miterLimit) {
|
||||||
|
endCurrent();
|
||||||
|
currentLineStyle = lineStyles.size();
|
||||||
|
LINESTYLE2 lineStyle = new LINESTYLE2();
|
||||||
|
lineStyle.width = (int) thickness;
|
||||||
|
lineStyle.color = new RGBA(color);
|
||||||
|
lineStyle.pixelHintingFlag = pixelHinting;
|
||||||
|
switch (scaleMode) {
|
||||||
|
case "NONE":
|
||||||
|
lineStyle.noHScaleFlag = true;
|
||||||
|
lineStyle.noVScaleFlag = true;
|
||||||
|
break;
|
||||||
|
case "VERTICAL":
|
||||||
|
lineStyle.noHScaleFlag = true;
|
||||||
|
break;
|
||||||
|
case "HORIZONTAL":
|
||||||
|
lineStyle.noVScaleFlag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lineStyle.startCapStyle = startCaps;
|
||||||
|
lineStyle.endCapStyle = endCaps;
|
||||||
|
lineStyle.joinStyle = joints;
|
||||||
|
lineStyle.miterLimitFactor = miterLimit;
|
||||||
|
lineStyles.add(lineStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) {
|
||||||
|
LINESTYLE2 lineStyle = lineStyles.get(lineStyles.size() - 1);
|
||||||
|
lineStyle.hasFillFlag = true;
|
||||||
|
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||||
|
fillStyle.fillStyleType = type;
|
||||||
|
fillStyle.gradient = focalPointRatio == 0 ? new FOCALGRADIENT() : new GRADIENT();
|
||||||
|
fillStyle.gradient.gradientRecords = Helper.deepCopy(gradientRecords);
|
||||||
|
fillStyle.gradientMatrix = matrix.toMATRIX();
|
||||||
|
fillStyle.gradient.spreadMode = spreadMethod;
|
||||||
|
fillStyle.gradient.interpolationMode = interpolationMethod;
|
||||||
|
if (focalPointRatio != 0) {
|
||||||
|
((FOCALGRADIENT) fillStyle.gradient).focalPoint = focalPointRatio;
|
||||||
|
}
|
||||||
|
lineStyle.fillType = fillStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lineBitmapStyle(int bitmapId, Matrix matrix, boolean repeat, boolean smooth, ColorTransform colorTransform) {
|
||||||
|
LINESTYLE2 lineStyle = lineStyles.get(lineStyles.size() - 1);
|
||||||
|
lineStyle.hasFillFlag = true;
|
||||||
|
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||||
|
if (repeat) {
|
||||||
|
if (smooth) {
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.REPEATING_BITMAP;
|
||||||
|
} else {
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (smooth) {
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.CLIPPED_BITMAP;
|
||||||
|
} else {
|
||||||
|
fillStyle.fillStyleType = FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fillStyle.bitmapMatrix = matrix.toMATRIX();
|
||||||
|
fillStyle.bitmapId = bitmapId;
|
||||||
|
lineStyle.fillType = fillStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveTo(double x, double y) {
|
||||||
|
int backupFillStyle = currentFillStyle;
|
||||||
|
int backupLineStyle = currentLineStyle;
|
||||||
|
endCurrent();
|
||||||
|
currentFillStyle = backupFillStyle;
|
||||||
|
currentLineStyle = backupLineStyle;
|
||||||
|
lastX = (int) x;
|
||||||
|
lastY = (int) y;
|
||||||
|
//currentPointsPos.add(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lineTo(double x, double y) {
|
||||||
|
if (x == lastX && y == lastY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BezierEdge be = new BezierEdge(lastX, lastY, x, y);
|
||||||
|
|
||||||
|
currentPointsSum.x += x; // - lastX;
|
||||||
|
currentPointsSum.y += y; // - lastY;
|
||||||
|
|
||||||
|
currentShape.add(be);
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
currentBezierLengths.add(be.length());
|
||||||
|
currentShapeLen += be.length();
|
||||||
|
|
||||||
|
currentSegmentCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void curveTo(double controlX, double controlY, double anchorX, double anchorY) {
|
||||||
|
|
||||||
|
if (anchorX == lastX && anchorY == lastY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BezierEdge be = new BezierEdge(lastX, lastY, controlX, controlY, anchorX, anchorY);
|
||||||
|
|
||||||
|
currentShape.add(be);
|
||||||
|
|
||||||
|
currentPointsSum.x += anchorX; // - lastX;
|
||||||
|
currentPointsSum.y += anchorY; // - lastY;
|
||||||
|
|
||||||
|
lastX = anchorX;
|
||||||
|
lastY = anchorY;
|
||||||
|
currentBezierLengths.add(be.length());
|
||||||
|
currentShapeLen += be.length();
|
||||||
|
|
||||||
|
currentSegmentCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double roundPct(double pct) {
|
||||||
|
double precision = 1000000d;
|
||||||
|
return Math.round(pct * precision) / precision;
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2023 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.importers.morphshape;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author JPEXS
|
||||||
|
*/
|
||||||
|
public class StyleMismatchException extends Exception {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -226,6 +226,11 @@ public class SvgImporter {
|
|||||||
transform = Matrix.getScaleInstance(ratioX, ratioY);
|
transform = Matrix.getScaleInstance(ratioX, ratioY);
|
||||||
transform.translate(origXmin / SWF.unitDivisor / ratioX, origYmin / SWF.unitDivisor / ratioY);
|
transform.translate(origXmin / SWF.unitDivisor / ratioX, origYmin / SWF.unitDivisor / ratioY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transform = transform.preConcatenate(Matrix.getTranslateInstance(-viewBox.x, -viewBox.y));
|
||||||
|
if (viewBox.height != 0 && viewBox.width != 0) {
|
||||||
|
transform = transform.preConcatenate(Matrix.getScaleInstance(width / viewBox.width, height / viewBox.height));
|
||||||
|
}
|
||||||
|
|
||||||
processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style, morphShape);
|
processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style, morphShape);
|
||||||
} catch (SAXException | IOException | ParserConfigurationException ex) {
|
} catch (SAXException | IOException | ParserConfigurationException ex) {
|
||||||
|
|||||||
@@ -19,14 +19,16 @@ package com.jpexs.decompiler.flash.math;
|
|||||||
import com.jpexs.helpers.Reference;
|
import com.jpexs.helpers.Reference;
|
||||||
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.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author JPEXS
|
* @author JPEXS
|
||||||
*/
|
*/
|
||||||
public class BezierEdge {
|
public class BezierEdge implements Serializable {
|
||||||
|
|
||||||
public List<Point2D> points = new ArrayList<>();
|
public List<Point2D> points = new ArrayList<>();
|
||||||
|
|
||||||
@@ -45,6 +47,14 @@ public class BezierEdge {
|
|||||||
points.add(new Point2D.Double(x1, y1));
|
points.add(new Point2D.Double(x1, y1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Point2D getBeginPoint() {
|
||||||
|
return points.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D getEndPoint() {
|
||||||
|
return points.get(points.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
public Point2D pointAt(double t) {
|
public Point2D pointAt(double t) {
|
||||||
if (points.size() == 2) {
|
if (points.size() == 2) {
|
||||||
double x = (1 - t) * points.get(0).getX() + t * points.get(1).getX();
|
double x = (1 - t) * points.get(0).getX() + t * points.get(1).getX();
|
||||||
@@ -189,6 +199,30 @@ public class BezierEdge {
|
|||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public double length() {
|
||||||
|
double distance = 0;
|
||||||
|
double epsilon = 1;
|
||||||
|
|
||||||
|
Stack<BezierEdge> parts = new Stack<BezierEdge>();
|
||||||
|
parts.push(this);
|
||||||
|
|
||||||
|
while (!parts.isEmpty()) {
|
||||||
|
BezierEdge curve = parts.pop();
|
||||||
|
double d = curve.points.get(0).distance(curve.points.get(curve.points.size() - 1));
|
||||||
|
if (d < epsilon) {
|
||||||
|
distance += d;
|
||||||
|
} else {
|
||||||
|
Reference<BezierEdge> leftRef = new Reference<>(null);
|
||||||
|
Reference<BezierEdge> rightRef = new Reference<>(null);
|
||||||
|
curve.split(0.5, leftRef, rightRef);
|
||||||
|
parts.add(leftRef.getVal());
|
||||||
|
parts.add(rightRef.getVal());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -207,6 +241,14 @@ public class BezierEdge {
|
|||||||
left.setVal(new BezierEdge(leftPoints));
|
left.setVal(new BezierEdge(leftPoints));
|
||||||
right.setVal(new BezierEdge(rightPoints));
|
right.setVal(new BezierEdge(rightPoints));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
List<Double> t1 = new ArrayList<>();
|
List<Double> t1 = new ArrayList<>();
|
||||||
@@ -245,6 +287,10 @@ public class BezierEdge {
|
|||||||
);
|
);
|
||||||
|
|
||||||
System.out.println("Intersection point: " + c);
|
System.out.println("Intersection point: " + c);
|
||||||
|
|
||||||
|
BezierEdge be = new BezierEdge(0, 0, 100, 50, 0, 100);
|
||||||
|
|
||||||
|
System.out.println("be5.dist: " + be.length());
|
||||||
|
|
||||||
//Rectangle2D out = new Rectangle2D.Double();
|
//Rectangle2D out = new Rectangle2D.Double();
|
||||||
//rectIntersection(new Rectangle2D.Double(0,0,50,50), new Rectangle2D.Double(0,50,50,50), out);
|
//rectIntersection(new Rectangle2D.Double(0,0,50,50), new Rectangle2D.Double(0,50,50,50), out);
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject {
|
|||||||
|
|
||||||
public abstract int getShapeNum();
|
public abstract int getShapeNum();
|
||||||
|
|
||||||
public SHAPEWITHSTYLE getShapes() {
|
public synchronized SHAPEWITHSTYLE getShapes() {
|
||||||
if (shapes == null && shapeData != null) {
|
if (shapes == null && shapeData != null) {
|
||||||
try {
|
try {
|
||||||
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
|
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
|
||||||
|
|||||||
@@ -151,6 +151,30 @@ public class FILLSTYLE implements NeedsCharacters, FieldChangeObserver, Serializ
|
|||||||
gradient = g;
|
gradient = g;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompatibleFillStyle(FILLSTYLE otherFillStyle) {
|
||||||
|
if (fillStyleType != otherFillStyle.fillStyleType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (fillStyleType) {
|
||||||
|
case CLIPPED_BITMAP:
|
||||||
|
case NON_SMOOTHED_CLIPPED_BITMAP:
|
||||||
|
case NON_SMOOTHED_REPEATING_BITMAP:
|
||||||
|
case REPEATING_BITMAP:
|
||||||
|
if (bitmapId != otherFillStyle.bitmapId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LINEAR_GRADIENT:
|
||||||
|
case RADIAL_GRADIENT:
|
||||||
|
case FOCAL_RADIAL_GRADIENT:
|
||||||
|
if (!gradient.isCompatibleGradient(otherFillStyle.gradient)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MORPHFILLSTYLE toMorphStyle() {
|
public MORPHFILLSTYLE toMorphStyle() {
|
||||||
@@ -171,4 +195,30 @@ public class FILLSTYLE implements NeedsCharacters, FieldChangeObserver, Serializ
|
|||||||
|
|
||||||
return morphFillStyle;
|
return morphFillStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MORPHFILLSTYLE toMorphStyle(FILLSTYLE endFillStyle) {
|
||||||
|
if (!isCompatibleFillStyle(endFillStyle)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MORPHFILLSTYLE morphFillStyle = new MORPHFILLSTYLE();
|
||||||
|
morphFillStyle.bitmapId = bitmapId;
|
||||||
|
if (bitmapMatrix != null) {
|
||||||
|
morphFillStyle.startBitmapMatrix = new MATRIX(bitmapMatrix);
|
||||||
|
}
|
||||||
|
if (endFillStyle.bitmapMatrix != null) {
|
||||||
|
morphFillStyle.endBitmapMatrix = new MATRIX(endFillStyle.bitmapMatrix);
|
||||||
|
}
|
||||||
|
if (color != null) {
|
||||||
|
morphFillStyle.startColor = new RGBA(color);
|
||||||
|
}
|
||||||
|
if (endFillStyle.color != null) {
|
||||||
|
morphFillStyle.endColor = new RGBA(endFillStyle.color);
|
||||||
|
}
|
||||||
|
morphFillStyle.fillStyleType = fillStyleType;
|
||||||
|
if (gradient != null) {
|
||||||
|
morphFillStyle.gradient = gradient.toMorphGradient(endFillStyle.gradient);
|
||||||
|
}
|
||||||
|
|
||||||
|
return morphFillStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,20 @@ public class GRADIENT implements Serializable {
|
|||||||
public static final int INTERPOLATION_RESERVED2 = 3;
|
public static final int INTERPOLATION_RESERVED2 = 3;
|
||||||
|
|
||||||
@SWFArray(value = "record")
|
@SWFArray(value = "record")
|
||||||
public GRADRECORD[] gradientRecords = new GRADRECORD[0];
|
public GRADRECORD[] gradientRecords = new GRADRECORD[0];
|
||||||
|
|
||||||
|
public boolean isCompatibleGradient(GRADIENT otherGradient) {
|
||||||
|
if (interpolationMode != otherGradient.interpolationMode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (spreadMode != otherGradient.spreadMode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (gradientRecords.length != otherGradient.gradientRecords.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public MORPHGRADIENT toMorphGradient() {
|
public MORPHGRADIENT toMorphGradient() {
|
||||||
MORPHGRADIENT morphGradient = new MORPHGRADIENT();
|
MORPHGRADIENT morphGradient = new MORPHGRADIENT();
|
||||||
@@ -73,4 +86,18 @@ public class GRADIENT implements Serializable {
|
|||||||
}
|
}
|
||||||
return morphGradient;
|
return morphGradient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MORPHGRADIENT toMorphGradient(GRADIENT endGradient) {
|
||||||
|
if (!isCompatibleGradient(endGradient)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MORPHGRADIENT morphGradient = new MORPHGRADIENT();
|
||||||
|
morphGradient.interPolationMode = interpolationMode;
|
||||||
|
morphGradient.spreadMode = spreadMode;
|
||||||
|
morphGradient.gradientRecords = new MORPHGRADRECORD[gradientRecords.length];
|
||||||
|
for (int i = 0; i < gradientRecords.length; i++) {
|
||||||
|
morphGradient.gradientRecords[i] = gradientRecords[i].toMorphGradRecord();
|
||||||
|
}
|
||||||
|
return morphGradient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,4 +46,13 @@ public class GRADRECORD implements Serializable {
|
|||||||
morphGradRecord.endRatio = ratio;
|
morphGradRecord.endRatio = ratio;
|
||||||
return morphGradRecord;
|
return morphGradRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MORPHGRADRECORD toMorphGradRecord(GRADRECORD endGradRecord) {
|
||||||
|
MORPHGRADRECORD morphGradRecord = new MORPHGRADRECORD();
|
||||||
|
morphGradRecord.startColor = new RGBA(color);
|
||||||
|
morphGradRecord.endColor = new RGBA(endGradRecord.color);
|
||||||
|
morphGradRecord.startRatio = ratio;
|
||||||
|
morphGradRecord.endRatio = endGradRecord.ratio;
|
||||||
|
return morphGradRecord;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,44 @@ public class LINESTYLE2 implements NeedsCharacters, Serializable, ILINESTYLE {
|
|||||||
@Override
|
@Override
|
||||||
public void setWidth(int width) {
|
public void setWidth(int width) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompatibleLineStyle(LINESTYLE2 otherLineStyle) {
|
||||||
|
if (startCapStyle != otherLineStyle.startCapStyle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (endCapStyle != otherLineStyle.endCapStyle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joinStyle != otherLineStyle.joinStyle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasFillFlag != otherLineStyle.hasFillFlag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noVScaleFlag != otherLineStyle.noVScaleFlag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pixelHintingFlag != otherLineStyle.pixelHintingFlag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (noClose != otherLineStyle.noClose) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (miterLimitFactor != otherLineStyle.miterLimitFactor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasFillFlag) {
|
||||||
|
if (!fillType.isCompatibleFillStyle(otherLineStyle.fillType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MORPHLINESTYLE2 toMorphLineStyle2() {
|
public MORPHLINESTYLE2 toMorphLineStyle2() {
|
||||||
@@ -165,4 +203,33 @@ public class LINESTYLE2 implements NeedsCharacters, Serializable, ILINESTYLE {
|
|||||||
}
|
}
|
||||||
return morphLineStyle2;
|
return morphLineStyle2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MORPHLINESTYLE2 toMorphLineStyle2(LINESTYLE2 endLineStyle) {
|
||||||
|
if (!isCompatibleLineStyle(endLineStyle)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MORPHLINESTYLE2 morphLineStyle2 = new MORPHLINESTYLE2();
|
||||||
|
morphLineStyle2.startWidth = width;
|
||||||
|
morphLineStyle2.endWidth = endLineStyle.width;
|
||||||
|
morphLineStyle2.startCapStyle = startCapStyle;
|
||||||
|
morphLineStyle2.joinStyle = joinStyle;
|
||||||
|
morphLineStyle2.hasFillFlag = hasFillFlag;
|
||||||
|
morphLineStyle2.noHScaleFlag = noHScaleFlag;
|
||||||
|
morphLineStyle2.noVScaleFlag = noVScaleFlag;
|
||||||
|
morphLineStyle2.pixelHintingFlag = pixelHintingFlag;
|
||||||
|
morphLineStyle2.noClose = noClose;
|
||||||
|
morphLineStyle2.endCapStyle = endCapStyle;
|
||||||
|
morphLineStyle2.miterLimitFactor = miterLimitFactor;
|
||||||
|
if (color != null) {
|
||||||
|
morphLineStyle2.startColor = new RGBA(color);
|
||||||
|
}
|
||||||
|
if (endLineStyle.color != null) {
|
||||||
|
morphLineStyle2.endColor = new RGBA(endLineStyle.color);
|
||||||
|
}
|
||||||
|
if (hasFillFlag) {
|
||||||
|
morphLineStyle2.fillType = fillType.toMorphStyle(endLineStyle.fillType);
|
||||||
|
}
|
||||||
|
return morphLineStyle2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ import com.jpexs.decompiler.flash.importers.SpriteImporter;
|
|||||||
import com.jpexs.decompiler.flash.importers.SwfXmlImporter;
|
import com.jpexs.decompiler.flash.importers.SwfXmlImporter;
|
||||||
import com.jpexs.decompiler.flash.importers.SymbolClassImporter;
|
import com.jpexs.decompiler.flash.importers.SymbolClassImporter;
|
||||||
import com.jpexs.decompiler.flash.importers.TextImporter;
|
import com.jpexs.decompiler.flash.importers.TextImporter;
|
||||||
|
import com.jpexs.decompiler.flash.importers.morphshape.MorphShapeGenerator;
|
||||||
|
import com.jpexs.decompiler.flash.importers.morphshape.StyleMismatchException;
|
||||||
import com.jpexs.decompiler.flash.importers.svg.SvgImporter;
|
import com.jpexs.decompiler.flash.importers.svg.SvgImporter;
|
||||||
import com.jpexs.decompiler.flash.search.ABCSearchResult;
|
import com.jpexs.decompiler.flash.search.ABCSearchResult;
|
||||||
import com.jpexs.decompiler.flash.search.ActionSearchResult;
|
import com.jpexs.decompiler.flash.search.ActionSearchResult;
|
||||||
@@ -142,7 +144,10 @@ import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
|
|||||||
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
|
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
|
||||||
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
|
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
|
||||||
import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
|
import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag;
|
||||||
import com.jpexs.decompiler.flash.tags.DefineShape2Tag;
|
import com.jpexs.decompiler.flash.tags.DefineShape2Tag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.DefineShape4Tag;
|
||||||
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
||||||
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
|
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
|
||||||
import com.jpexs.decompiler.flash.tags.DoActionTag;
|
import com.jpexs.decompiler.flash.tags.DoActionTag;
|
||||||
@@ -371,8 +376,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
private static final int DETAILCARDTAGINFO = 0;
|
private static final int DETAILCARDTAGINFO = 0;
|
||||||
|
|
||||||
private static final int DETAILCARDEMPTYPANEL = -1;
|
private static final int DETAILCARDEMPTYPANEL = -1;
|
||||||
|
|
||||||
private static final int DETAILCARDDEBUGSTACKFRAME = 2;
|
private static final int DETAILCARDDEBUGSTACKFRAME = 2;
|
||||||
|
|
||||||
private static final String SPLIT_PANE1 = "SPLITPANE1";
|
private static final String SPLIT_PANE1 = "SPLITPANE1";
|
||||||
|
|
||||||
@@ -413,7 +418,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
private final PreviewPanel dumpPreviewPanel;
|
private final PreviewPanel dumpPreviewPanel;
|
||||||
|
|
||||||
private final TagInfoPanel tagInfoPanel;
|
private final TagInfoPanel tagInfoPanel;
|
||||||
|
|
||||||
private final DebugStackPanel debugStackPanel;
|
private final DebugStackPanel debugStackPanel;
|
||||||
|
|
||||||
private TreePanelMode treePanelMode;
|
private TreePanelMode treePanelMode;
|
||||||
@@ -1028,7 +1033,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
public String translate(String key) {
|
public String translate(String key) {
|
||||||
return mainFrame.translate(key);
|
return mainFrame.translate(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MainPanel(MainFrame mainFrame, MainFrameMenu mainMenu, FlashPlayerPanel flashPanel, FlashPlayerPanel previewFlashPanel) {
|
public MainPanel(MainFrame mainFrame, MainFrameMenu mainMenu, FlashPlayerPanel flashPanel, FlashPlayerPanel previewFlashPanel) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -1050,9 +1055,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
whitePanel.setBackground(Color.white);
|
whitePanel.setBackground(Color.white);
|
||||||
}
|
}
|
||||||
detailPanel.add(whitePanel, DETAILCARDEMPTYPANEL);
|
detailPanel.add(whitePanel, DETAILCARDEMPTYPANEL);
|
||||||
*/
|
*/
|
||||||
tagInfoPanel = new TagInfoPanel(this);
|
tagInfoPanel = new TagInfoPanel(this);
|
||||||
|
|
||||||
debugStackPanel = new DebugStackPanel();
|
debugStackPanel = new DebugStackPanel();
|
||||||
Main.getDebugHandler().addBreakListener(new DebuggerHandler.BreakListener() {
|
Main.getDebugHandler().addBreakListener(new DebuggerHandler.BreakListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -1061,8 +1066,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
showDetail(DETAILCARDDEBUGSTACKFRAME);
|
showDetail(DETAILCARDDEBUGSTACKFRAME);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1071,14 +1076,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
showDetail(DETAILCARDEMPTYPANEL);
|
showDetail(DETAILCARDEMPTYPANEL);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Main.getDebugHandler().addConnectionListener(new DebuggerHandler.ConnectionListener() {
|
Main.getDebugHandler().addConnectionListener(new DebuggerHandler.ConnectionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void connected() {
|
public void connected() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1087,11 +1092,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
reload(true);
|
reload(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName());
|
UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName());
|
||||||
tagTree = new TagTree(null, this);
|
tagTree = new TagTree(null, this);
|
||||||
tagTree.addTreeSelectionListener(this);
|
tagTree.addTreeSelectionListener(this);
|
||||||
@@ -1454,7 +1459,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
public ABCPanel getABCPanel() {
|
public ABCPanel getABCPanel() {
|
||||||
if (abcPanel == null) {
|
if (abcPanel == null) {
|
||||||
abcPanel = new ABCPanel(this);
|
abcPanel = new ABCPanel(this);
|
||||||
displayPanel.add(abcPanel, CARDACTIONSCRIPT3PANEL);
|
displayPanel.add(abcPanel, CARDACTIONSCRIPT3PANEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return abcPanel;
|
return abcPanel;
|
||||||
@@ -1854,19 +1859,19 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
if (constants.getMultiname(multiNameIndex).name_index > 0) {
|
if (constants.getMultiname(multiNameIndex).name_index > 0) {
|
||||||
oldName = constants.getString(constants.getMultiname(multiNameIndex).name_index);
|
oldName = constants.getString(constants.getMultiname(multiNameIndex).name_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
String scriptName = abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().toString();
|
String scriptName = abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().toString();
|
||||||
|
|
||||||
String newName = ViewMessages.showInputDialog(this, translate("rename.enternew"), oldName);
|
String newName = ViewMessages.showInputDialog(this, translate("rename.enternew"), oldName);
|
||||||
if (newName != null) {
|
if (newName != null) {
|
||||||
if (!oldName.equals(newName)) {
|
if (!oldName.equals(newName)) {
|
||||||
|
|
||||||
if (oldName.equals(abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().className)) {
|
if (oldName.equals(abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().className)) {
|
||||||
scriptName = abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().packageStr.add(newName, "").toPrintableString(true);
|
scriptName = abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().packageStr.add(newName, "").toPrintableString(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String fScriptName = scriptName;
|
final String fScriptName = scriptName;
|
||||||
|
|
||||||
int mulCount = 0;
|
int mulCount = 0;
|
||||||
for (ABCContainerTag cnt : abcList) {
|
for (ABCContainerTag cnt : abcList) {
|
||||||
ABC abc = cnt.getABC();
|
ABC abc = cnt.getABC();
|
||||||
@@ -1941,17 +1946,17 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
|
|
||||||
Set<Openable> usedOpenables = new HashSet<>();
|
Set<Openable> usedOpenables = new HashSet<>();
|
||||||
Set<OpenableList> usedOpenableLists = new HashSet<>();
|
Set<OpenableList> usedOpenableLists = new HashSet<>();
|
||||||
|
|
||||||
Map<OpenableList, Map<String, Integer>> usedSwfIdsInBundles = new HashMap<>();
|
Map<OpenableList, Map<String, Integer>> usedSwfIdsInBundles = new HashMap<>();
|
||||||
|
|
||||||
for (TreeItem d : sel) {
|
for (TreeItem d : sel) {
|
||||||
Openable selectedNodeOpenable = d.getOpenable();
|
Openable selectedNodeOpenable = d.getOpenable();
|
||||||
usedOpenables.add(selectedNodeOpenable);
|
usedOpenables.add(selectedNodeOpenable);
|
||||||
|
|
||||||
OpenableList list = selectedNodeOpenable.getOpenableList();
|
OpenableList list = selectedNodeOpenable.getOpenableList();
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
usedOpenableLists.add(list);
|
usedOpenableLists.add(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Integer> usedSwfsIds = new HashMap<>();
|
Map<String, Integer> usedSwfsIds = new HashMap<>();
|
||||||
@@ -2074,13 +2079,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
|
|
||||||
String selFile2;
|
String selFile2;
|
||||||
if (usedOpenables.size() > 1) {
|
if (usedOpenables.size() > 1) {
|
||||||
if (usedOpenableLists.size() > 1 && openable.getOpenableList() != null && openable.getOpenableList().isBundle()) {
|
if (usedOpenableLists.size() > 1 && openable.getOpenableList() != null && openable.getOpenableList().isBundle()) {
|
||||||
if (!usedSwfIdsInBundles.containsKey(openable.getOpenableList())) {
|
if (!usedSwfIdsInBundles.containsKey(openable.getOpenableList())) {
|
||||||
usedSwfIdsInBundles.put(openable.getOpenableList(), new HashMap<>());
|
usedSwfIdsInBundles.put(openable.getOpenableList(), new HashMap<>());
|
||||||
}
|
}
|
||||||
selFile2 = selFile + File.separator + openable.getOpenableList().name + File.separator + Helper.getNextId(openable.getTitleOrShortFileName(), usedSwfIdsInBundles.get(openable.getOpenableList()));
|
selFile2 = selFile + File.separator + openable.getOpenableList().name + File.separator + Helper.getNextId(openable.getTitleOrShortFileName(), usedSwfIdsInBundles.get(openable.getOpenableList()));
|
||||||
} else {
|
} else {
|
||||||
selFile2 = selFile + File.separator + Helper.getNextId(openable.getTitleOrShortFileName(), usedSwfsIds);
|
selFile2 = selFile + File.separator + Helper.getNextId(openable.getTitleOrShortFileName(), usedSwfsIds);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -2547,16 +2552,16 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.gotoInstrLine(line);
|
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.gotoInstrLine(line);
|
||||||
} else {
|
} else {
|
||||||
abcPanel.decompiledTextArea.gotoLine(line);
|
abcPanel.decompiledTextArea.gotoLine(line);
|
||||||
}
|
}
|
||||||
scrollPosStorage.saveScrollPos(oldItem);
|
scrollPosStorage.saveScrollPos(oldItem);
|
||||||
refreshBreakPoints();
|
refreshBreakPoints();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (actionPanel != null && !swf.isAS3()) {
|
} else if (actionPanel != null && !swf.isAS3()) {
|
||||||
actionPanel.addScriptListener(new Runnable() {
|
actionPanel.addScriptListener(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -2571,11 +2576,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
actionPanel.decompiledEditor.gotoLine(line);
|
actionPanel.decompiledEditor.gotoLine(line);
|
||||||
}
|
}
|
||||||
scrollPosStorage.saveScrollPos(oldItem);
|
scrollPosStorage.saveScrollPos(oldItem);
|
||||||
refreshBreakPoints();
|
refreshBreakPoints();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
gotoScriptName(swf, scriptName);
|
gotoScriptName(swf, scriptName);
|
||||||
}
|
}
|
||||||
@@ -2627,12 +2632,12 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
String rawScriptName = scriptName;
|
String rawScriptName = scriptName;
|
||||||
if (rawScriptName.startsWith("#PCODE ")) {
|
if (rawScriptName.startsWith("#PCODE ")) {
|
||||||
rawScriptName = rawScriptName.substring("#PCODE ".length());
|
rawScriptName = rawScriptName.substring("#PCODE ".length());
|
||||||
}
|
}
|
||||||
Map<String, ASMSource> asms = swf.getASMs(true);
|
Map<String, ASMSource> asms = swf.getASMs(true);
|
||||||
if (asms.containsKey(rawScriptName)) {
|
if (asms.containsKey(rawScriptName)) {
|
||||||
oldItem = null;
|
oldItem = null;
|
||||||
getCurrentTree().setSelectionPath(null);
|
getCurrentTree().setSelectionPath(null);
|
||||||
setTagTreeSelectedNode(getCurrentTree(), asms.get(rawScriptName));
|
setTagTreeSelectedNode(getCurrentTree(), asms.get(rawScriptName));
|
||||||
}
|
}
|
||||||
/*if (actionPanel != null && asms.containsKey(rawScriptName)) {
|
/*if (actionPanel != null && asms.containsKey(rawScriptName)) {
|
||||||
actionPanel.setSource(asms.get(rawScriptName), true);
|
actionPanel.setSource(asms.get(rawScriptName), true);
|
||||||
@@ -3090,7 +3095,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable");
|
Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable");
|
||||||
clearAllScriptCache();
|
clearAllScriptCache();
|
||||||
updateClassesList();
|
updateClassesList();
|
||||||
reload(true);
|
reload(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renameColliding(final Openable openable) {
|
public void renameColliding(final Openable openable) {
|
||||||
@@ -3170,7 +3175,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done() {
|
protected void done() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
|
|
||||||
@@ -4275,7 +4280,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
reload(true);
|
reload(true);
|
||||||
pinsPanel.refresh();
|
pinsPanel.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshTree() {
|
public void refreshTree() {
|
||||||
refreshTree(new SWF[0]);
|
refreshTree(new SWF[0]);
|
||||||
}
|
}
|
||||||
@@ -4425,7 +4430,99 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
replace(items, false);
|
replace(items, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean replace(List<TreeItem> items, boolean create) {
|
public boolean replaceMorphShape(MorphShapeTag morphShape, boolean create) {
|
||||||
|
File fileStart = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg", true, AppStrings.translate("dialog.morphshape.startShape"));
|
||||||
|
if (fileStart == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
File fileEnd = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg", true, AppStrings.translate("dialog.morphshape.endShape"));
|
||||||
|
|
||||||
|
if (fileEnd == null) {
|
||||||
|
fileEnd = fileStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineShape4Tag shapeStart = new DefineShape4Tag(morphShape.getSwf());
|
||||||
|
SWF.addTagBefore(shapeStart, morphShape);
|
||||||
|
|
||||||
|
DefineShape4Tag shapeEnd = new DefineShape4Tag(morphShape.getSwf());
|
||||||
|
SWF.addTagBefore(shapeEnd, morphShape);
|
||||||
|
|
||||||
|
File selfileStart = Helper.fixDialogFile(fileStart);
|
||||||
|
byte[] dataStart = null;
|
||||||
|
String svgTextStart = null;
|
||||||
|
boolean svgWarningShown = false;
|
||||||
|
if (".svg".equals(Path.getExtension(selfileStart))) {
|
||||||
|
svgTextStart = Helper.readTextFile(selfileStart.getAbsolutePath());
|
||||||
|
showSvgImportWarning();
|
||||||
|
svgWarningShown = true;
|
||||||
|
} else {
|
||||||
|
dataStart = Helper.readFile(selfileStart.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
File selfileEnd = Helper.fixDialogFile(fileEnd);
|
||||||
|
byte[] dataEnd = null;
|
||||||
|
String svgTextEnd = null;
|
||||||
|
if (".svg".equals(Path.getExtension(selfileEnd))) {
|
||||||
|
svgTextEnd = Helper.readTextFile(selfileEnd.getAbsolutePath());
|
||||||
|
if (!svgWarningShown) {
|
||||||
|
showSvgImportWarning();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dataEnd = Helper.readFile(selfileEnd.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Tag newStartTag;
|
||||||
|
if (svgTextStart != null) {
|
||||||
|
newStartTag = new SvgImporter().importSvg(shapeStart, svgTextStart, false);
|
||||||
|
} else {
|
||||||
|
newStartTag = new ShapeImporter().importImage(shapeStart, dataStart, 0, false);
|
||||||
|
}
|
||||||
|
newStartTag.getTimelined().removeTag(newStartTag);
|
||||||
|
|
||||||
|
Tag newEndTag;
|
||||||
|
if (svgTextStart != null) {
|
||||||
|
newEndTag = new SvgImporter().importSvg(shapeEnd, svgTextEnd, false);
|
||||||
|
} else {
|
||||||
|
newEndTag = new ShapeImporter().importImage(shapeEnd, dataEnd, 0, false);
|
||||||
|
}
|
||||||
|
newEndTag.getTimelined().removeTag(newEndTag);
|
||||||
|
|
||||||
|
if (morphShape instanceof DefineMorphShapeTag) {
|
||||||
|
DefineMorphShape2Tag morphShape2 = new DefineMorphShape2Tag(morphShape.getSwf());
|
||||||
|
morphShape.getTimelined().replaceTag(morphShape, morphShape2);
|
||||||
|
morphShape2.setTimelined(morphShape.getTimelined());
|
||||||
|
morphShape = morphShape2;
|
||||||
|
}
|
||||||
|
|
||||||
|
MorphShapeGenerator gen = new MorphShapeGenerator();
|
||||||
|
try {
|
||||||
|
gen.generate((DefineMorphShape2Tag) morphShape, shapeStart, shapeEnd);
|
||||||
|
} catch (StyleMismatchException sme) {
|
||||||
|
ViewMessages.showMessageDialog(this, AppStrings.translate("error.morphshape.incompatible"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWF swf = morphShape.getSwf();
|
||||||
|
swf.resetTimeline();
|
||||||
|
refreshTree(swf);
|
||||||
|
/*if (newTag != null) {
|
||||||
|
|
||||||
|
setTagTreeSelectedNode(getCurrentTree(), newTag);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
swf.clearImageCache();
|
||||||
|
swf.clearShapeCache();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Invalid image", ex);
|
||||||
|
ViewMessages.showMessageDialog(MainPanel.this, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
reload(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean replace(List<TreeItem> items, boolean create) {
|
||||||
if (items.isEmpty()) {
|
if (items.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -4442,10 +4539,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg", true);
|
file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg", true);
|
||||||
}
|
}
|
||||||
if (ti0 instanceof MorphShapeTag) {
|
if (ti0 instanceof MorphShapeTag) {
|
||||||
if (ViewMessages.showConfirmDialog(this, AppStrings.translate("warning.replace.morphshape"), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE, JOptionPane.WARNING_MESSAGE, Configuration.warningReplaceMorphShape, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION) {
|
return replaceMorphShape((MorphShapeTag) ti0, create);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg", true);
|
|
||||||
}
|
}
|
||||||
if (ti0 instanceof DefineVideoStreamTag) {
|
if (ti0 instanceof DefineVideoStreamTag) {
|
||||||
file = showImportFileChooser("filter.movies|*.flv", false);
|
file = showImportFileChooser("filter.movies|*.flv", false);
|
||||||
@@ -4543,14 +4637,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
if (svgText != null) {
|
if (svgText != null) {
|
||||||
newTag = new SvgImporter().importSvg((ShapeTag) st, svgText);
|
newTag = new SvgImporter().importSvg((ShapeTag) st, svgText);
|
||||||
} else {
|
} else {
|
||||||
newTag = new ShapeImporter().importImage((ShapeTag) st, data);
|
newTag = new ShapeImporter().importImage((ShapeTag) st, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (st instanceof MorphShapeTag) {
|
if (st instanceof MorphShapeTag) {
|
||||||
if (svgText != null) {
|
if (svgText != null) {
|
||||||
newTag = new SvgImporter().importSvg((MorphShapeTag) st, svgText);
|
newTag = new SvgImporter().importSvg((MorphShapeTag) st, svgText);
|
||||||
} else {
|
} else {
|
||||||
newTag = new ShapeImporter().importImage((MorphShapeTag) st, data);
|
newTag = new ShapeImporter().importImage((MorphShapeTag) st, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SWF swf = st.getSwf();
|
SWF swf = st.getSwf();
|
||||||
@@ -4628,7 +4722,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceSpriteWithGifButtonActionPerformed(TreeItem item) {
|
public void replaceSpriteWithGifButtonActionPerformed(TreeItem item) {
|
||||||
replaceSpriteWithGif(item);
|
replaceSpriteWithGif(item);
|
||||||
}
|
}
|
||||||
@@ -4660,14 +4754,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
Tag newTag = null;
|
Tag newTag = null;
|
||||||
if (st instanceof ShapeTag) {
|
if (st instanceof ShapeTag) {
|
||||||
if (svgText != null) {
|
if (svgText != null) {
|
||||||
newTag = new SvgImporter().importSvg((ShapeTag) st, svgText, false);
|
newTag = new SvgImporter().importSvg((ShapeTag) st, svgText, false);
|
||||||
} else {
|
} else {
|
||||||
newTag = new ShapeImporter().importImage((ShapeTag) st, data, 0, false);
|
newTag = new ShapeImporter().importImage((ShapeTag) st, data, 0, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (st instanceof MorphShapeTag) {
|
if (st instanceof MorphShapeTag) {
|
||||||
if (svgText != null) {
|
if (svgText != null) {
|
||||||
newTag = new SvgImporter().importSvg((MorphShapeTag) st, svgText, false);
|
newTag = new SvgImporter().importSvg((MorphShapeTag) st, svgText, false);
|
||||||
} else {
|
} else {
|
||||||
newTag = new ShapeImporter().importImage((MorphShapeTag) st, data, 0, false);
|
newTag = new ShapeImporter().importImage((MorphShapeTag) st, data, 0, false);
|
||||||
}
|
}
|
||||||
@@ -4757,6 +4851,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
|
|
||||||
public File showImportFileChooser(String filter, boolean imagePreview) {
|
public File showImportFileChooser(String filter, boolean imagePreview) {
|
||||||
|
return showImportFileChooser(filter, imagePreview, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public File showImportFileChooser(String filter, boolean imagePreview, String title) {
|
||||||
String[] filterArray = filter.length() > 0 ? filter.split("\\|") : new String[0];
|
String[] filterArray = filter.length() > 0 ? filter.split("\\|") : new String[0];
|
||||||
|
|
||||||
JFileChooser fc = new JFileChooser();
|
JFileChooser fc = new JFileChooser();
|
||||||
@@ -4816,6 +4914,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (title != null) {
|
||||||
|
fc.setDialogTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||||||
File result = fc.getSelectedFile();
|
File result = fc.getSelectedFile();
|
||||||
Configuration.lastOpenDir.set(Helper.fixDialogFile(result).getParentFile().getAbsolutePath());
|
Configuration.lastOpenDir.set(Helper.fixDialogFile(result).getParentFile().getAbsolutePath());
|
||||||
@@ -4823,7 +4925,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDetail(int card) {
|
private void showDetail(int card) {
|
||||||
if (debugStackPanel.isActive() && card != DETAILCARDDEBUGSTACKFRAME) {
|
if (debugStackPanel.isActive() && card != DETAILCARDDEBUGSTACKFRAME) {
|
||||||
@@ -4832,9 +4934,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
|
|
||||||
detailPanel.removeAll();
|
detailPanel.removeAll();
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
if (card == DETAILCARDTAGINFO) {
|
if (card == DETAILCARDTAGINFO) {
|
||||||
detailPanel.addTab(AppStrings.translate("taginfo.header"), tagInfoPanel);
|
detailPanel.addTab(AppStrings.translate("taginfo.header"), tagInfoPanel);
|
||||||
if (card == DETAILCARDTAGINFO) {
|
if (card == DETAILCARDTAGINFO) {
|
||||||
detailPanel.setSelectedIndex(pos);
|
detailPanel.setSelectedIndex(pos);
|
||||||
}
|
}
|
||||||
@@ -4845,15 +4947,15 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
detailPanel.addTab(AppStrings.translate("traits"), abcPanel.navigatorPanel);
|
detailPanel.addTab(AppStrings.translate("traits"), abcPanel.navigatorPanel);
|
||||||
if (card == DETAILCARDAS3NAVIGATOR) {
|
if (card == DETAILCARDAS3NAVIGATOR) {
|
||||||
detailPanel.setSelectedIndex(pos);
|
detailPanel.setSelectedIndex(pos);
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debugStackPanel.isActive()) {
|
if (debugStackPanel.isActive()) {
|
||||||
detailPanel.addTab(AppStrings.translate("callStack.header"), debugStackPanel);
|
detailPanel.addTab(AppStrings.translate("callStack.header"), debugStackPanel);
|
||||||
if (card == DETAILCARDDEBUGSTACKFRAME) {
|
if (card == DETAILCARDDEBUGSTACKFRAME) {
|
||||||
detailPanel.setSelectedIndex(pos);
|
detailPanel.setSelectedIndex(pos);
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
if (currentView != VIEW_DUMP) {
|
if (currentView != VIEW_DUMP) {
|
||||||
@@ -5121,10 +5223,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
showTreePanelCard(DUMP_VIEW);
|
showTreePanelCard(DUMP_VIEW);
|
||||||
treePanelMode = TreePanelMode.DUMP_TREE;
|
treePanelMode = TreePanelMode.DUMP_TREE;
|
||||||
//showDetail(DETAILCARDEMPTYPANEL);
|
//showDetail(DETAILCARDEMPTYPANEL);
|
||||||
showDetail(DETAILCARDEMPTYPANEL);
|
showDetail(DETAILCARDEMPTYPANEL);
|
||||||
reload(true);
|
reload(true);
|
||||||
updateUiWithCurrentOpenable();
|
updateUiWithCurrentOpenable();
|
||||||
detailPanel.setVisible(false);
|
detailPanel.setVisible(false);
|
||||||
return true;
|
return true;
|
||||||
case VIEW_RESOURCES:
|
case VIEW_RESOURCES:
|
||||||
pinsPanel.setVisible(true);
|
pinsPanel.setVisible(true);
|
||||||
@@ -5181,7 +5283,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
showTreePanelCard(TAGLIST_VIEW);
|
showTreePanelCard(TAGLIST_VIEW);
|
||||||
treePanelMode = TreePanelMode.TAGLIST_TREE;
|
treePanelMode = TreePanelMode.TAGLIST_TREE;
|
||||||
detailPanel.setVisible(true);
|
detailPanel.setVisible(true);
|
||||||
refreshPins();
|
refreshPins();
|
||||||
reload(true);
|
reload(true);
|
||||||
updateUiWithCurrentOpenable();
|
updateUiWithCurrentOpenable();
|
||||||
@@ -5971,7 +6073,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
|
|
||||||
return new Timelined() {
|
return new Timelined() {
|
||||||
private Timeline tim;
|
private Timeline tim;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Timeline getTimeline() {
|
public Timeline getTimeline() {
|
||||||
if (tim == null) {
|
if (tim == null) {
|
||||||
@@ -5991,6 +6093,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void initTimeline(Timeline timeline) {
|
private void initTimeline(Timeline timeline) {
|
||||||
if (tag instanceof MorphShapeTag) {
|
if (tag instanceof MorphShapeTag) {
|
||||||
timeline.frameRate = PreviewExporter.MORPH_SHAPE_ANIMATION_FRAME_RATE;
|
timeline.frameRate = PreviewExporter.MORPH_SHAPE_ANIMATION_FRAME_RATE;
|
||||||
@@ -6005,6 +6109,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
f.layersChanged = true;
|
f.layersChanged = true;
|
||||||
timeline.addFrame(f);
|
timeline.addFrame(f);
|
||||||
}
|
}
|
||||||
|
Frame f = new Frame(timeline, framesCnt);
|
||||||
|
DepthState ds = new DepthState(tag.getSwf(), f);
|
||||||
|
ds.characterId = ((CharacterTag) tag).getCharacterId();
|
||||||
|
ds.matrix = new MATRIX();
|
||||||
|
ds.ratio = 65535;
|
||||||
|
f.layers.put(1, ds);
|
||||||
|
f.layersChanged = true;
|
||||||
|
timeline.addFrame(f);
|
||||||
} else if (tag instanceof FontTag) {
|
} else if (tag instanceof FontTag) {
|
||||||
int pageCount = PreviewPanel.getFontPageCount((FontTag) tag);
|
int pageCount = PreviewPanel.getFontPageCount((FontTag) tag);
|
||||||
int frame = fontFrameNum;
|
int frame = fontFrameNum;
|
||||||
@@ -6129,7 +6241,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
setDropTarget(null);
|
setDropTarget(null);
|
||||||
disposeInner(this);
|
disposeInner(this);
|
||||||
Helper.emptyObject(this);
|
Helper.emptyObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateMissingNeededCharacters() {
|
public void updateMissingNeededCharacters() {
|
||||||
if (calculateMissingNeededThread != null) {
|
if (calculateMissingNeededThread != null) {
|
||||||
@@ -6179,7 +6291,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateMissingNeededCharacters() {
|
private void calculateMissingNeededCharacters() {
|
||||||
Map<TreeItem, Set<Integer>> missingNeededCharacters = new WeakHashMap<>();
|
Map<TreeItem, Set<Integer>> missingNeededCharacters = new WeakHashMap<>();
|
||||||
Map<TreeItem, Set<Integer>> neededCharacters = new WeakHashMap<>();
|
Map<TreeItem, Set<Integer>> neededCharacters = new WeakHashMap<>();
|
||||||
@@ -6304,7 +6416,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean fontEmbed(TreeItem item, boolean create) {
|
public boolean fontEmbed(TreeItem item, boolean create) {
|
||||||
return previewPanel.getFontPanel().fontEmbed(item, create);
|
return previewPanel.getFontPanel().fontEmbed(item, create);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,6 +190,8 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
|
|
||||||
// Image tag buttons
|
// Image tag buttons
|
||||||
private JButton replaceShapeButton;
|
private JButton replaceShapeButton;
|
||||||
|
|
||||||
|
private JButton replaceMorphShapeButton;
|
||||||
|
|
||||||
private JButton replaceShapeUpdateBoundsButton;
|
private JButton replaceShapeUpdateBoundsButton;
|
||||||
|
|
||||||
@@ -1302,6 +1304,16 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
replaceShapeButton.setVisible(false);
|
replaceShapeButton.setVisible(false);
|
||||||
|
|
||||||
|
replaceMorphShapeButton = new JButton(mainPanel.translate("button.replace"), View.getIcon("importmorphshape16"));
|
||||||
|
replaceMorphShapeButton.setMargin(new Insets(3, 3, 3, 10));
|
||||||
|
replaceMorphShapeButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
mainPanel.replaceMorphShape((MorphShapeTag) mainPanel.getCurrentTree().getCurrentTreeItem(), false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
replaceMorphShapeButton.setVisible(false);
|
||||||
|
|
||||||
replaceShapeUpdateBoundsButton = new JButton(mainPanel.translate("button.replaceNoFill"), View.getIcon("importshape16"));
|
replaceShapeUpdateBoundsButton = new JButton(mainPanel.translate("button.replaceNoFill"), View.getIcon("importshape16"));
|
||||||
replaceShapeUpdateBoundsButton.setMargin(new Insets(3, 3, 3, 10));
|
replaceShapeUpdateBoundsButton.setMargin(new Insets(3, 3, 3, 10));
|
||||||
@@ -1363,6 +1375,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
displayEditButtonsPanel.add(displayEditEditPointsButton);
|
displayEditButtonsPanel.add(displayEditEditPointsButton);
|
||||||
//displayEditButtonsPanel.add(fixPathsButton);
|
//displayEditButtonsPanel.add(fixPathsButton);
|
||||||
displayEditButtonsPanel.add(replaceShapeButton);
|
displayEditButtonsPanel.add(replaceShapeButton);
|
||||||
|
displayEditButtonsPanel.add(replaceMorphShapeButton);
|
||||||
displayEditButtonsPanel.add(replaceShapeUpdateBoundsButton);
|
displayEditButtonsPanel.add(replaceShapeUpdateBoundsButton);
|
||||||
displayEditButtonsPanel.add(morphShowPanel);
|
displayEditButtonsPanel.add(morphShowPanel);
|
||||||
return displayEditButtonsPanel;
|
return displayEditButtonsPanel;
|
||||||
@@ -1723,10 +1736,11 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
replaceImageButton.setVisible(showImage);
|
replaceImageButton.setVisible(showImage);
|
||||||
replaceImageAlphaButton.setVisible(showAlpha);
|
replaceImageAlphaButton.setVisible(showAlpha);
|
||||||
replaceSpriteButton.setVisible(showSprite);
|
replaceSpriteButton.setVisible(showSprite);
|
||||||
replaceShapeButton.setVisible(showShape || showMorphShape);
|
replaceShapeButton.setVisible(showShape);
|
||||||
|
replaceMorphShapeButton.setVisible(showMorphShape);
|
||||||
morphShowPanel.setVisible(showMorphShape);
|
morphShowPanel.setVisible(showMorphShape);
|
||||||
displayEditEditPointsButton.setVisible(showShape || showMorphShape);
|
displayEditEditPointsButton.setVisible(showShape || showMorphShape);
|
||||||
replaceShapeUpdateBoundsButton.setVisible(showShape || showMorphShape);
|
replaceShapeUpdateBoundsButton.setVisible(showShape);
|
||||||
replaceSoundButton.setVisible(showSound);
|
replaceSoundButton.setVisible(showSound);
|
||||||
replaceMovieButton.setVisible(showMovie);
|
replaceMovieButton.setVisible(showMovie);
|
||||||
prevFontsButton.setVisible(false);
|
prevFontsButton.setVisible(false);
|
||||||
@@ -2316,6 +2330,11 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
replaceShapeUpdateBoundsButton.setVisible(true);
|
replaceShapeUpdateBoundsButton.setVisible(true);
|
||||||
displayEditEditPointsButton.setVisible(true);
|
displayEditEditPointsButton.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (displayEditTag instanceof MorphShapeTag) {
|
||||||
|
replaceMorphShapeButton.setVisible(true);
|
||||||
|
displayEditEditPointsButton.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (displayEditTag instanceof DefineSpriteTag) {
|
if (displayEditTag instanceof DefineSpriteTag) {
|
||||||
replaceSpriteButton.setVisible(true);
|
replaceSpriteButton.setVisible(true);
|
||||||
@@ -2365,6 +2384,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
displayEditSaveButton.setVisible(true);
|
displayEditSaveButton.setVisible(true);
|
||||||
displayEditCancelButton.setVisible(true);
|
displayEditCancelButton.setVisible(true);
|
||||||
replaceShapeButton.setVisible(false);
|
replaceShapeButton.setVisible(false);
|
||||||
|
replaceMorphShapeButton.setVisible(false);
|
||||||
replaceShapeUpdateBoundsButton.setVisible(false);
|
replaceShapeUpdateBoundsButton.setVisible(false);
|
||||||
displayEditEditPointsButton.setVisible(false);
|
displayEditEditPointsButton.setVisible(false);
|
||||||
mainPanel.setEditingStatus();
|
mainPanel.setEditingStatus();
|
||||||
@@ -2396,6 +2416,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
displayEditSaveButton.setVisible(true);
|
displayEditSaveButton.setVisible(true);
|
||||||
displayEditCancelButton.setVisible(true);
|
displayEditCancelButton.setVisible(true);
|
||||||
replaceShapeButton.setVisible(false);
|
replaceShapeButton.setVisible(false);
|
||||||
|
replaceMorphShapeButton.setVisible(false);
|
||||||
replaceShapeUpdateBoundsButton.setVisible(false);
|
replaceShapeUpdateBoundsButton.setVisible(false);
|
||||||
displayEditEditPointsButton.setVisible(false);
|
displayEditEditPointsButton.setVisible(false);
|
||||||
|
|
||||||
@@ -2496,6 +2517,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
displayEditCancelButton.setVisible(true);
|
displayEditCancelButton.setVisible(true);
|
||||||
|
|
||||||
replaceShapeButton.setVisible(false);
|
replaceShapeButton.setVisible(false);
|
||||||
|
replaceMorphShapeButton.setVisible(false);
|
||||||
replaceShapeUpdateBoundsButton.setVisible(false);
|
replaceShapeUpdateBoundsButton.setVisible(false);
|
||||||
displayEditEditPointsButton.setVisible(false);
|
displayEditEditPointsButton.setVisible(false);
|
||||||
|
|
||||||
@@ -2792,6 +2814,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
|
|
||||||
if (displayEditTag instanceof MorphShapeTag) {
|
if (displayEditTag instanceof MorphShapeTag) {
|
||||||
morphShowPanel.setVisible(true);
|
morphShowPanel.setVisible(true);
|
||||||
|
replaceMorphShapeButton.setVisible(true);
|
||||||
displayEditEditPointsButton.setVisible(true);
|
displayEditEditPointsButton.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -740,6 +740,3 @@ config.description.displayAs12PCodePanel = Show panel with disassembled P-code a
|
|||||||
|
|
||||||
config.name.displayAs3PCodePanel = Show AS3 P-code panel
|
config.name.displayAs3PCodePanel = Show AS3 P-code panel
|
||||||
config.description.displayAs3PCodePanel = Show panel with disassembled P-code instructions for ActionScript 3
|
config.description.displayAs3PCodePanel = Show panel with disassembled P-code instructions for ActionScript 3
|
||||||
|
|
||||||
config.name.warning.replace.morphshape = Warn on replace morphshape
|
|
||||||
config.description.warning.replace.morphshape = Show warning on replacing morphshape about same start and end shape
|
|
||||||
|
|||||||
@@ -730,6 +730,3 @@ config.description.displayAs12PCodePanel = Zobrazit panel s akcemi disassemblova
|
|||||||
|
|
||||||
config.name.displayAs3PCodePanel = Zobrazit AS3 panel s P-k\u00f3dem
|
config.name.displayAs3PCodePanel = Zobrazit AS3 panel s P-k\u00f3dem
|
||||||
config.description.displayAs3PCodePanel = Zobrazit panel s instrukcemi disassemblovan\u00e9ho P-k\u00f3du pro ActionScript 3
|
config.description.displayAs3PCodePanel = Zobrazit panel s instrukcemi disassemblovan\u00e9ho P-k\u00f3du pro ActionScript 3
|
||||||
|
|
||||||
config.name.warning.replace.morphshape = Varovat p\u0159i nahrazov\u00e1n\u00ed morphshape
|
|
||||||
config.description.warning.replace.morphshape = Zobrazovat varov\u00e1n\u00ed p\u0159i nahrazov\u00e1n\u00ed morphshape o tom, \u017ee bude startov\u00e1n\u00ed a koncov\u00fd tvar stejn\u00fd
|
|
||||||
|
|||||||
@@ -1204,8 +1204,9 @@ tag.movie.create = Create movie from file...
|
|||||||
tag.sound.create = Create sound from file...
|
tag.sound.create = Create sound from file...
|
||||||
tag.font.create = Create font using dialog...
|
tag.font.create = Create font using dialog...
|
||||||
tag.binaryData.create = Create binary data from file...
|
tag.binaryData.create = Create binary data from file...
|
||||||
tag.morphshape.create = Create morphshape from shape file...
|
tag.morphshape.create = Create morphshape from shape files...
|
||||||
|
|
||||||
warning.replace.morphshape = In the following dialog you select a shape file.\r\n \
|
dialog.morphshape.startShape = Select start shape.
|
||||||
That shape would be set as start and also the end shape of the morphshape.\r\n\
|
dialog.morphshape.endShape = Select end shape. Click cancel to make end shape same as the start shape.
|
||||||
You won't see any morphing animation until you edit start/end shape to be different.
|
|
||||||
|
error.morphshape.incompatible = Cannot create morphshape: Start and end shape have incompatible fill/line styles.
|
||||||
@@ -1181,8 +1181,9 @@ tag.movie.create = Vytvo\u0159it video ze souboru...
|
|||||||
tag.sound.create = Vytvo\u0159it zvuk ze souboru...
|
tag.sound.create = Vytvo\u0159it zvuk ze souboru...
|
||||||
tag.font.create = Vytvo\u0159it p\u00edsmo pomoc\u00ed dialogu...
|
tag.font.create = Vytvo\u0159it p\u00edsmo pomoc\u00ed dialogu...
|
||||||
tag.binaryData.create = Vytvo\u0159it bin\u00e1rn\u00ed data ze souboru...
|
tag.binaryData.create = Vytvo\u0159it bin\u00e1rn\u00ed data ze souboru...
|
||||||
tag.morphshape.create = Vytvo\u0159it morphshape ze souboru tvaru...
|
tag.morphshape.create = Vytvo\u0159it morphshape ze soubor\u016f tvar\u016f...
|
||||||
|
|
||||||
warning.replace.morphshape = V n\u00e1sleduj\u00edc\u00edm dialogu vyberete soubor s tvarem.\r\n \
|
dialog.morphshape.startShape = Vyberte po\u010d\u00e1te\u010dn\u00ed tvar.
|
||||||
Ten tvar bude nastaven jako po\u010d\u00e1te\u010dn\u00ed a tak\u00e9 koncov\u00fd tvar tohot morphshape.\r\n\
|
dialog.morphshape.endShape = Vyberte koncov\u00fd tvar. Klikn\u011bte na Storno pro nastaven\u00ed stejn\u00e9ho jako je po\u010d\u00e1te\u010dn\u00ed.
|
||||||
Neuvid\u00edte \u017e\u00e1dnou morfuj\u00edc\u00ed animaci do doby ne\u017e uprav\u00edte po\u010d\u00e1te\u010dn\u00ed/koncov\u00fd tvar tak, aby byly odli\u0161n\u00e9.
|
|
||||||
|
error.morphshape.incompatible = Nelze vytvo\u0159it morphshape: Po\u010d\u00e1te\u010dn\u00ed a koncov\u00fd tvar maj\u00ed nekompatibiln\u00ed styl v\u00fdpln\u011b/ohrani\u010den\u00ed.
|
||||||
@@ -1039,11 +1039,15 @@ public class TagTreeContextMenu extends JPopupMenu {
|
|||||||
replaceMenuItem.setVisible(true);
|
replaceMenuItem.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canReplace.test(it -> (it instanceof ShapeTag) || (it instanceof MorphShapeTag))) {
|
if (canReplace.test(it -> it instanceof ShapeTag)) {
|
||||||
replaceMenuItem.setVisible(true);
|
replaceMenuItem.setVisible(true);
|
||||||
replaceNoFillMenuItem.setVisible(true);
|
replaceNoFillMenuItem.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (canReplace.test(it -> it instanceof MorphShapeTag)) {
|
||||||
|
replaceMenuItem.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (canReplace.test(it -> it instanceof DefineBinaryDataTag)) {
|
if (canReplace.test(it -> it instanceof DefineBinaryDataTag)) {
|
||||||
replaceMenuItem.setVisible(true);
|
replaceMenuItem.setVisible(true);
|
||||||
}
|
}
|
||||||
@@ -1660,11 +1664,11 @@ public class TagTreeContextMenu extends JPopupMenu {
|
|||||||
case TagTreeModel.FOLDER_MORPHSHAPES:
|
case TagTreeModel.FOLDER_MORPHSHAPES:
|
||||||
addTagMenu.addSeparator();
|
addTagMenu.addSeparator();
|
||||||
JMenuItem createMorphShapeItem = new JMenuItem(AppStrings.translate("tag.morphshape.create"));
|
JMenuItem createMorphShapeItem = new JMenuItem(AppStrings.translate("tag.morphshape.create"));
|
||||||
createMorphShapeItem.setIcon(View.getIcon("importshape16"));
|
createMorphShapeItem.setIcon(View.getIcon("importmorphshape16"));
|
||||||
createMorphShapeItem.addActionListener((ActionEvent ae) -> {
|
createMorphShapeItem.addActionListener((ActionEvent ae) -> {
|
||||||
listener.call(ae, item, DefineMorphShape2Tag.class, TreeNodeType.MORPH_SHAPE);
|
listener.call(ae, item, DefineMorphShape2Tag.class, TreeNodeType.MORPH_SHAPE);
|
||||||
});
|
});
|
||||||
addTagMenu.add(createMorphShapeItem);
|
addTagMenu.add(createMorphShapeItem);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3822,10 +3826,12 @@ public class TagTreeContextMenu extends JPopupMenu {
|
|||||||
case SPRITE:
|
case SPRITE:
|
||||||
remove = !mainPanel.replaceSpriteWithGif(tag);
|
remove = !mainPanel.replaceSpriteWithGif(tag);
|
||||||
break;
|
break;
|
||||||
case SHAPE:
|
case SHAPE:
|
||||||
case MORPH_SHAPE:
|
|
||||||
remove = !mainPanel.replaceNoFill(tag);
|
remove = !mainPanel.replaceNoFill(tag);
|
||||||
break;
|
break;
|
||||||
|
case MORPH_SHAPE:
|
||||||
|
remove = !mainPanel.replaceMorphShape((MorphShapeTag) tag, true);
|
||||||
|
break;
|
||||||
case FONT:
|
case FONT:
|
||||||
remove = !mainPanel.fontEmbed(tag, true);
|
remove = !mainPanel.fontEmbed(tag, true);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user