diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java index 062af5c5f..fb32080e4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java @@ -57,6 +57,11 @@ public class DepthState { * Matrix */ public MATRIX matrix; + + /** + * Temporary matrix + */ + public MATRIX temporaryMatrix; /** * Instance name @@ -376,4 +381,12 @@ public class DepthState { } return Arrays.equals(this.amfData, other.amfData); } + + public MATRIX getDrawingMatrix() { + MATRIX temp = temporaryMatrix; + if (temp != null) { + return temp; + } + return matrix; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java index 13bf80390..59a6c34dd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -1394,7 +1394,7 @@ public class Timeline { if (character == null) { continue; } - Matrix layerMatrix = new Matrix(layer.matrix); + Matrix layerMatrix = new Matrix(layer.getDrawingMatrix()); Matrix mat = transformation.concatenate(layerMatrix); Matrix absMat = absoluteTransformation.concatenate(layerMatrix); @@ -1726,7 +1726,7 @@ public class Timeline { CharacterTag character = layer.getCharacter(); if (character instanceof DrawableTag) { DrawableTag drawable = (DrawableTag) character; - Matrix m = transformation.concatenate(new Matrix(layer.matrix)); + Matrix m = transformation.concatenate(new Matrix(layer.getDrawingMatrix())); int drawableFrameCount = drawable.getNumFrames(); if (drawableFrameCount == 0) { diff --git a/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java b/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java index 6e560ef05..7ff5752da 100644 --- a/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java +++ b/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java @@ -175,6 +175,8 @@ public class EasySwfPanel extends JPanel { stagePanel.setRegistrationPointPosition(regPointPos); } transformPanel.setVisible(true); + } else { + stagePanel.selectDepths(depths); } } @@ -196,6 +198,8 @@ public class EasySwfPanel extends JPanel { if (transformEnabled()) { stagePanel.freeTransformDepths(depths); transformPanel.setVisible(true); + } else { + stagePanel.selectDepths(depths); } } diff --git a/src/com/jpexs/decompiler/flash/easygui/properties/AbstractPropertyField.java b/src/com/jpexs/decompiler/flash/easygui/properties/AbstractPropertyField.java index 375b2ef57..f5be553a9 100644 --- a/src/com/jpexs/decompiler/flash/easygui/properties/AbstractPropertyField.java +++ b/src/com/jpexs/decompiler/flash/easygui/properties/AbstractPropertyField.java @@ -61,6 +61,7 @@ public abstract class AbstractPropertyField extends JPanel { private AWTEventListener aeListener; private boolean undetermined = false; + private boolean editing = false; public void addValidation(PropertyValidationInteface validation) { validations.add(validation); @@ -97,12 +98,13 @@ public abstract class AbstractPropertyField extends JPanel { readLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 1) { + if (e.getClickCount() == 1) { ((CardLayout)AbstractPropertyField.this.getLayout()).show(AbstractPropertyField.this, CARD_WRITE); writeField.requestFocus(); writeField.selectAll(); Toolkit.getDefaultToolkit().addAWTEventListener(aeListener, AWTEvent.MOUSE_EVENT_MASK); + editing = true; } } }); @@ -147,7 +149,10 @@ public abstract class AbstractPropertyField extends JPanel { protected abstract E textToValue(String text); protected abstract String valueToText(E value); - private void finishEdit() { + private synchronized void finishEdit() { + if (!editing) { + return; + } String textBefore = readLabel.getText(); String textAfter = writeField.getText(); @@ -179,10 +184,14 @@ public abstract class AbstractPropertyField extends JPanel { undetermined = false; readLabel.setText(valueToText(value)); ((CardLayout)AbstractPropertyField.this.getLayout()).show(AbstractPropertyField.this, CARD_READ); + editing = false; fireChange(); } private void cancelEdit() { + if (!editing) { + return; + } Toolkit.getDefaultToolkit().removeAWTEventListener(aeListener); if (undetermined) { writeField.setText(""); @@ -190,6 +199,7 @@ public abstract class AbstractPropertyField extends JPanel { writeField.setText(readLabel.getText()); } ((CardLayout)AbstractPropertyField.this.getLayout()).show(AbstractPropertyField.this, CARD_READ); + editing = false; } public E getValue() { @@ -200,25 +210,36 @@ public abstract class AbstractPropertyField extends JPanel { } public void setValue(Set value) { + setValue(value, false); + } + public void setValue(Set value, boolean silent) { if (value.size() != 1) { - setValue((E) null); + setValue((E) null, silent); } else { - setValue(value.iterator().next()); + setValue(value.iterator().next(), silent); } } public void setValue(E value) { + setValue(value, false); + } + + public void setValue(E value, boolean silent) { if (value == null) { readLabel.setText("-"); writeField.setText(""); undetermined = true; - fireChange(); + if (!silent) { + fireChange(); + } return; } String text = valueToText(value); readLabel.setText(text); writeField.setText(text); - fireChange(); + if (!silent) { + fireChange(); + } } } diff --git a/src/com/jpexs/decompiler/flash/easygui/properties/panels/GeneralPropertiesPanel.java b/src/com/jpexs/decompiler/flash/easygui/properties/panels/GeneralPropertiesPanel.java index 7344d0391..4be2c1437 100644 --- a/src/com/jpexs/decompiler/flash/easygui/properties/panels/GeneralPropertiesPanel.java +++ b/src/com/jpexs/decompiler/flash/easygui/properties/panels/GeneralPropertiesPanel.java @@ -20,9 +20,14 @@ import com.jpexs.decompiler.flash.easygui.ChangeDoableOperation; import com.jpexs.decompiler.flash.easygui.EasyStrings; import com.jpexs.decompiler.flash.easygui.EasySwfPanel; import com.jpexs.decompiler.flash.easygui.UndoManager; +import com.jpexs.decompiler.flash.easygui.properties.FloatPropertyField; import com.jpexs.decompiler.flash.easygui.properties.IntegerPropertyField; +import com.jpexs.decompiler.flash.easygui.properties.PropertyValidationInteface; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.gui.AppStrings; +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.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.tags.converters.PlaceObjectTypeConverter; import com.jpexs.decompiler.flash.timeline.DepthState; @@ -33,6 +38,8 @@ import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -49,6 +56,11 @@ import javax.swing.event.ChangeListener; */ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { + private final FloatPropertyField xPropertyField = new FloatPropertyField(0, -8192, 8192); + private final FloatPropertyField yPropertyField = new FloatPropertyField(0, -8192, 8192); + private final FloatPropertyField wPropertyField = new FloatPropertyField(0, -8192, 8192); + private final FloatPropertyField hPropertyField = new FloatPropertyField(0, -8192, 8192); + private final IntegerPropertyField alphaPercentPropertyField = new IntegerPropertyField(100, -100, 100); private final IntegerPropertyField redPercentPropertyField = new IntegerPropertyField(100, -100, 100); private final IntegerPropertyField greenPercentPropertyField = new IntegerPropertyField(100, -100, 100); @@ -61,17 +73,59 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { private final JPanel propertiesPanel; - private boolean updating = false; + private Rectangle2D lastBounds = null; public GeneralPropertiesPanel(EasySwfPanel swfPanel, UndoManager undoManager) { super("general"); - - JPanel colorEffectPanel = new JPanel(); - - GridBagLayout gridBag = new GridBagLayout(); + GridBagLayout gridBag; + GridBagConstraints gbc; + + JPanel positionSizePanel = new JPanel(); + gridBag = new GridBagLayout(); + positionSizePanel.setLayout(gridBag); + gbc = new GridBagConstraints(); + gbc.weightx = 0; + gbc.insets = new Insets(3, 3, 3, 3); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.EAST; + positionSizePanel.add(new JLabel(formatPropertyName("positionSize.x")), gbc); + gbc.gridx++; + gbc.anchor = GridBagConstraints.WEST; + positionSizePanel.add(xPropertyField, gbc); + gbc.gridx++; + gbc.anchor = GridBagConstraints.EAST; + positionSizePanel.add(new JLabel(formatPropertyName("positionSize.y")), gbc); + gbc.gridx++; + gbc.anchor = GridBagConstraints.WEST; + positionSizePanel.add(yPropertyField, gbc); + gbc.gridy++; + gbc.gridx = 0; + gbc.anchor = GridBagConstraints.EAST; + positionSizePanel.add(new JLabel(formatPropertyName("positionSize.width")), gbc); + gbc.gridx++; + gbc.anchor = GridBagConstraints.WEST; + positionSizePanel.add(wPropertyField, gbc); + gbc.gridx++; + gbc.anchor = GridBagConstraints.EAST; + positionSizePanel.add(new JLabel(formatPropertyName("positionSize.height")), gbc); + gbc.gridx++; + gbc.anchor = GridBagConstraints.WEST; + positionSizePanel.add(hPropertyField, gbc); + + gbc.gridx++; + gbc.gridy = 0; + gbc.gridheight = 2; + gbc.weightx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + positionSizePanel.add(new JPanel(), gbc); + + JPanel colorEffectPanel = new JPanel(); + + gridBag = new GridBagLayout(); colorEffectPanel.setLayout(gridBag); - GridBagConstraints gbc = new GridBagConstraints(); + gbc = new GridBagConstraints(); gbc.weightx = 0; gbc.insets = new Insets(3, 3, 3, 3); gbc.gridx = 0; @@ -133,15 +187,13 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { propertiesPanel = new JPanel(); propertiesPanel.setLayout(new BoxLayout(propertiesPanel, BoxLayout.Y_AXIS)); + propertiesPanel.add(makeCard("positionSize", null, positionSizePanel)); propertiesPanel.add(makeCard("colorEffect", null, colorEffectPanel)); this.swfPanel = swfPanel; alphaPercentPropertyField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - if (updating) { - return; - } undoManager.doOperation(new ColorEffectChangeDoableOperation() { int value = alphaPercentPropertyField.getValue(); @Override @@ -155,9 +207,6 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { alphaAddPropertyField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - if (updating) { - return; - } undoManager.doOperation(new ColorEffectChangeDoableOperation() { int value = alphaAddPropertyField.getValue(); @Override @@ -172,9 +221,6 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { redPercentPropertyField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - if (updating) { - return; - } undoManager.doOperation(new ColorEffectChangeDoableOperation() { int value = redPercentPropertyField.getValue(); @Override @@ -188,9 +234,6 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { redAddPropertyField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - if (updating) { - return; - } undoManager.doOperation(new ColorEffectChangeDoableOperation() { int value = redAddPropertyField.getValue(); @Override @@ -205,9 +248,6 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { greenPercentPropertyField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - if (updating) { - return; - } undoManager.doOperation(new ColorEffectChangeDoableOperation() { int value = greenPercentPropertyField.getValue(); @Override @@ -221,9 +261,6 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { greenAddPropertyField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - if (updating) { - return; - } undoManager.doOperation(new ColorEffectChangeDoableOperation() { int value = greenAddPropertyField.getValue(); @Override @@ -238,9 +275,6 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { bluePercentPropertyField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - if (updating) { - return; - } undoManager.doOperation(new ColorEffectChangeDoableOperation() { int value = bluePercentPropertyField.getValue(); @Override @@ -254,9 +288,6 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { blueAddPropertyField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - if (updating) { - return; - } undoManager.doOperation(new ColorEffectChangeDoableOperation() { int value = blueAddPropertyField.getValue(); @Override @@ -268,18 +299,101 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { } }); - add(propertiesPanel, BorderLayout.CENTER);; + xPropertyField.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + double xBefore = lastBounds.getX(); + double xAfter = xPropertyField.getValue() * 20; + double xDelta = Math.round(xAfter - xBefore); + swfPanel.getStagePanel().applyTransformMatrix(Matrix.getTranslateInstance(xDelta, 0)); + } + }); + + yPropertyField.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + double yBefore = lastBounds.getY(); + double yAfter = yPropertyField.getValue() * 20; + double yDelta = Math.round(yAfter - yBefore); + swfPanel.getStagePanel().applyTransformMatrix(Matrix.getTranslateInstance(0, yDelta)); + } + }); + + PropertyValidationInteface nonZeroFloatValidation = new PropertyValidationInteface() { + @Override + public boolean validate(Float value) { + return value != 0f; + } + }; + + wPropertyField.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + double wBefore = lastBounds.getWidth(); + if (wBefore == 0) { + return; + } + double wAfter = wPropertyField.getValue() * 20; + double wScale = wAfter / wBefore; + Matrix m = new Matrix(); + m.translate(Math.round(lastBounds.getX()), Math.round(lastBounds.getY())); + m.scale(wScale, 1); + m.translate(-Math.round(lastBounds.getX()), -Math.round(lastBounds.getY())); + swfPanel.getStagePanel().applyTransformMatrix(m); + } + }); + wPropertyField.addValidation(nonZeroFloatValidation); + + hPropertyField.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + double hBefore = lastBounds.getHeight(); + if (hBefore == 0) { + return; + } + double hAfter = hPropertyField.getValue() * 20; + double hScale = hAfter / hBefore; + Matrix m = new Matrix(); + m.translate(Math.round(lastBounds.getX()), Math.round(lastBounds.getY())); + m.scale(1, hScale); + m.translate(-Math.round(lastBounds.getX()), -Math.round(lastBounds.getY())); + swfPanel.getStagePanel().applyTransformMatrix(m); + } + }); + hPropertyField.addValidation(nonZeroFloatValidation); + + add(propertiesPanel, BorderLayout.CENTER); + + swfPanel.getStagePanel().addBoundsChangeListener(new BoundsChangeListener() { + @Override + public void boundsChanged(Rectangle2D newBounds, Point2D registrationPoint, RegistrationPointPosition registrationPointPosition) { + lastBounds = newBounds; + xPropertyField.setValue(twipToPixelValue(newBounds.getX()), true); + yPropertyField.setValue(twipToPixelValue(newBounds.getY()), true); + wPropertyField.setValue(twipToPixelValue(newBounds.getWidth()), true); + hPropertyField.setValue(twipToPixelValue(newBounds.getHeight()), true); + } + }); } + private static float twipToPixelValue(double val) { + float ret = (float) val; + ret = Math.round(ret); + ret = ret / 20; + return ret; + } + public void update() { - updating = true; List dss = swfPanel.getSelectedDepthStates(); if (dss == null || dss.isEmpty()) { propertiesPanel.setVisible(false); return; } propertiesPanel.setVisible(true); + + //swfPanel.getStagePanel().gett + Set alphaPercent = new HashSet<>(); Set alphaAdd = new HashSet<>(); Set redPercent = new HashSet<>(); @@ -316,16 +430,14 @@ public class GeneralPropertiesPanel extends AbstractPropertiesPanel { } - alphaPercentPropertyField.setValue(alphaPercent); - alphaAddPropertyField.setValue(alphaAdd); - redPercentPropertyField.setValue(redPercent); - redAddPropertyField.setValue(redAdd); - greenPercentPropertyField.setValue(greenPercent); - greenAddPropertyField.setValue(greenAdd); - bluePercentPropertyField.setValue(bluePercent); - blueAddPropertyField.setValue(blueAdd); - - updating = false; + alphaPercentPropertyField.setValue(alphaPercent, true); + alphaAddPropertyField.setValue(alphaAdd, true); + redPercentPropertyField.setValue(redPercent, true); + redAddPropertyField.setValue(redAdd, true); + greenPercentPropertyField.setValue(greenPercent, true); + greenAddPropertyField.setValue(greenAdd, true); + bluePercentPropertyField.setValue(bluePercent, true); + blueAddPropertyField.setValue(blueAdd, true); } abstract class PlaceChangeDoableOperation extends ChangeDoableOperation { diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 392deb960..33d28357d 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -1402,7 +1402,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { repaint(); } if (selectionMode && !doFreeTransform) { - transform = null; + //transform = null; } mode = Cursor.DEFAULT_CURSOR; } @@ -3170,19 +3170,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Matrix fullM = m.clone(); - List oldMatrices = new ArrayList<>(); - for (int i = 0; i < selectedDepths.size(); i++) { if (newMatrix != null) { DepthState ds = timeline.getFrame(frame).layers.get(selectedDepths.get(i)); if (ds != null) { - oldMatrices.add(ds.matrix); - timeline.getFrame(frame).layers.get(selectedDepths.get(i)).matrix = newMatrix.concatenate(new Matrix(ds.matrix)).toMATRIX(); - } else { - oldMatrices.add(null); - } - } else { - oldMatrices.add(null); + ds.temporaryMatrix = newMatrix.concatenate(new Matrix(ds.matrix)).toMATRIX(); + } } } @@ -3262,15 +3255,13 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Matrix transform2 = transform; - if (oldMatrices != null) { - transform2 = transform2.concatenate(new Matrix(oldMatrices.get(i))); - } + transform2 = transform2.concatenate(new Matrix(ds.matrix)); Shape outline = dt.getOutline(true, dframe, time, ds.ratio, renderContext, transform2, true, viewRect, zoom); if (temporaryMatrix != null) { Matrix tMatrix = temporaryMatrix; - tMatrix = tMatrix.concatenate(new Matrix(ds.matrix)); + tMatrix = tMatrix.concatenate(new Matrix(ds.temporaryMatrix)); Shape tempOutline = dt.getOutline(true, dframe, time, ds.ratio, renderContext, tMatrix, true, viewRect, zoom); gg.setStroke(new BasicStroke(1)); gg.setPaint(Color.black); @@ -3305,13 +3296,13 @@ public final class ImagePanel extends JPanel implements MediaDisplay { drawRegistrationPoint(gg, regPoint); } - if (doFreeTransform && oldMatrices != null && timeline != null && timeline.getFrameCount() > frame) { + if (timeline != null && timeline.getFrameCount() > frame) { for (int i = 0; i < selectedDepths.size(); i++) { int selectedDepth = selectedDepths.get(i); - MATRIX oldMatrix = oldMatrices.get(i); - if (oldMatrix != null) { - timeline.getFrame(frame).layers.get(selectedDepth).matrix = oldMatrix; - } + DepthState ds = timeline.getDepthState(frame, selectedDepth); + if (ds != null) { + ds.temporaryMatrix = null; + } } } img = image; diff --git a/src/com/jpexs/decompiler/flash/gui/locales/EasyPanel.properties b/src/com/jpexs/decompiler/flash/gui/locales/EasyPanel.properties index b852b409e..9b78cbebb 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/EasyPanel.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/EasyPanel.properties @@ -75,6 +75,7 @@ properties = Properties properties.document = Document properties.general = General +properties.general.header.positionSize = Position and size properties.general.header.colorEffect = Color effect property.label = %item%: @@ -84,5 +85,9 @@ property.general.colorEffect.alpha = Alpha property.general.colorEffect.red = Red property.general.colorEffect.green = Green property.general.colorEffect.blue = Blue +property.general.positionSize.x = X +property.general.positionSize.y = Y +property.general.positionSize.width = W +property.general.positionSize.height = H