From fa4d5f73201264a2abba1fdf09b85e895241aad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 5 Oct 2024 23:41:20 +0200 Subject: [PATCH] Transform tab. --- .../decompiler/flash/easygui/MainFrame.java | 92 ++++++++++++++----- .../decompiler/flash/gui/ImagePanel.java | 46 ++++++++-- .../decompiler/flash/gui/TransformPanel.java | 13 ++- 3 files changed, 114 insertions(+), 37 deletions(-) diff --git a/src/com/jpexs/decompiler/flash/easygui/MainFrame.java b/src/com/jpexs/decompiler/flash/easygui/MainFrame.java index 75e8b5611..b3015ff82 100644 --- a/src/com/jpexs/decompiler/flash/easygui/MainFrame.java +++ b/src/com/jpexs/decompiler/flash/easygui/MainFrame.java @@ -17,11 +17,10 @@ package com.jpexs.decompiler.flash.easygui; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; -import com.jpexs.decompiler.flash.gui.BoundsChangeListener; import com.jpexs.decompiler.flash.gui.ImagePanel; import com.jpexs.decompiler.flash.gui.RegistrationPointPosition; import com.jpexs.decompiler.flash.gui.TimelinedMaker; +import com.jpexs.decompiler.flash.gui.TransformPanel; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.timeline.DepthState; @@ -34,19 +33,18 @@ import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; import javax.swing.UIManager; -import javax.swing.border.BevelBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; @@ -66,6 +64,8 @@ public class MainFrame extends JFrame { private JButton undoButton; private JButton redoButton; private UndoManager undoManager; + private JTabbedPane rightTabbedPane; + private TransformPanel transformPanel; public MainFrame() { setTitle("JPEXS FFDec Easy GUI"); @@ -94,33 +94,50 @@ public class MainFrame extends JFrame { public void run() { final int depth = stagePanel.getSelectedDepth(); final int frame = stagePanel.getFrame(); - MATRIX m = stagePanel.getNewMatrix().toMATRIX(); + final MATRIX newMatrix = stagePanel.getNewMatrix().toMATRIX(); + MATRIX previousMatrix = null; + synchronized (stagePanel) { + DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth); + previousMatrix = ds.matrix; + } + + final Point2D regPoint = stagePanel.getRegistrationPoint(); + final RegistrationPointPosition regPointPos = stagePanel.getRegistrationPointPosition(); + + final MATRIX fpreviousMatrix = previousMatrix; + + final boolean transformEnabled = transformEnabled(); undoManager.doOperation(new DoableOperation() { - - private MATRIX previousMatrix; - private MATRIX newMatrix = m; - + @Override public void doOperation() { timelinePanel.setFrame(frame, depth); DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth); - PlaceObjectTypeTag pl = ds.placeObjectTag; - previousMatrix = ds.matrix; ds.setMATRIX(newMatrix); stagePanel.repaint(); + if (transformEnabled()) { + stagePanel.freeTransformDepth(depth); + stagePanel.setRegistrationPoint(regPoint); + if (regPointPos != null) { + stagePanel.setRegistrationPointPosition(regPointPos); + } + } } @Override public void undoOperation() { timelinePanel.setFrame(frame, depth); DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth); - ds.setMATRIX(previousMatrix); + ds.setMATRIX(fpreviousMatrix); stagePanel.repaint(); + if (transformEnabled()) { + stagePanel.freeTransformDepth(depth); + } } @Override public String getDescription() { - return "Move"; + return transformEnabled ? "Transform" : "Move"; } }); @@ -193,16 +210,35 @@ public class MainFrame extends JFrame { libraryPreviewPanel = new ImagePanel(); libraryPreviewPanel.setTopPanelVisible(false); - JPanel topLibraryPanel = new JPanel(new BorderLayout()); - JLabel libraryLabel = new JLabel("Library"); - libraryLabel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); - topLibraryPanel.add(libraryLabel, BorderLayout.NORTH); - topLibraryPanel.add(libraryPreviewPanel, BorderLayout.CENTER); - libraryPanel.add(topLibraryPanel, BorderLayout.NORTH); + libraryPanel.add(libraryPreviewPanel, BorderLayout.NORTH); libraryPreviewPanel.setPreferredSize(new Dimension(200,200)); - horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, verticalSplitPane, libraryPanel); + rightTabbedPane = new JTabbedPane(); + rightTabbedPane.addTab("Library", libraryPanel); + + JPanel transformTab = new JPanel(new BorderLayout()); + transformPanel = new TransformPanel(stagePanel, false); + transformTab.add(new JScrollPane(transformPanel), BorderLayout.CENTER); + + rightTabbedPane.addTab("Transform", transformTab); + rightTabbedPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + int depth = stagePanel.getSelectedDepth(); + transformPanel.setVisible(depth != -1); + if (transformEnabled()) { + stagePanel.freeTransformDepth(depth); + stagePanel.setTransformSelectionMode(true); + } else { + stagePanel.freeTransformDepth(-1); + stagePanel.selectDepth(depth); + stagePanel.setTransformSelectionMode(false); + } + } + }); + + horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, verticalSplitPane, rightTabbedPane); libraryScrollPane.getViewport().setBackground(UIManager.getColor("Tree.background")); cnt.add(horizontalSplitPane, BorderLayout.CENTER); @@ -227,6 +263,10 @@ public class MainFrame extends JFrame { }); } + private boolean transformEnabled() { + return rightTabbedPane.getSelectedIndex() == 1; + } + public void open(File file) throws IOException, InterruptedException { try(FileInputStream fis = new FileInputStream(file)) { swf = new SWF(fis, true); @@ -240,9 +280,13 @@ public class MainFrame extends JFrame { timelinePanel.addFrameSelectionListener(new FrameSelectionListener() { @Override public void frameSelected(int frame, int depth) { - stagePanel.selectDepth(depth); stagePanel.pause(); - stagePanel.gotoFrame(frame + 1); + stagePanel.gotoFrame(frame + 1); + stagePanel.selectDepth(depth); + if (transformEnabled()) { + stagePanel.freeTransformDepth(depth); + } + transformPanel.setVisible(depth != -1); } }); } diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 59bb8b3d2..df2086b3a 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -311,9 +311,15 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private boolean showAllDepthLevelsInfo = true; private boolean selectionMode = false; + + private boolean transformSelectionMode = false; public void setSelectionMode(boolean selectionMode) { this.selectionMode = selectionMode; + } + + public void setTransformSelectionMode(boolean transformSelectionMode) { + this.transformSelectionMode = transformSelectionMode; } public void setTagNameResolver(TagNameResolverInterface tagNameResolver) { @@ -598,6 +604,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } public synchronized void selectDepth(int depth) { + boolean wasFreeTransform = freeTransformDepth != -1; + + transformUpdated = null; + registrationPointUpdated = null; + transform = null; + if (depth != selectedDepth) { this.selectedDepth = depth; freeTransformDepth = -1; @@ -651,6 +663,9 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } public synchronized void freeTransformDepth(int depth) { + if (selectedDepth != depth) { + selectedDepth = depth; + } if (depth != freeTransformDepth) { this.freeTransformDepth = depth; } @@ -1128,7 +1143,11 @@ public final class ImagePanel extends JPanel implements MediaDisplay { if (SwingUtilities.isLeftMouseButton(e)) { if (altDown || selectionMode) { if (depthStateUnderCursor != null) { - if (selectionMode) { + if (transformSelectionMode) { + if (freeTransformDepth != depthStateUnderCursor.depth) { + freeTransformDepth(depthStateUnderCursor.depth); + } + } else if (selectionMode) { selectDepth(depthStateUnderCursor.depth); } firePlaceObjectSelected(); @@ -1252,7 +1271,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { fireTransformChanged(); repaint(); } - if (selectionMode) { + if (selectionMode && freeTransformDepth == -1) { transform = null; } mode = Cursor.DEFAULT_CURSOR; @@ -1343,7 +1362,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { return; } - if (dragStart != null && selectionMode) { + if (dragStart != null && selectionMode && freeTransformDepth == -1) { if (transform == null) { return; } @@ -3010,7 +3029,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Matrix fullM = m.clone(); MATRIX oldMatrix = null; - if (freeTransformDepth > -1) { + if (freeTransformDepth > -1 && newMatrix != null) { DepthState ds = timeline.getFrame(frame).layers.get(freeTransformDepth); if (ds != null) { oldMatrix = ds.matrix; @@ -3043,7 +3062,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { ds = timeline.getFrame(frame).layers.get(selectedDepth); } - if (ds != null) { + if (ds != null && freeTransformDepth == -1) { CharacterTag cht = ds.getCharacter(); if (cht != null) { if (cht instanceof DrawableTag) { @@ -3103,7 +3122,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { boundsRef.setVal(bounds); gg.setStroke(new BasicStroke(1)); gg.setPaint(Color.black); - if (!selectionMode) { + if (!selectionMode || freeTransformDepth != -1) { gg.draw(bounds); drawHandles(gg, bounds); Point2D regPoint = registrationPointRef.getVal(); @@ -3315,7 +3334,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { }*/ RenderContext renderContext = new RenderContext(); renderContext.displayObjectCache = displayObjectCache; - if (cursorPosition != null && freeTransformDepth == -1) { + if (cursorPosition != null && (freeTransformDepth == -1 || transformSelectionMode)) { renderContext.cursorPosition = new Point((int) (cursorPosition.x * SWF.unitDivisor), (int) (cursorPosition.y * SWF.unitDivisor)); } @@ -3907,7 +3926,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { this.autoPlayed = true; this.frame = frame - 1; - this.prevFrame = -1; + this.prevFrame = -1; stopInternal(); redraw(); fireMediaDisplayStateChanged(); @@ -3984,6 +4003,14 @@ public final class ImagePanel extends JPanel implements MediaDisplay { return mutable; } + public Point2D getRegistrationPoint() { + return registrationPoint; + } + + public RegistrationPointPosition getRegistrationPointPosition() { + return registrationPointPosition; + } + public void setRegistrationPoint(Point2D registrationPoint) { this.registrationPoint = registrationPoint; this.registrationPointPosition = null; @@ -4012,6 +4039,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { redraw(); fireBoundsChange(getTransformBounds(), registrationPoint, registrationPointPosition); + fireTransformChanged(); } private Point2D toTransformPoint(Point2D point) { @@ -4064,7 +4092,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { int time = frozen ? 0 : this.time; DepthState ds = null; Timeline timeline = timelined.getTimeline(); - if (freeTransformDepth > -1 && timeline.getFrameCount() > frame) { + if (freeTransformDepth > -1 && timeline.getFrameCount() > frame && transform != null) { ds = timeline.getFrame(frame).layers.get(freeTransformDepth); } if (freeTransformDepth == -1 && selectionMode && transform != null && selectedDepth != -1 && timeline.getFrameCount() > frame) { diff --git a/src/com/jpexs/decompiler/flash/gui/TransformPanel.java b/src/com/jpexs/decompiler/flash/gui/TransformPanel.java index a27f94912..7f5e732d6 100644 --- a/src/com/jpexs/decompiler/flash/gui/TransformPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/TransformPanel.java @@ -170,6 +170,9 @@ public class TransformPanel extends JPanel { } public TransformPanel(ImagePanel imagePanel) { + this(imagePanel, true); + } + public TransformPanel(ImagePanel imagePanel, boolean headerLabel) { imagePanel.addBoundsChangeListener(new BoundsChangeListener() { @Override @@ -181,10 +184,12 @@ public class TransformPanel extends JPanel { this.imagePanel = imagePanel; setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - JLabel transformLabel = new JLabel(AppStrings.translate("transform")); - transformLabel.setAlignmentX(Component.CENTER_ALIGNMENT); - transformLabel.setFont(transformLabel.getFont().deriveFont(Font.BOLD)); - add(transformLabel); + if (headerLabel) { + JLabel transformLabel = new JLabel(AppStrings.translate("transform")); + transformLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + transformLabel.setFont(transformLabel.getFont().deriveFont(Font.BOLD)); + add(transformLabel); + } JPanel registrationPointPanel = new JPanel(new FlowLayout()); this.registrationPointPanel = new RegistrationPointPanel(this::registrationPointChangedActionPerformed);