diff --git a/src/com/jpexs/decompiler/flash/gui/DisplayPoint.java b/src/com/jpexs/decompiler/flash/gui/DisplayPoint.java
new file mode 100644
index 000000000..fb928ff08
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/DisplayPoint.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.jpexs.decompiler.flash.gui;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class DisplayPoint {
+ public int x;
+ public int y;
+ public boolean onPath;
+
+ public DisplayPoint(DisplayPoint src) {
+ this(src.x, src.y, src.onPath);
+ }
+
+ public DisplayPoint(int x, int y) {
+ this(x, y, true);
+ }
+ public DisplayPoint(int x, int y, boolean onPath) {
+ this.x = x;
+ this.y = y;
+ this.onPath = onPath;
+ }
+
+ @Override
+ public String toString() {
+ return "["+x+","+y+"]";
+ }
+
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java
index 19c189b14..89e146cca 100644
--- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java
@@ -231,6 +231,8 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
private static Cursor selectCursor;
private static Cursor shearXCursor;
private static Cursor shearYCursor;
+ private static Cursor movePointCursor;
+ private static Cursor defaultCursor;
private Point2D offsetPoint = new Point2D.Double(0, 0);
@@ -253,9 +255,14 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
private DepthState depthStateUnderCursor = null;
private List placeObjectSelectedListeners = new ArrayList<>();
-
+
private Point[] hilightedEdge = null;
+
+ private List hilightedPoints = null;
+ private List pointsUnderCursor = new ArrayList<>();
+ private List pointsUnderCursorValues = new ArrayList<>();
+
private int hilightEdgeColorStep = 10;
private int hilightEdgeColor = 0;
@@ -268,21 +275,44 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
private SerializableImage imgPlay = null;
private List boundsChangeListeners = new ArrayList<>();
+
+ private List pointUpdateListeners = new ArrayList<>();
+
+ public void addPointUpdateListener(PointUpdateListener listener) {
+ pointUpdateListeners.add(listener);
+ }
+ public void removePointUpdateListener(PointUpdateListener listener) {
+ pointUpdateListeners.remove(listener);
+ }
+
+ private void firePointsUpdated(List points) {
+ for(PointUpdateListener listener:pointUpdateListeners) {
+ listener.pointsUpdated(points);
+ }
+ }
+
+ private void firePointAdded(int position, DisplayPoint point) {
+ for(PointUpdateListener listener:pointUpdateListeners) {
+ listener.pointAdded(position, point);
+ }
+ }
+
+ private void firePointRemoved(int position) {
+ for(PointUpdateListener listener:pointUpdateListeners) {
+ listener.pointRemoved(position);
+ }
+ }
+
+ public void setHilightedPoints(List hilightedPoints) {
+ this.hilightedPoints = hilightedPoints;
+ redraw();
+ }
public void setHilightedEdge(Point[] hilightedEdge) {
this.hilightedEdge = hilightedEdge;
hilightEdgeColor = 255;
- /*if (hilightedEdge == null) {
- System.out.println("set no hilight edge");
- } else {
- String s = "";
- for(Point p:hilightedEdge) {
- s+="["+p.x+","+p.y+"]";
- }
- System.out.println("set hilight edge " + s);
- }*/
redraw();
- }
+ }
public void addBoundsChangeListener(BoundsChangeListener listener) {
boundsChangeListeners.add(listener);
@@ -371,7 +401,9 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
selectCursor = loadCursor("select", 0, 0);
shearXCursor = loadCursor("shear_x", 9, 5);
shearYCursor = loadCursor("shear_y", 5, 9);
-
+ movePointCursor = loadCursor("move_point", 0, 0);
+ defaultCursor = loadCursor("default", 0, 0);
+
} catch (IOException ex) {
Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -481,6 +513,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
this.freeTransformDepth = depth;
}
hilightedEdge = null;
+ hilightedPoints = null;
registrationPoint = null;
calculateFreeTransform();
hideMouseSelection();
@@ -637,7 +670,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
g2.drawImage(img.getBufferedImage(), x, y, x + img.getWidth(), y + img.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null);
- if (hilightedEdge != null) {
+ if (hilightedEdge != null || hilightedPoints != null) {
hilightEdgeColor += hilightEdgeColorStep;
if (hilightEdgeColor < 100 || hilightEdgeColor > 255) {
hilightEdgeColorStep = -hilightEdgeColorStep;
@@ -645,43 +678,59 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
}
RECT timRect = timelined.getRect();
double zoomDouble = zoom.fit ? getZoomToFit() : zoom.value;
- AffineTransform t = new AffineTransform();
- t.translate(offsetPoint.getX() - (int) (timRect.Xmin * zoomDouble / SWF.unitDivisor)
- , offsetPoint.getY() - (int) (timRect.Ymin * zoomDouble / SWF.unitDivisor));
- t.scale(1/SWF.unitDivisor, 1/SWF.unitDivisor);
+ AffineTransform t = new AffineTransform();
+ t.translate(offsetPoint.getX() - (int) (timRect.Xmin * zoomDouble / SWF.unitDivisor),
+ offsetPoint.getY() - (int) (timRect.Ymin * zoomDouble / SWF.unitDivisor));
+ t.scale(1 / SWF.unitDivisor, 1 / SWF.unitDivisor);
t.scale(zoomDouble, zoomDouble);
AffineTransform oldTransform = g2.getTransform();
g2.setTransform(t);
- g2.setStroke(new BasicStroke((float) (SWF.unitDivisor * 6 / zoomDouble)));
- g2.setPaint(new Color(hilightEdgeColor, hilightEdgeColor, hilightEdgeColor));
- Point[] edge = hilightedEdge;
- GeneralPath path = new GeneralPath();
- if (edge.length == 2) {
- path.moveTo(edge[0].x, edge[0].y);
- path.lineTo(edge[1].x, edge[1].y);
+
+ if (hilightedEdge != null) {
+ g2.setStroke(new BasicStroke((float) (SWF.unitDivisor * 6 / zoomDouble)));
+ g2.setPaint(new Color(hilightEdgeColor, hilightEdgeColor, hilightEdgeColor));
+ Point[] edge = hilightedEdge;
+ GeneralPath path = new GeneralPath();
+ if (edge.length == 2) {
+ path.moveTo(edge[0].x, edge[0].y);
+ path.lineTo(edge[1].x, edge[1].y);
+ }
+ if (edge.length == 3) {
+ path.moveTo(edge[0].x, edge[0].y);
+ path.quadTo(edge[1].x, edge[1].y, edge[2].x, edge[2].y);
+ }
+ if (edge.length == 1) {
+ double crossSize = (SWF.unitDivisor * 10 / zoomDouble);
+ path.moveTo(edge[0].x - crossSize, edge[0].y);
+ path.lineTo(edge[0].x + crossSize, edge[0].y);
+ path.moveTo(edge[0].x, edge[0].y - crossSize);
+ path.lineTo(edge[0].x, edge[0].y + crossSize);
+ }
+ g2.draw(path);
+
+ double pointSize = SWF.unitDivisor * 4 / zoomDouble;
+
+ g2.setPaint(Color.red);
+ g2.fill(new Ellipse2D.Double(edge[edge.length - 1].x - pointSize, edge[edge.length - 1].y - pointSize, pointSize * 2, pointSize * 2));
+ g2.setPaint(Color.green);
+ g2.fill(new Ellipse2D.Double(edge[0].x - pointSize, edge[0].y - pointSize, pointSize * 2, pointSize * 2));
}
- if (edge.length == 3) {
- path.moveTo(edge[0].x, edge[0].y);
- path.quadTo(edge[1].x, edge[1].y, edge[2].x, edge[2].y);
- }
- if (edge.length == 1) {
- double crossSize = (SWF.unitDivisor * 10 / zoomDouble);
- path.moveTo(edge[0].x - crossSize, edge[0].y);
- path.lineTo(edge[0].x + crossSize, edge[0].y);
- path.moveTo(edge[0].x, edge[0].y - crossSize);
- path.lineTo(edge[0].x, edge[0].y + crossSize);
- }
- g2.draw(path);
- double pointSize = SWF.unitDivisor * 4 / zoomDouble;
-
- g2.setPaint(Color.red);
- g2.fill(new Ellipse2D.Double(edge[edge.length - 1].x - pointSize, edge[edge.length - 1].y - pointSize, pointSize * 2, pointSize * 2));
- g2.setPaint(Color.green);
- g2.fill(new Ellipse2D.Double(edge[0].x - pointSize, edge[0].y - pointSize, pointSize * 2, pointSize * 2));
+ List points = hilightedPoints;
+ if (points != null) {
+ g2.setStroke(new BasicStroke((float) (SWF.unitDivisor * 1 / zoomDouble)));
+ double pointSize = SWF.unitDivisor * 4 / zoomDouble;
+ for (DisplayPoint p:points) {
+ Rectangle2D pointRect = new Rectangle2D.Double(p.x - pointSize, p.y - pointSize, pointSize * 2, pointSize * 2);
+ g2.setPaint(Color.white);
+ g2.fill(pointRect);
+ g2.setPaint(Color.black);
+ g2.draw(pointRect);
+ }
+ }
g2.setTransform(oldTransform);
}
- if (!(timelined instanceof SWF) && freeTransformDepth > -1) {
+ if (!(timelined instanceof SWF) && (freeTransformDepth > -1 || hilightedPoints != null)) {
int axisX = 0;
int axisY = 0;
@@ -800,6 +849,14 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
}
mouseMoved(e); //to correctly calculate mode, because moseMoved event is not called during dragging
setDragStart(e.getPoint());
+
+ List newPointsUnderCursorValues = new ArrayList<>();
+ for (int i:pointsUnderCursor) {
+ newPointsUnderCursorValues.add(new DisplayPoint(hilightedPoints.get(i)));
+ }
+
+ pointsUnderCursorValues = newPointsUnderCursorValues;
+
if (!autoPlayed) {
Configuration.autoPlayPreviews.set(true);
@@ -858,6 +915,26 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
@Override
public void mouseDragged(MouseEvent e) {
+ List points = hilightedPoints;
+ if (dragStart != null && points != null) {
+ if (!pointsUnderCursor.isEmpty()) {
+
+ for (int i = 0; i < pointsUnderCursor.size(); i++) {
+ int pointIndex = pointsUnderCursor.get(i);
+ DisplayPoint pointStart = pointsUnderCursorValues.get(i);
+ Point2D dragEnd = e.getPoint();
+ Point2D startTransformPoint = toTransformPoint(dragStart);
+ Point2D endTransformPoint = toTransformPoint(dragEnd);
+ Point2D delta = new Point2D.Double(endTransformPoint.getX() - startTransformPoint.getX(), endTransformPoint.getY() - startTransformPoint.getY());
+ //System.out.println("delta = "+delta);
+ DisplayPoint newPoint = new DisplayPoint((int)Math.round(pointStart.x + delta.getX()), (int)Math.round(pointStart.y + delta.getY()), pointStart.onPath);
+ points.set(pointIndex, newPoint);
+ }
+ firePointsUpdated(points);
+ repaint();
+ return;
+ }
+ }
if (dragStart != null && allowMove && mode == Cursor.DEFAULT_CURSOR) {
Point2D dragEnd = e.getPoint();
Point2D delta = new Point2D.Double(dragEnd.getX() - dragStart.getX(), dragEnd.getY() - dragStart.getY());
@@ -1347,6 +1424,32 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
@Override
public void mouseMoved(MouseEvent e) {
+ List points = hilightedPoints;
+ if (points != null) {
+ Cursor cursor = defaultCursor;
+ int maxDistance = 5;
+ List newPointsUnderCursor = new ArrayList<>();
+ for (int i = 0; i < points.size(); i++) {
+ DisplayPoint p = points.get(i);
+ Point2D ip = toImagePoint(new Point2D.Double(p.x,p.y));
+ int ex = e.getX();
+ int ey = e.getY();
+ if (ex > ip.getX() - maxDistance && ex < ip.getX() + maxDistance) {
+ if (ey > ip.getY() - maxDistance && ey < ip.getY() + maxDistance) {
+ cursor = movePointCursor;
+ newPointsUnderCursor.add(i);
+ }
+ }
+ }
+ if (dragStart == null) {
+ pointsUnderCursor = newPointsUnderCursor;
+ }
+
+ if (getCursor() != cursor) {
+ setCursor(cursor);
+ }
+ return;
+ }
if (freeTransformDepth > -1) {
if (bounds == null) {
return;
@@ -1983,6 +2086,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
this.mutable = mutable;
depthStateUnderCursor = null;
hilightedEdge = null;
+ hilightedPoints = null;
this.showObjectsUnderCursor = showObjectsUnderCursor;
this.registrationPointPosition = RegistrationPointPosition.CENTER;
centerImage();
@@ -2019,6 +2123,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
stillFrame = true;
zoomAvailable = false;
hilightedEdge = null;
+ hilightedPoints = null;
iconPanel.setImg(image);
drawReady = true;
@@ -2690,7 +2795,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
} else {
debugLabel.setText(ret.toString());
}
- if (freeTransformDepth == -1) {
+ if (freeTransformDepth == -1 && hilightedPoints == null) {
Cursor newCursor;
if (iconPanel.isAltDown()) {
if (depthStateUnderCursor == null) {
diff --git a/src/com/jpexs/decompiler/flash/gui/PointUpdateListener.java b/src/com/jpexs/decompiler/flash/gui/PointUpdateListener.java
new file mode 100644
index 000000000..a46a094a6
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/PointUpdateListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.jpexs.decompiler.flash.gui;
+
+import java.util.List;
+
+/**
+ *
+ * @author JPEXS
+ */
+public interface PointUpdateListener {
+ public void pointsUpdated(List points);
+
+ public void pointAdded(int position, DisplayPoint point);
+
+ public void pointRemoved(int position);
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java
index 35b51e4e9..a76f9e7fd 100644
--- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java
@@ -64,6 +64,7 @@ import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
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.SerializableImage;
import java.awt.BorderLayout;
import java.awt.CardLayout;
@@ -220,6 +221,8 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
private JButton displayEditSaveButton;
private JButton displayEditCancelButton;
+
+ private JButton displayEditEditPointsButton;
private JPanel parametersPanel;
@@ -241,9 +244,12 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
private HexView unknownHexView;
- private final int PLACE_EDIT_TRANSFORM = 1;
- private final int PLACE_EDIT_RAW = 2;
- private int placeEditMode = PLACE_EDIT_RAW;
+ private final int EDIT_TRANSFORM = 1;
+ private final int EDIT_RAW = 2;
+ private final int EDIT_POINTS = 3;
+ private int displayEditMode = EDIT_RAW;
+
+ private List oldShapeRecords;
//used only for flash player
private TreeItem currentItem;
@@ -731,6 +737,58 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
}
});
}
+
+ displayEditImagePanel.addPointUpdateListener(new PointUpdateListener() {
+ @Override
+ public void pointsUpdated(List points) {
+ ShapeTag shape = (ShapeTag) displayEditTag;
+ int pointsPos = 0;
+ int x = 0;
+ int y = 0;
+ for(int i = 0; i < shape.shapes.shapeRecords.size(); i++) {
+ SHAPERECORD rec = shape.shapes.shapeRecords.get(i);
+ if (rec instanceof StyleChangeRecord) {
+ StyleChangeRecord scr = (StyleChangeRecord) rec;
+ if (scr.stateMoveTo) {
+ scr.moveDeltaX = points.get(pointsPos).x;
+ scr.moveDeltaY = points.get(pointsPos).y;
+ pointsPos++;
+ }
+ }
+ if (rec instanceof StraightEdgeRecord) {
+ StraightEdgeRecord ser = (StraightEdgeRecord) rec;
+ ser.generalLineFlag = true;
+ ser.deltaX = points.get(pointsPos).x - x;
+ ser.deltaY = points.get(pointsPos).y - y;
+ pointsPos += 1;
+ ser.simplify();
+ }
+ if (rec instanceof CurvedEdgeRecord) {
+ CurvedEdgeRecord cer = (CurvedEdgeRecord) rec;
+ cer.controlDeltaX = points.get(pointsPos).x - x;
+ cer.controlDeltaY = points.get(pointsPos).y - y;
+ cer.anchorDeltaX = points.get(pointsPos + 1).x - points.get(pointsPos).x;
+ cer.anchorDeltaY = points.get(pointsPos + 1).y - points.get(pointsPos).y;
+ pointsPos += 2;
+ }
+ x = rec.changeX(x);
+ y = rec.changeY(y);
+ }
+ shape.getSwf().clearShapeCache();
+ displayEditImagePanel.repaint();
+ }
+
+ @Override
+ public void pointAdded(int position, DisplayPoint point) {
+ }
+
+ @Override
+ public void pointRemoved(int position) {
+
+ }
+
+ });
+
displayEditTransformPanel = new TransformPanel(displayEditImagePanel);
//imagePanel.setLoop(Configuration.loopMedia.get());
previewCnt.add(displayEditTransformSplitPane = new JPersistentSplitPane(
@@ -837,6 +895,10 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
displayEditCancelButton.setMargin(new Insets(3, 3, 3, 10));
displayEditCancelButton.addActionListener(this::cancelDisplayEditTagButtonActionPerformed);
+ displayEditEditPointsButton = new JButton(mainPanel.translate("button.edit.points"), View.getIcon("edit16"));
+ displayEditEditPointsButton.setMargin(new Insets(3, 3, 3, 10));
+ displayEditEditPointsButton.addActionListener(this::editPointsDisplayEditTagButtonActionPerformed);
+
replaceShapeButton = new JButton(mainPanel.translate("button.replace"), View.getIcon("replaceshape16"));
replaceShapeButton.setMargin(new Insets(3, 3, 3, 10));
replaceShapeButton.addActionListener(new ActionListener() {
@@ -874,6 +936,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
placeTagButtonsPanel.add(displayEditEditButton);
placeTagButtonsPanel.add(displayEditSaveButton);
placeTagButtonsPanel.add(displayEditCancelButton);
+ placeTagButtonsPanel.add(displayEditEditPointsButton);
placeTagButtonsPanel.add(replaceShapeButton);
placeTagButtonsPanel.add(replaceShapeUpdateBoundsButton);
return placeTagButtonsPanel;
@@ -1225,6 +1288,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
replaceImageButton.setVisible(showImage);
replaceImageAlphaButton.setVisible(showAlpha);
replaceShapeButton.setVisible(showShape);
+ displayEditEditPointsButton.setVisible(showShape);
replaceShapeUpdateBoundsButton.setVisible(showShape);
replaceSoundButton.setVisible(showSound);
replaceMovieButton.setVisible(showMovie);
@@ -1460,7 +1524,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
}
private void saveDisplayEditTag(boolean refreshTree) {
- if (placeEditMode == PLACE_EDIT_TRANSFORM) {
+ if (displayEditMode == EDIT_TRANSFORM) {
Matrix matrix = displayEditImagePanel.getNewMatrix();
if (displayEditTag instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag placeTag = (PlaceObjectTypeTag) displayEditTag;
@@ -1550,9 +1614,14 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
displayEditTransformScrollPane.setVisible(false);
displayEditGenericPanel.setVisible(true);
}
+ if (displayEditMode == EDIT_POINTS) {
+ displayEditImagePanel.setHilightedPoints(null);
+ displayEditTag.setModified(true);
+ oldShapeRecords = null;
+ }
Tag hilightTag = null;
SWF swf = null;
- if (placeEditMode == PLACE_EDIT_RAW) {
+ if (displayEditMode == EDIT_RAW) {
if (displayEditGenericPanel.save()) {
Tag tag = displayEditGenericPanel.getTag();
swf = tag.getSwf();
@@ -1565,6 +1634,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
if (displayEditTag instanceof ShapeTag) {
replaceShapeButton.setVisible(true);
replaceShapeUpdateBoundsButton.setVisible(true);
+ displayEditEditPointsButton.setVisible(true);
}
displayEditTransformButton.setVisible(true);
@@ -1581,7 +1651,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
displayEditCancelButton.setVisible(false);
}
- if (placeEditMode == PLACE_EDIT_RAW && refreshTree && swf != null) {
+ if (displayEditMode == EDIT_RAW && refreshTree && swf != null) {
mainPanel.refreshTree(swf);
}
mainPanel.clearEditingStatus();
@@ -1589,8 +1659,8 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
if (hilightTag != null) {
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), hilightTag);
}
- if (placeEditMode == PLACE_EDIT_TRANSFORM) {
- placeEditMode = PLACE_EDIT_RAW;
+ if (displayEditMode == EDIT_TRANSFORM) {
+ displayEditMode = EDIT_RAW;
}
}
@@ -1599,7 +1669,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
}
private void editDisplayEditTagButtonActionPerformed(ActionEvent evt) {
- placeEditMode = PLACE_EDIT_RAW;
+ displayEditMode = EDIT_RAW;
displayEditGenericPanel.setEditMode(true, displayEditTag);
displayEditEditButton.setVisible(false);
displayEditTransformButton.setVisible(false);
@@ -1607,6 +1677,55 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
displayEditCancelButton.setVisible(true);
replaceShapeButton.setVisible(false);
replaceShapeUpdateBoundsButton.setVisible(false);
+ displayEditEditPointsButton.setVisible(false);
+ mainPanel.setEditingStatus();
+ }
+
+ private void editPointsDisplayEditTagButtonActionPerformed(ActionEvent evt) {
+ displayEditMode = EDIT_POINTS;
+ displayEditGenericPanel.setVisible(false);
+ displayEditEditButton.setVisible(false);
+ displayEditTransformButton.setVisible(false);
+ displayEditSaveButton.setVisible(true);
+ displayEditCancelButton.setVisible(true);
+ replaceShapeButton.setVisible(false);
+ replaceShapeUpdateBoundsButton.setVisible(false);
+ displayEditEditPointsButton.setVisible(false);
+
+
+ ShapeTag shape = (ShapeTag) displayEditTag;
+
+ oldShapeRecords = Helper.deepCopy(shape.shapes.shapeRecords);
+ int x = 0;
+ int y = 0;
+
+ List points = new ArrayList<>();
+ for (SHAPERECORD rec:shape.shapes.shapeRecords) {
+ if (rec instanceof StraightEdgeRecord) {
+ StraightEdgeRecord ser = (StraightEdgeRecord) rec;
+ DisplayPoint point = new DisplayPoint(x + ser.deltaX, y + ser.deltaY);
+ points.add(point);
+ }
+ if (rec instanceof CurvedEdgeRecord) {
+ CurvedEdgeRecord cer = (CurvedEdgeRecord) rec;
+ DisplayPoint controlPoint = new DisplayPoint(x + cer.controlDeltaX, y + cer.controlDeltaY, false);
+ DisplayPoint anchorPoint = new DisplayPoint(x + cer.controlDeltaX + cer.anchorDeltaX, y + cer.controlDeltaY + cer.anchorDeltaY);
+ points.add(controlPoint);
+ points.add(anchorPoint);
+ }
+ if (rec instanceof StyleChangeRecord) {
+ StyleChangeRecord scr = (StyleChangeRecord) rec;
+ if (scr.stateMoveTo) {
+ DisplayPoint point = new DisplayPoint(scr.moveDeltaX, scr.moveDeltaY);
+ points.add(point);
+ }
+ }
+
+ x = rec.changeX(x);
+ y = rec.changeY(y);
+ }
+ displayEditImagePanel.setHilightedPoints(points);
+
mainPanel.setEditingStatus();
}
@@ -1615,7 +1734,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
if (item == null) {
return;
}
- placeEditMode = PLACE_EDIT_TRANSFORM;
+ displayEditMode = EDIT_TRANSFORM;
displayEditGenericPanel.setVisible(false);
displayEditImagePanel.selectDepth(-1);
@@ -1628,6 +1747,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
replaceShapeButton.setVisible(false);
replaceShapeUpdateBoundsButton.setVisible(false);
+ displayEditEditPointsButton.setVisible(false);
if (Configuration.editorMode.get()) {
displayEditSaveButton.setEnabled(false);
@@ -1869,7 +1989,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
}
private void cancelDisplayEditTagButtonActionPerformed(ActionEvent evt) {
- if (placeEditMode == PLACE_EDIT_TRANSFORM) {
+ if (displayEditMode == EDIT_TRANSFORM) {
if (displayEditTag instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag place = (PlaceObjectTypeTag) displayEditTag;
displayEditImagePanel.selectDepth(place.getDepth());
@@ -1879,9 +1999,18 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
displayEditTransformScrollPane.setVisible(false);
displayEditGenericPanel.setVisible(true);
}
+
+ if (displayEditMode == EDIT_POINTS) {
+ displayEditImagePanel.setHilightedPoints(null);
+ ShapeTag shape = (ShapeTag) displayEditTag;
+ shape.shapes.shapeRecords = oldShapeRecords;
+ shape.getSwf().clearShapeCache();
+ displayEditImagePanel.repaint();
+ displayEditGenericPanel.setVisible(true);
+ }
if (Configuration.editorMode.get()) {
- if (placeEditMode == PLACE_EDIT_RAW) {
+ if (displayEditMode == EDIT_RAW) {
displayEditGenericPanel.setEditMode(true, null);
}
displayEditEditButton.setVisible(false);
@@ -1890,7 +2019,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
displayEditCancelButton.setVisible(true);
displayEditCancelButton.setEnabled(false);
} else {
- if (placeEditMode == PLACE_EDIT_RAW) {
+ if (displayEditMode == EDIT_RAW) {
displayEditGenericPanel.setEditMode(false, null);
}
displayEditEditButton.setVisible(true);
@@ -1900,14 +2029,15 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
if (displayEditTag instanceof ShapeTag) {
replaceShapeButton.setVisible(true);
- replaceShapeUpdateBoundsButton.setVisible(true);
+ replaceShapeUpdateBoundsButton.setVisible(true);
+ displayEditEditPointsButton.setVisible(true);
}
mainPanel.clearEditingStatus();
displayEditTransformButton.setVisible(true);
- if (placeEditMode == PLACE_EDIT_TRANSFORM) {
- placeEditMode = PLACE_EDIT_RAW;
+ if (displayEditMode == EDIT_TRANSFORM) {
+ displayEditMode = EDIT_RAW;
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/cursors/default.png b/src/com/jpexs/decompiler/flash/gui/graphics/cursors/default.png
new file mode 100644
index 000000000..a1adae238
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/cursors/default.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/cursors/move_point.png b/src/com/jpexs/decompiler/flash/gui/graphics/cursors/move_point.png
new file mode 100644
index 000000000..df67227a9
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/cursors/move_point.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
index c92268376..54b9da5d2 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
@@ -1107,4 +1107,7 @@ message.info.importSounds2 = During importing sounds, you need to select a FOLDE
If there exist "sounds" folder inside, it is selected instead.\r\n \
The best way to get the structure right is to export sounds in current SWF file first.
-import.sound.result = %count% sounds imported.
\ No newline at end of file
+import.sound.result = %count% sounds imported.
+
+#after 18.2.1
+button.edit.points = Edit points
\ No newline at end of file
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties
index 7c6c35b58..b6f44da28 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties
@@ -1092,4 +1092,7 @@ message.info.importSounds2 = B\u011bhem importu zvuk\u016f mus\u00edte vybrat SL
Pokud je uvnit\u0159 slo\u017eka "sounds", pak je vybr\u00e1na m\u00edsto n\u00ed.\r\n \
Nejlep\u0161\u00ed zp\u016fsob jak m\u00edt tuto strukturu spr\u00e1vn\u011b je nejprve exportovat zvuky v aktu\u00e1ln\u00edm SWF souboru.
-import.sound.result = %count% zvuk\u016f importov\u00e1no.
\ No newline at end of file
+import.sound.result = %count% zvuk\u016f importov\u00e1no.
+
+#after 18.2.1
+button.edit.points = Editovat body
\ No newline at end of file