diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index e028c61e1..a4de7c88e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -4890,7 +4890,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { renderContext.cursorPosition = cursorPosition; renderContext.mouseButton = mouseButton; ExportRectangle viewRect = new ExportRectangle(rect); - timeline.toImage(frame, time, renderContext, image, image, false, m, new Matrix(), m, colorTransform, zoom, true, viewRect, m, true, Timeline.DRAW_MODE_ALL, 0, canUseSmoothing); + timeline.toImage(frame, time, renderContext, image, image, false, m, new Matrix(), m, colorTransform, zoom, true, viewRect, m, true, Timeline.DRAW_MODE_ALL, 0, canUseSmoothing, new ArrayList<>()); return image; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java index aaefe2d3f..1048397b9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java @@ -609,7 +609,7 @@ public class FrameExporter { renderContext.stateUnderCursor = new ArrayList<>(); try { - tim.toImage(fframe, fframe, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, new ExportRectangle(rect), m, true, Timeline.DRAW_MODE_ALL, 0, true); + tim.toImage(fframe, fframe, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, new ExportRectangle(rect), m, true, Timeline.DRAW_MODE_ALL, 0, true, new ArrayList<>()); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java index fafcbb53b..8c00b8624 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.exporters.commonshape; import com.jpexs.decompiler.flash.types.MATRIX; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; /** * Matrix class, used in shape export. @@ -92,6 +93,15 @@ public final class Matrix implements Cloneable { scaleY = 1; } + public Matrix(double scaleX, double scaleY, double rotateSkew0, double rotateSkew1, double translateX, double translateY) { + this.scaleX = scaleX; + this.scaleY = scaleY; + this.rotateSkew0 = rotateSkew0; + this.rotateSkew1 = rotateSkew1; + this.translateX = translateX; + this.translateY = translateY; + } + public Matrix(MATRIX matrix) { if (matrix == null) { matrix = new MATRIX(); @@ -170,6 +180,11 @@ public final class Matrix implements Cloneable { return new Point2D.Double(p.x, p.y); } + public Rectangle2D transform(Rectangle2D rect) { + ExportRectangle er = transform(new ExportRectangle(rect)); + return new Rectangle2D.Double(er.xMin, er.yMin, er.getWidth(), er.getHeight()); + } + public ExportRectangle transform(ExportRectangle rect) { double minX = Double.MAX_VALUE; double minY = Double.MAX_VALUE; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index 47525a713..e6844efe0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -415,7 +415,7 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { @Override public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) { - getTimeline().toImage(frame, time, renderContext, image, fullImage, isClip, transformation, strokeTransformation, absoluteTransformation, colorTransform, unzoom, sameImage, viewRect, fullTransformation, scaleStrokes, drawMode, blendMode, canUseSmoothing); + getTimeline().toImage(frame, time, renderContext, image, fullImage, isClip, transformation, strokeTransformation, absoluteTransformation, colorTransform, unzoom, sameImage, viewRect, fullTransformation, scaleStrokes, drawMode, blendMode, canUseSmoothing, new ArrayList<>()); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java index aee8f922f..e12b01f6b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java @@ -32,6 +32,7 @@ import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.SerializableImage; import java.awt.Shape; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -123,7 +124,7 @@ public abstract class ButtonTag extends DrawableTag implements Timelined { @Override public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) { - getTimeline().toImage(frame, time, renderContext, image, fullImage, isClip, transformation, strokeTransformation, absoluteTransformation, colorTransform, unzoom, sameImage, viewRect, fullTransformation, scaleStrokes, drawMode, blendMode, canUseSmoothing); + getTimeline().toImage(frame, time, renderContext, image, fullImage, isClip, transformation, strokeTransformation, absoluteTransformation, colorTransform, unzoom, sameImage, viewRect, fullTransformation, scaleStrokes, drawMode, blendMode, canUseSmoothing, new ArrayList<>()); } @Override 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 15879e659..6b60d1a72 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 @@ -1363,8 +1363,9 @@ public class Timeline { * @param drawMode Draw mode * @param blendMode Blend mode * @param canUseSmoothing Can use smoothing + * @param ignoreDepths Ignore these depths when drawing */ - public void toImage(int frame, int time, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, Matrix fullTransformation, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) { + public void toImage(int frame, int time, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, Matrix fullTransformation, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing, List ignoreDepths) { if (getFrameCount() <= frame) { return; } @@ -1385,7 +1386,7 @@ public class Timeline { int maxDepth = getMaxDepth(); int clipCount = 0; - for (int i = 0; i <= maxDepth; i++) { + for (int i = 0; i <= maxDepth; i++) { boolean clipChanged = clipCount != clips.size(); for (int c = 0; c < clips.size(); c++) { if (clips.get(c).depth < i) { @@ -1448,6 +1449,11 @@ public class Timeline { if (drawMode != DRAW_MODE_ALL && drawMode != DRAW_MODE_SHAPES && (character instanceof ShapeTag)) { continue; } + + if (ignoreDepths.contains(i)) { + continue; + } + if (character instanceof DrawableTag) { RECT scalingRect = null; diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index e49fdacec..e2cd38756 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -2839,7 +2839,7 @@ public class CommandLineArgumentParser { renderContext.stateUnderCursor = new ArrayList<>(); try { - tim.toImage(fframe, fframe, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, new ExportRectangle(rect), m, true, Timeline.DRAW_MODE_ALL, 0, true); + tim.toImage(fframe, fframe, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, new ExportRectangle(rect), m, true, Timeline.DRAW_MODE_ALL, 0, true, new ArrayList<>()); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java b/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java index e2fab87bc..372499774 100644 --- a/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java +++ b/src/com/jpexs/decompiler/flash/easygui/EasySwfPanel.java @@ -31,6 +31,8 @@ import com.jpexs.decompiler.flash.gui.TimelinedMaker; import com.jpexs.decompiler.flash.gui.TransformPanel; import com.jpexs.decompiler.flash.gui.View; import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane; +import com.jpexs.decompiler.flash.gui.player.MediaDisplay; +import com.jpexs.decompiler.flash.gui.player.MediaDisplayListener; import com.jpexs.decompiler.flash.gui.player.ZoomPanel; import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; @@ -111,6 +113,30 @@ public class EasySwfPanel extends JPanel { stagePanel.setShowAllDepthLevelsInfo(false); stagePanel.setSelectionMode(true); stagePanel.setMultiSelect(true); + + stagePanel.addEventListener(new MediaDisplayListener() { + @Override + public void mediaDisplayStateChanged(MediaDisplay source) { + if (stagePanel.getTimelined() != timelined) { + View.execInEventDispatchLater(new Runnable() { + @Override + public void run() { + setTimelined(stagePanel.getTimelined(), false); + } + }); + + } + } + + @Override + public void playingFinished(MediaDisplay source) { + } + + @Override + public void statusChanged(String status) { + } + }); + stagePanel.addPlaceObjectSelectedListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -126,7 +152,8 @@ public class EasySwfPanel extends JPanel { public void run() { final List depths = stagePanel.getSelectedDepths(); final int frame = stagePanel.getFrame(); - final Matrix newMatrix = stagePanel.getNewMatrix(); + final Matrix parentMatrix = stagePanel.getParentMatrix(); + final Matrix newMatrix = parentMatrix.inverse().concatenate(stagePanel.getNewMatrix()).concatenate(parentMatrix); final Point2D regPoint = stagePanel.getRegistrationPoint(); final RegistrationPointPosition regPointPos = stagePanel.getRegistrationPointPosition(); @@ -151,14 +178,16 @@ public class EasySwfPanel extends JPanel { @Override public void doOperation() { - setTimelined(timelined); + if (timelined != EasySwfPanel.this.timelined) { + setTimelined(timelined); + } timelinePanel.setFrame(frame, depths); for (int i = 0; i < depths.size(); i++) { int depth = depths.get(i); DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth); - wasModified.add(ds.placeObjectTag.isModified()); + wasModified.add(ds.placeObjectTag.isModified()); - Matrix contMat = new Matrix(fpreviousMatrices.get(i)).preConcatenate(newMatrix); + Matrix contMat = newMatrix.concatenate(new Matrix(fpreviousMatrices.get(i))); ds.placeObjectTag.setMatrix(contMat.toMATRIX()); ds.placeObjectTag.setPlaceFlagHasMatrix(newMatrix != null); @@ -528,6 +557,9 @@ public class EasySwfPanel extends JPanel { } public void setTimelined(Timelined timelined) { + setTimelined(timelined, true); + } + private void setTimelined(Timelined timelined, boolean updateStage) { if (this.timelined == timelined) { return; } @@ -546,9 +578,11 @@ public class EasySwfPanel extends JPanel { documentPropertiesPanel.setSwf(swf); libraryTreeTable.setSwf(swf); libraryPreviewPanel.clearAll(); - stagePanel.setTimelined(timelined, swf, 0, true, true, true, true, true, false, true); - stagePanel.pause(); - stagePanel.gotoFrame(0); + if (updateStage) { + stagePanel.setTimelined(timelined, swf, 0, true, true, true, true, true, false, true); + stagePanel.pause(); + stagePanel.gotoFrame(0); + } timelinePanel.setTimelined(timelined); if (timelined instanceof SWF) { timelineLabel.setText(EasyStrings.translate("timeline.main")); @@ -645,5 +679,5 @@ public class EasySwfPanel extends JPanel { public void setFrame(int frame, List depths) { timelinePanel.setFrame(frame, depths); - } -} + } +} \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/easygui/properties/panels/InstancePropertiesPanel.java b/src/com/jpexs/decompiler/flash/easygui/properties/panels/InstancePropertiesPanel.java index 4440a4a89..0187d29df 100644 --- a/src/com/jpexs/decompiler/flash/easygui/properties/panels/InstancePropertiesPanel.java +++ b/src/com/jpexs/decompiler/flash/easygui/properties/panels/InstancePropertiesPanel.java @@ -649,7 +649,12 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel { if (dss.size() == 1) { EasyTagNameResolver resolver = new EasyTagNameResolver(); - instanceLabel.setText(EasyStrings.translate("properties.instance.single").replace("%item%", resolver.getTagName(dss.get(0).getCharacter()))); + DepthState ds = dss.get(0); + if (ds == null) { + instanceLabel.setText(""); + } else { + instanceLabel.setText(EasyStrings.translate("properties.instance.single").replace("%item%", resolver.getTagName(ds.getCharacter()))); + } } else { instanceLabel.setText(EasyStrings.translate("properties.instance.multiple").replace("%count%", "" + dss.size())); } @@ -703,6 +708,10 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel { backgroundColor.add(ds.backGroundColor); } + if (visible.size() == 0) { + return; + } + alphaPercentPropertyField.setValue(alphaPercent, true); alphaAddPropertyField.setValue(alphaAdd, true); diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index e7f97bee4..f303273b8 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -47,6 +47,8 @@ import com.jpexs.decompiler.flash.timeline.Frame; import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; +import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; +import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.ConstantColorColorTransform; import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RECT; @@ -207,10 +209,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private Point2D registrationPoint = null; private Point2D registrationPointUpdated = null; - + private int mode = Cursor.DEFAULT_CURSOR; private Rectangle2D bounds; - + private Matrix transform; private AffineTransform transformUpdated; @@ -321,7 +323,13 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private boolean inMoving = false; private List selectedDepths = new ArrayList<>(); + + private final List parentFrames = new ArrayList<>(); + + private final List parentDepths = new ArrayList<>(); + private final List parentTimelineds = new ArrayList<>(); + public boolean isMultiSelect() { return multiSelect; } @@ -1170,6 +1178,32 @@ public final class ImagePanel extends JPanel implements MediaDisplay { MouseInputAdapter mouseInputAdapter = new MouseInputAdapter() { @Override public void mouseClicked(MouseEvent e) { + + if (e.getClickCount() == 2 && selectionMode && !transformSelectionMode) { + + if (true) { //WIP, not yet ready + return; + } + + DepthState ds = depthStateUnderCursor; + if (ds != null) { + CharacterTag cht = ds.getCharacter(); + if (cht instanceof Timelined) { + synchronized(lock) { + parentTimelineds.add(timelined); + parentDepths.add(ds.depth); + parentFrames.add(ds.frame.frame); + timelined = (Timelined) cht; + selectedDepths.clear(); + frame = 0; + } + fireMediaDisplayStateChanged(); + } + } + + return; + } + if (shiftDown) { List newSelectedPoints = new ArrayList<>(pointsUnderCursor); for (int i : selectedPoints) { @@ -1498,25 +1532,32 @@ public final class ImagePanel extends JPanel implements MediaDisplay { return; } + //move in selection mode if (dragStart != null && selectionMode && !doFreeTransform) { if (transform == null) { return; - } + } + Matrix p = getParentMatrix(); + Point2D mouseTransPoint = toTransformPoint(new Point2D.Double(e.getX(), e.getY())); + //mouseTransPoint = p.transform(mouseTransPoint); double ex = mouseTransPoint.getX(); double ey = mouseTransPoint.getY(); Point2D dragStartTransPoint = toTransformPoint(dragStart); + //dragStartTransPoint = p.transform(dragStartTransPoint); double dsx = dragStartTransPoint.getX(); double dsy = dragStartTransPoint.getY(); double deltaX = ex - dsx; double deltaY = ey - dsy; + //AffineTransform pt = p.toTransform(); + AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); t.translate(deltaX, deltaY); newTransform.preConcatenate(t); - + Point2D newRegistrationPoint = new Point2D.Double(); t.transform(registrationPoint, newRegistrationPoint); @@ -1531,10 +1572,14 @@ public final class ImagePanel extends JPanel implements MediaDisplay { return; } + Matrix parentMatrix = getParentMatrix(); Point2D mouseTransPoint = toTransformPoint(new Point2D.Double(e.getX(), e.getY())); + //mouseTransPoint = parentMatrix.inverse().transform(mouseTransPoint); + double ex = mouseTransPoint.getX(); double ey = mouseTransPoint.getY(); Point2D dragStartTransPoint = toTransformPoint(dragStart); + Point2D parentRegistrationPoint = parentMatrix.transform(registrationPoint); double dsx = dragStartTransPoint.getX(); double dsy = dragStartTransPoint.getY(); @@ -1544,15 +1589,15 @@ public final class ImagePanel extends JPanel implements MediaDisplay { AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(bounds.getX(), bounds.getY()); + Point2D bStart = parentMatrix.transform(new Point2D.Double(bounds.getX(), bounds.getY())); + t.translate(bStart.getX(), bStart.getY()); t.shear(shearX, 0); - t.translate(-bounds.getX(), -bounds.getY()); + t.translate(-bStart.getX(), -bStart.getY()); t.translate(ex - dsx, 0); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1564,14 +1609,15 @@ public final class ImagePanel extends JPanel implements MediaDisplay { AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(bounds.getX(), bounds.getY()); + Point2D bStart = parentMatrix.transform(new Point2D.Double(bounds.getX(), bounds.getY())); + + t.translate(bStart.getX(), bStart.getY()); t.shear(shearX, 0); - t.translate(-bounds.getX(), -bounds.getY()); + t.translate(-bStart.getX(), -bStart.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1583,15 +1629,15 @@ public final class ImagePanel extends JPanel implements MediaDisplay { AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(bounds.getX(), bounds.getY()); + Point2D bStart = parentMatrix.transform(new Point2D.Double(bounds.getX(), bounds.getY())); + t.translate(bStart.getX(), bStart.getY()); t.shear(0, shearY); - t.translate(-bounds.getX(), -bounds.getY()); + t.translate(-bStart.getX(), -bStart.getY()); t.translate(0, ey - dsy); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1602,14 +1648,14 @@ public final class ImagePanel extends JPanel implements MediaDisplay { AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(bounds.getX(), bounds.getY()); + Point2D bStart = parentMatrix.transform(new Point2D.Double(bounds.getX(), bounds.getY())); + t.translate(bStart.getX(), bStart.getY()); t.shear(0, shearY); - t.translate(-bounds.getX(), -bounds.getY()); + t.translate(-bStart.getX(), -bStart.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1647,11 +1693,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.rotate(deltaTheta, registrationPoint.getX(), registrationPoint.getY()); + t.rotate(deltaTheta, parentRegistrationPoint.getX(), parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1689,11 +1734,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.rotate(deltaTheta, registrationPoint.getX(), registrationPoint.getY()); + t.rotate(deltaTheta, parentRegistrationPoint.getX(), parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1731,11 +1775,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.rotate(deltaTheta, registrationPoint.getX(), registrationPoint.getY()); + t.rotate(deltaTheta, parentRegistrationPoint.getX(), parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1773,11 +1816,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.rotate(deltaTheta, registrationPoint.getX(), registrationPoint.getY()); + t.rotate(deltaTheta, parentRegistrationPoint.getX(), parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1797,9 +1839,8 @@ public final class ImagePanel extends JPanel implements MediaDisplay { AffineTransform t = new AffineTransform(); t.translate(deltaX, deltaY); newTransform.preConcatenate(t); - - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1812,14 +1853,13 @@ public final class ImagePanel extends JPanel implements MediaDisplay { double scaleX = deltaX / deltaBefore; AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(registrationPoint.getX(), 0); + t.translate(parentRegistrationPoint.getX(), 0); t.scale(scaleX, 1); - t.translate(-registrationPoint.getX(), 0); + t.translate(-parentRegistrationPoint.getX(), 0); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); - + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); + transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; repaint(); @@ -1830,13 +1870,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { double scaleX = deltaX / deltaBefore; AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(registrationPoint.getX(), 0); + t.translate(parentRegistrationPoint.getX(), 0); t.scale(scaleX, 1); - t.translate(-registrationPoint.getX(), 0); + t.translate(-parentRegistrationPoint.getX(), 0); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1849,13 +1888,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { double scaleY = deltaY / deltaBefore; AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(0, registrationPoint.getY()); + t.translate(0, parentRegistrationPoint.getY()); t.scale(1, scaleY); - t.translate(0, -registrationPoint.getY()); + t.translate(0, -parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1867,13 +1905,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { double scaleY = deltaY / deltaBefore; AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(0, registrationPoint.getY()); + t.translate(0, parentRegistrationPoint.getY()); t.scale(1, scaleY); - t.translate(0, -registrationPoint.getY()); + t.translate(0, -parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1888,13 +1925,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { double scaleY = deltaY / deltaYBefore; AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(registrationPoint.getX(), registrationPoint.getY()); + t.translate(parentRegistrationPoint.getX(), parentRegistrationPoint.getY()); t.scale(scaleX, scaleY); - t.translate(-registrationPoint.getX(), -registrationPoint.getY()); + t.translate(-parentRegistrationPoint.getX(), -parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1910,13 +1946,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { double scaleY = deltaY / deltaYBefore; AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(registrationPoint.getX(), registrationPoint.getY()); + t.translate(parentRegistrationPoint.getX(), parentRegistrationPoint.getY()); t.scale(scaleX, scaleY); - t.translate(-registrationPoint.getX(), -registrationPoint.getY()); + t.translate(-parentRegistrationPoint.getX(), -parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1932,13 +1967,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { double scaleY = deltaY / deltaYBefore; AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(registrationPoint.getX(), registrationPoint.getY()); + t.translate(parentRegistrationPoint.getX(), parentRegistrationPoint.getY()); t.scale(scaleX, scaleY); - t.translate(-registrationPoint.getX(), -registrationPoint.getY()); + t.translate(-parentRegistrationPoint.getX(), -parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -1954,13 +1988,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { double scaleY = deltaY / deltaYBefore; AffineTransform newTransform = new AffineTransform(transform.toTransform()); AffineTransform t = new AffineTransform(); - t.translate(registrationPoint.getX(), registrationPoint.getY()); + t.translate(parentRegistrationPoint.getX(), parentRegistrationPoint.getY()); t.scale(scaleX, scaleY); - t.translate(-registrationPoint.getX(), -registrationPoint.getY()); + t.translate(-parentRegistrationPoint.getX(), -parentRegistrationPoint.getY()); newTransform.preConcatenate(t); - Point2D newRegistrationPoint = new Point2D.Double(); - t.transform(registrationPoint, newRegistrationPoint); + Point2D newRegistrationPoint = new Matrix(t).preConcatenate(parentMatrix.inverse()).concatenate(parentMatrix).transform(registrationPoint); transformUpdated = newTransform; registrationPointUpdated = newRegistrationPoint; @@ -2242,7 +2275,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private void calcRect(Zoom z) { synchronized (ImagePanel.this) { - if (_img != null || timelined != null) { + + + Timelined topTimelined = getTopTimelined(); + if (_img != null || topTimelined != null) { //int w1 = (int) (_img.getWidth() * (lowQuality ? LQ_FACTOR : 1)); //int h1 = (int) (_img.getHeight() * (lowQuality ? LQ_FACTOR : 1)); double zoomDouble = z.fit ? getZoomToFit() : z.value; @@ -2250,16 +2286,16 @@ public final class ImagePanel extends JPanel implements MediaDisplay { int h1; int dx; int dy; - if (timelined == null || (!autoPlayed && _img != null)) { + if (topTimelined == null || (!autoPlayed && _img != null)) { w1 = (int) (_img.getWidth() * (lowQuality ? LQ_FACTOR : 1)); h1 = (int) (_img.getHeight() * (lowQuality ? LQ_FACTOR : 1)); dx = 0; dy = 0; } else { - w1 = (int) (timelined.getRect().getWidth() * zoomDouble / SWF.unitDivisor); - h1 = (int) (timelined.getRect().getHeight() * zoomDouble / SWF.unitDivisor); - dx = (int) (timelined.getRect().Xmin * zoomDouble / SWF.unitDivisor); - dy = (int) (timelined.getRect().Ymin * zoomDouble / SWF.unitDivisor); + w1 = (int) (topTimelined.getRect().getWidth() * zoomDouble / SWF.unitDivisor); + h1 = (int) (topTimelined.getRect().getHeight() * zoomDouble / SWF.unitDivisor); + dx = (int) (topTimelined.getRect().Xmin * zoomDouble / SWF.unitDivisor); + dy = (int) (topTimelined.getRect().Ymin * zoomDouble / SWF.unitDivisor); } //HERE @@ -2929,6 +2965,9 @@ public final class ImagePanel extends JPanel implements MediaDisplay { bounds = null; displayObjectCache.clear(); this.timelined = drawable; + this.parentTimelineds.clear(); + this.parentFrames.clear(); + this.parentDepths.clear(); centerImage(); this.swf = swf; zoomAvailable = allowZoom; @@ -3151,8 +3190,23 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } fireMediaDisplayStateChanged(); } + + public Matrix getParentMatrix() { + synchronized (lock) { + Matrix parentMatrix = new Matrix(); + for (int i = 0; i < parentTimelineds.size(); i++) { + DepthState parentDepthState = parentTimelineds.get(i).getTimeline().getDepthState(parentFrames.get(i), parentDepths.get(i)); - private static SerializableImage getFrame(Rectangle realRect, RECT rect, ExportRectangle viewRect, SWF swf, int frame, int time, Timelined drawable, RenderContext renderContext, List selectedDepths, boolean doFreeTransform, double zoom, Reference registrationPointRef, Reference boundsRef, Matrix transform, Matrix temporaryMatrix, Matrix newMatrix, boolean selectionMode) { + parentMatrix = parentMatrix.concatenate(new Matrix(parentDepthState.matrix)); + } + return parentMatrix; + } + } + + private static SerializableImage getFrame(Rectangle realRect, RECT rect, ExportRectangle viewRect, SWF swf, int frame, int time, Timelined drawable, RenderContext renderContext, List selectedDepths, boolean doFreeTransform, double zoom, Reference registrationPointRef, Reference boundsRef, Matrix transform, Matrix temporaryMatrix, Matrix newMatrix, boolean selectionMode, + List parentTimelineds, List parentDepths, List parentFrames, + Matrix parentMatrix + ) { Timeline timeline = drawable.getTimeline(); SerializableImage img; @@ -3173,7 +3227,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { m.scale(zoom); Matrix fullM = m.clone(); - + for (int i = 0; i < selectedDepths.size(); i++) { if (newMatrix != null) { DepthState ds = timeline.getFrame(frame).layers.get(selectedDepths.get(i)); @@ -3184,17 +3238,45 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } Frame fr = timeline.getFrame(frame); - if (fr == null) { + + Frame bgFr = timeline.getFrame(frame); + + if (!parentTimelineds.isEmpty()) { + bgFr = parentTimelineds.get(0).getTimeline().getFrame(parentFrames.get(0)); + } + + if (bgFr == null || fr == null) { return image; } - RGB backgroundColor = fr.backgroundColor; + RGB backgroundColor = bgFr.backgroundColor; if (backgroundColor != null) { Graphics2D g = (Graphics2D) image.getBufferedImage().getGraphics(); g.setPaint(backgroundColor.toColor()); g.fillRect(realRect.x, realRect.y, realRect.width, realRect.height); + } + + + parentMatrix = new Matrix(); + List ignoreDepths = new ArrayList<>(); + for (int i = 0; i < parentTimelineds.size(); i++) { + Timelined parentTimelined = parentTimelineds.get(i); + DepthState parentDepthState = parentTimelineds.get(i).getTimeline().getDepthState(parentFrames.get(i), parentDepths.get(i)); + + ignoreDepths.add(parentDepthState.depth); + parentTimelined.getTimeline().toImage(parentFrames.get(i), 0, new RenderContext(), image, image, false, + parentMatrix.preConcatenate(m), new Matrix(), parentMatrix.preConcatenate(m), null, zoom, true, viewRect, parentMatrix.preConcatenate(m), true, Timeline.DRAW_MODE_ALL, 0, !Configuration.disableBitmapSmoothing.get(), + ignoreDepths); + parentMatrix = parentMatrix.concatenate(new Matrix(parentDepthState.matrix)); + ignoreDepths.clear(); } - - timeline.toImage(frame, time, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, viewRect, fullM, true, Timeline.DRAW_MODE_ALL, 0, !Configuration.disableBitmapSmoothing.get()); + + if (!parentTimelineds.isEmpty()) { + Graphics2D g = (Graphics2D) image.getBufferedImage().getGraphics(); + g.setPaint(new Color(255, 255, 255, 128)); + g.fillRect(realRect.x, realRect.y, realRect.width, realRect.height); + } + + timeline.toImage(frame, time, renderContext, image, image, false, parentMatrix.preConcatenate(m), new Matrix(), parentMatrix.preConcatenate(m), null, zoom, true, viewRect, parentMatrix.preConcatenate(m), true, Timeline.DRAW_MODE_ALL, 0, !Configuration.disableBitmapSmoothing.get(), ignoreDepths); Graphics2D gg = (Graphics2D) image.getGraphics(); gg.setStroke(new BasicStroke(3)); @@ -3219,7 +3301,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } int dframe = time % drawableFrameCount; - Matrix transformation = Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m.concatenate(new Matrix(ds.matrix))); + Matrix transformation = Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m.concatenate(parentMatrix).concatenate(new Matrix(ds.matrix))); RECT dtRect = dt.getRect(); Rectangle2D dtRect2D = new Rectangle2D.Double(dtRect.Xmin, dtRect.Ymin, dtRect.getWidth(), dtRect.getHeight()); Shape outline = transformation.toTransform().createTransformedShape(dtRect2D); @@ -3259,7 +3341,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Matrix transform2 = transform; - transform2 = transform2.concatenate(new Matrix(ds.matrix)); + transform2 = transform.concatenate(new Matrix(ds.matrix)); Shape outline = dt.getOutline(true, dframe, time, ds.ratio, renderContext, transform2, true, viewRect, zoom); @@ -3487,6 +3569,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { cursorPosition = this.cursorPosition; if (cursorPosition != null) { Point2D p2d = toTransformPoint(cursorPosition); + //p2d = getParentMatrix().inverse().transform(p2d); cursorPosition = new Point((int) Math.round(p2d.getX() / SWF.unitDivisor), (int) Math.round(p2d.getY() / SWF.unitDivisor)); } @@ -3507,6 +3590,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { renderContext.displayObjectCache = displayObjectCache; if (cursorPosition != null && (!doFreeTransform || transformSelectionMode)) { renderContext.cursorPosition = new Point((int) (cursorPosition.x * SWF.unitDivisor), (int) (cursorPosition.y * SWF.unitDivisor)); + renderContext.cursorPosition = getParentMatrix().transform(renderContext.cursorPosition); } renderContext.mouseButton = mouseButton; @@ -3538,17 +3622,19 @@ public final class ImagePanel extends JPanel implements MediaDisplay { synchronized (lock) { Reference boundsRef = new Reference<>(null); - RECT rect = timelined.getRect(); + RECT rect = getTopTimelined().getRect(); _viewRect = getViewRect(); Matrix trans2 = transform == null ? new Matrix() : transform.clone(); trans2 = toImageMatrix(trans2); - + AffineTransform tempTrans2 = null; if (transformUpdated != null) { Matrix matrixUpdated = new Matrix(transformUpdated); + //Matrix p = getParentMatrix(); + //matrixUpdated = p.concatenate(matrixUpdated); matrixUpdated = toImageMatrix(matrixUpdated); tempTrans2 = matrixUpdated.toTransform(); } @@ -3596,7 +3682,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } else if (_viewRect.getHeight() < 0 || _viewRect.getWidth() < 0) { img = new SerializableImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR); } else { - img = getFrame(realRect, rect, _viewRect, swf, frame, frozen ? 0 : time, timelined, renderContext, selectedDepths, doFreeTransform, zoomDouble, registrationPointRef, boundsRef, trans2, tempTrans2 == null ? null : new Matrix(tempTrans2), transform, selectionMode); + img = getFrame(realRect, rect, _viewRect, swf, frame, frozen ? 0 : time, timelined, renderContext, selectedDepths, doFreeTransform, zoomDouble, registrationPointRef, boundsRef, trans2, tempTrans2 == null ? null : new Matrix(tempTrans2), transform, selectionMode, parentTimelineds, parentDepths, parentFrames, getParentMatrix()); } /*if(freeTransformDepth > -1) { @@ -4206,7 +4292,9 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } public void applyTransformMatrix(Matrix matrix) { + Matrix parentMatrix = getParentMatrix(); transform = transform.preConcatenate(matrix); + transform = parentMatrix.concatenate(transform).concatenate(parentMatrix.inverse()); Point2D newRegistrationPoint = new Point2D.Double(); matrix.toTransform().transform(registrationPoint, newRegistrationPoint); @@ -4217,15 +4305,16 @@ public final class ImagePanel extends JPanel implements MediaDisplay { fireTransformChanged(); } - private Point2D toTransformPoint(Point2D point) { + private Point2D toTransformPoint(Point2D point) { double zoomDouble = zoom.fit ? getZoomToFit() : zoom.value; if (lowQuality) { zoomDouble /= LQ_FACTOR; } - RECT timRect = timelined.getRect(); + //RECT timRect = timelined.getRect(); double rx = (point.getX() - offsetPoint.getX()) * SWF.unitDivisor / zoomDouble; // + timRect.Xmin; double ry = (point.getY() - offsetPoint.getY()) * SWF.unitDivisor / zoomDouble; // + timRect.Ymin; Point2D ret = new Point2D.Double(rx, ry); + ret = getParentMatrix().inverse().transform(ret); return ret; } @@ -4239,10 +4328,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { m.translate(-_viewRect.xMin * zoom, -_viewRect.yMin * zoom); m.scale(zoom); - return Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m).concatenate(transform); + Matrix p = getParentMatrix(); + return Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m).concatenate(transform).concatenate(p); } private Point2D toImagePoint(Point2D point) { + point = getParentMatrix().transform(point); double zoomDouble = zoom.fit ? getZoomToFit() : zoom.value; if (lowQuality) { zoomDouble /= LQ_FACTOR; @@ -4259,6 +4350,17 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Point2D bottomRight = toImagePoint(new Point2D.Double(rect.getMaxX(), rect.getMaxY())); return new Rectangle2D.Double(topLeft.getX(), topLeft.getY(), bottomRight.getX() - topLeft.getX(), bottomRight.getY() - topLeft.getY()); } + + private Point2D toParentPoint(Point2D point) { + point = getParentMatrix().transform(point); + return point; + } + + private Rectangle2D toParentRect(Rectangle2D rect) { + Point2D topLeft = toParentPoint(new Point2D.Double(rect.getMinX(), rect.getMinY())); + Point2D bottomRight = toParentPoint(new Point2D.Double(rect.getMaxX(), rect.getMaxY())); + return new Rectangle2D.Double(topLeft.getX(), topLeft.getY(), bottomRight.getX() - topLeft.getX(), bottomRight.getY() - topLeft.getY()); + } private Rectangle2D getTransformBounds() { if (timelined == null) { @@ -4305,7 +4407,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { drawableFrameCount = 1; } - Matrix b = newMatrix; //.concatenate(new Matrix(ds.matrix).inverse()); + Matrix b = newMatrix; //getParentMatrix().concatenate(newMatrix); //.concatenate(new Matrix(ds.matrix).inverse()); int dframe = time % drawableFrameCount; double zoomDouble = zoom.fit ? getZoomToFit() : zoom.value; if (lowQuality) { @@ -4342,4 +4444,13 @@ public final class ImagePanel extends JPanel implements MediaDisplay { this.closestPoint = closestPoint; } } + + public Timelined getTopTimelined() { + synchronized (lock) { + if (!parentTimelineds.isEmpty()) { + return parentTimelineds.get(0); + } + return timelined; + } + } }