From ea8fb5618930c69c92e4c2a0f6b16668d125c8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 11 Dec 2022 20:58:25 +0100 Subject: [PATCH] Added Free transform whole sprites --- CHANGELOG.md | 2 + .../decompiler/flash/gui/ImagePanel.java | 268 ++++++++++++++---- .../jpexs/decompiler/flash/gui/MainPanel.java | 12 +- .../decompiler/flash/gui/PreviewPanel.java | 231 ++++++++++++--- .../flash/gui/SelectTagPositionDialog.java | 4 +- .../flash/gui/action/AddScriptDialog.java | 22 +- .../flash/gui/player/PlayerControls.java | 5 +- 7 files changed, 425 insertions(+), 119 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5352e9c3..4b7c63975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. - Experimental option to fix conflation artifacts in antialising (slow) - Option to disable autoplay of sounds (DefineSound) - [#1181] Remembering choice of loading assets via importassets tag +- [#1900] Free transform whole sprites ### Fixed - [#1897] Close menu button without selecting specific item @@ -2729,6 +2730,7 @@ All notable changes to this project will be documented in this file. [#1697]: https://www.free-decompiler.com/flash/issues/1697 [#1893]: https://www.free-decompiler.com/flash/issues/1893 [#1181]: https://www.free-decompiler.com/flash/issues/1181 +[#1900]: https://www.free-decompiler.com/flash/issues/1900 [#1897]: https://www.free-decompiler.com/flash/issues/1897 [#1006]: https://www.free-decompiler.com/flash/issues/1006 [#1828]: https://www.free-decompiler.com/flash/issues/1828 diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 67f968c7b..850134313 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -48,6 +48,7 @@ import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; import com.jpexs.decompiler.flash.types.ConstantColorColorTransform; import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.SOUNDINFO; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Cache; @@ -88,6 +89,7 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.VolatileImage; +import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; @@ -289,7 +291,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { return imgPlay; } - + static { try { moveCursor = loadCursor("move", 0, 0); @@ -320,18 +322,16 @@ public final class ImagePanel extends JPanel implements MediaDisplay { CharacterTag cht = ds.getCharacter(); if (cht != null) { if (cht instanceof DrawableTag) { - RECT rect = timelined.getRect(); - Matrix m = new Matrix(); double zoomDouble = zoom.fit ? getZoomToFit() : zoom.value; if (lowQuality) { zoomDouble /= LQ_FACTOR; } + double zoom = zoomDouble; - m.translate(-rect.Xmin * zoom, -rect.Ymin * zoom); - m.scale(zoom); - - Matrix eMatrix = Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m).inverse(); - eMatrix.translate(_rect.x < 0 ? -_rect.x : 0, _rect.y < 0 ? -_rect.y : 0); + Matrix m2 = new Matrix(); + m2.translate(-_viewRect.xMin * zoom, -_viewRect.yMin * zoom); + m2.scale(zoom); + Matrix eMatrix = Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m2).inverse(); return transform.preConcatenate(eMatrix).toMATRIX(); } @@ -358,6 +358,9 @@ public final class ImagePanel extends JPanel implements MediaDisplay { ds = timeline.getFrame(frame).layers.get(freeTransformDepth); } + _rect = null; + _viewRect = getViewRect(); + if (ds != null) { CharacterTag cht = ds.getCharacter(); if (cht != null) { @@ -377,6 +380,21 @@ public final class ImagePanel extends JPanel implements MediaDisplay { m.scale(zoom); transform = Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m).concatenate(new Matrix(ds.matrix)); + /*System.out.println("ds.matrix=" + ds.matrix); + System.out.println("transform=" + transform); + System.out.println("offset=" + offsetPoint); + System.out.println("_viewRect.xMin=" + (_viewRect.xMin * zoom / SWF.unitDivisor)); + System.out.println("_viewRect.yMin=" + (_viewRect.yMin * zoom / SWF.unitDivisor)); + System.out.println("zoomDouble=" + zoomDouble); + System.out.println("_viewRect="+_viewRect); + + Matrix m2 = new Matrix(); + m2.translate(-_viewRect.xMin * zoom, -_viewRect.yMin * zoom); + m2.scale(zoom); + Matrix eMatrix = Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m2).inverse(); + + Matrix newMatrix = transform.preConcatenate(eMatrix); + System.out.println("newMatrix="+newMatrix);*/ } } } @@ -511,12 +529,31 @@ public final class ImagePanel extends JPanel implements MediaDisplay { g2.setComposite(AlphaComposite.SrcOver); if (rect != null && img != null) { - int x = rect.x < 0 ? 0 : rect.x; - int y = rect.y < 0 ? 0 : rect.y; - g2.drawImage(img.getBufferedImage(), x, y, x + img.getWidth(), y + img.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null); - - /*g2.setColor(Color.red); - g2.drawRect(x, y, img.getWidth(), img.getHeight());*/ + int x = rect.x;//< 0 ? 0 : rect.x; + int y = rect.y;// < 0 ? 0 : rect.y; + + if(freeTransformDepth > -1) { + RECT timRect = timelined.getRectWithStrokes(); + double zoomDouble = zoom.fit ? getZoomToFit() : zoom.value; + int offsetX = (int) (SWF.unitDivisor * iconPanel.getWidth() / zoomDouble / 2 - timRect.getWidth() / 2); + int offsetY = (int) (SWF.unitDivisor * iconPanel.getHeight() / zoomDouble / 2 - timRect.getHeight() / 2); + offsetX *= zoomDouble; + offsetY *= zoomDouble; + offsetX /= SWF.unitDivisor; + offsetY /= SWF.unitDivisor; + + if (offsetX < 0) { + offsetX = -offsetX; + } + if (offsetY < 0) { + offsetY = -offsetY; + } + + x -= offsetX; + y -= offsetY; + } + + g2.drawImage(img.getBufferedImage(), x, y, x + img.getWidth(), y + img.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null); } } finally { if (g2 != null) { @@ -603,6 +640,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Point delta = new Point(dragEnd.x - dragStart.x, dragEnd.y - dragStart.y); offsetPoint.x += delta.x; offsetPoint.y += delta.y; + + //offsetPoint.x = 0; //FIXME + //offsetPoint.y = 0; //FIXME + ExportRectangle oldViewRect = new ExportRectangle(_viewRect); dragStart = dragEnd; iconPanel.calcRect(); @@ -648,10 +689,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { return; } - int ex = e.getX() - (_rect.x < 0 ? 0 : _rect.x); - int ey = e.getY() - (_rect.y < 0 ? 0 : _rect.y); - int dsx = dragStart.x - (_rect.x < 0 ? 0 : _rect.x); - int dsy = dragStart.y - (_rect.y < 0 ? 0 : _rect.y); + int ex = e.getX();// - (_rect.x < 0 ? 0 : _rect.x); + int ey = e.getY();// - (_rect.y < 0 ? 0 : _rect.y); + int dsx = dragStart.x;// - (_rect.x < 0 ? 0 : _rect.x); + int dsy = dragStart.y;// - (_rect.y < 0 ? 0 : _rect.y); if (mode == MODE_SHEAR_N) { @@ -1094,14 +1135,14 @@ public final class ImagePanel extends JPanel implements MediaDisplay { return; } - int ex = e.getX() - (_rect.x < 0 ? 0 : _rect.x); - int ey = e.getY() - (_rect.y < 0 ? 0 : _rect.y); - + int ex = e.getX();// - (_rect.x < 0 ? 0 : _rect.x); + int ey = e.getY();// - (_rect.y < 0 ? 0 : _rect.y); + boolean left = ex >= bounds.getX() - TOLERANCE_SCALESHEAR && ex <= bounds.getX() + TOLERANCE_SCALESHEAR; boolean right = ex >= bounds.getX() + bounds.getWidth() - TOLERANCE_SCALESHEAR && ex <= bounds.getX() + bounds.getWidth() + TOLERANCE_SCALESHEAR; boolean top = ey >= bounds.getY() - TOLERANCE_SCALESHEAR && ey <= bounds.getY() + TOLERANCE_SCALESHEAR; - boolean bottom = ey >= bounds.getY() + bounds.getHeight() - TOLERANCE_SCALESHEAR && ey <= bounds.getY() + bounds.getHeight() + TOLERANCE_SCALESHEAR; - + boolean bottom = ey >= bounds.getY() + bounds.getHeight() - TOLERANCE_SCALESHEAR && ey <= bounds.getY() + bounds.getHeight() + TOLERANCE_SCALESHEAR; + boolean xcenter = ex >= bounds.getCenterX() - TOLERANCE_SCALESHEAR && ex <= bounds.getCenterX() + TOLERANCE_SCALESHEAR; boolean ycenter = ey >= bounds.getCenterY() - TOLERANCE_SCALESHEAR && ey <= bounds.getCenterY() + TOLERANCE_SCALESHEAR; @@ -1280,6 +1321,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { h1 = (int) (timelined.getRectWithStrokes().getHeight() * zoomDouble / SWF.unitDivisor); } + //HERE + if (freeTransformDepth > -1) { + //w1 = Math.max(w1, getWidth()); + //h1 = Math.max(h1, getHeight()); + } + int w2 = getWidth(); int h2 = getHeight(); @@ -1304,7 +1351,14 @@ public final class ImagePanel extends JPanel implements MediaDisplay { h = h1; } - setAllowMove(h > h2 || w > w2); + if (freeTransformDepth > -1) { + setAllowMove(true); + + //return new Rectangle(0,0 /*offsetPoint.x, offsetPoint.y*/, w1 - offsetPoint.x, h1 - offsetPoint.y); + //return new Rectangle(offsetPoint.x, offsetPoint.y,w, h); + } else { + setAllowMove(h > h2 || w > w2); + } Rectangle r2 = new Rectangle(getWidth() / 2 - w / 2 + offsetPoint.x, getHeight() / 2 - h / 2 + offsetPoint.y, w, h); return r2; } @@ -1553,7 +1607,13 @@ public final class ImagePanel extends JPanel implements MediaDisplay { offsetPoint.x = (int) (offsetPoint.x * zoomDouble / zoomDoubleBefore); offsetPoint.y = (int) (offsetPoint.y * zoomDouble / zoomDoubleBefore); iconPanel.calcRect(); - _viewRect = getViewRect(); + _viewRect = getViewRect(); + + double deltaX = (_viewRect.xMin - oldViewRect.xMin)*zoomDouble/SWF.unitDivisor; + offsetPoint.x += deltaX / 2; + double deltaY = (_viewRect.yMin - oldViewRect.yMin) * zoomDouble/SWF.unitDivisor; + offsetPoint.y += deltaY / 2; + synchronized (lock) { if (transform != null) { @@ -1897,10 +1957,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { fireMediaDisplayStateChanged(); } - private static SerializableImage getFrame(ExportRectangle viewRect, SWF swf, int frame, int time, Timelined drawable, RenderContext renderContext, int selectedDepth, int freeTransformDepth, double zoom, Reference registrationPointRef, Reference boundsRef, Matrix transform, Matrix temporaryMatrix) { + private static SerializableImage getFrame(Rectangle realRect, RECT rect, ExportRectangle viewRect, SWF swf, int frame, int time, Timelined drawable, RenderContext renderContext, int selectedDepth, int freeTransformDepth, double zoom, Reference registrationPointRef, Reference boundsRef, Matrix transform, Matrix temporaryMatrix) { Timeline timeline = drawable.getTimeline(); SerializableImage img; - RECT rect = drawable.getRect(); + //RECT rect = drawable.getRect(); int width = (int) (viewRect.getWidth() * zoom); //int) (rect.getWidth() * zoom); int height = (int) (viewRect.getHeight() * zoom);//(int) (rect.getHeight() * zoom);(int) (rect.getHeight() * zoom); @@ -1925,13 +1985,22 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Matrix eMatrix = Matrix.getScaleInstance(1 / SWF.unitDivisor).concatenate(m).inverse(); - MATRIX newMatrix = transform.preConcatenate(eMatrix).toMATRIX(); + + Matrix nm = transform.preConcatenate(eMatrix); + MATRIX newMatrix = nm.toMATRIX(); oldMatrix = timeline.getFrame(frame).layers.get(freeTransformDepth).matrix; timeline.getFrame(frame).layers.get(freeTransformDepth).matrix = newMatrix; } - - timeline.toImage(frame, time, renderContext, image, image, false, m, new Matrix(), m, null, zoom, false, viewRect, fullM, true, Timeline.DRAW_MODE_ALL, 0); + + RGB backgroundColor = timeline.getFrame(frame).backgroundColor; + if (backgroundColor != null) { + Graphics2D g = (Graphics2D)image.getBufferedImage().getGraphics(); + g.setPaint(backgroundColor.toColor()); + g.fillRect(realRect.x, realRect.y, realRect.width, realRect.height); + } + + timeline.toImage(frame, time, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, viewRect, fullM, true, Timeline.DRAW_MODE_ALL, 0); Graphics2D gg = (Graphics2D) image.getGraphics(); gg.setStroke(new BasicStroke(3)); @@ -1998,10 +2067,14 @@ public final class ImagePanel extends JPanel implements MediaDisplay { gg.draw(bounds); drawHandles(gg, bounds); - if (registrationPointRef.getVal() == null) { - registrationPointRef.setVal(new Point2D.Double(bounds.getCenterX(), bounds.getCenterY())); + Point2D regPoint = registrationPointRef.getVal(); + if (regPoint == null) { + regPoint = new Point2D.Double(bounds.getCenterX(), bounds.getCenterY()); } - drawRegistrationPoint(gg, registrationPointRef.getVal()); + /*if (registrationPointRef.getVal() == null) { + registrationPointRef.setVal(new Point2D.Double(bounds.getCenterX(), bounds.getCenterY())); + }*/ + drawRegistrationPoint(gg, regPoint); } } } @@ -2151,7 +2224,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } if (w + aRect.xMin > iconPanel.getWidth()) { - w = -aRect.xMin + iconPanel.getWidth(); + //w = -aRect.xMin + iconPanel.getWidth(); } viewRect.xMax = w; @@ -2165,7 +2238,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } if (h + aRect.yMin > iconPanel.getHeight()) { - h = -aRect.yMin + iconPanel.getHeight(); + //h = -aRect.yMin + iconPanel.getHeight(); } viewRect.yMax = h; @@ -2184,6 +2257,24 @@ public final class ImagePanel extends JPanel implements MediaDisplay { viewRect.yMin += timRect.Ymin; viewRect.xMax += timRect.Xmin; viewRect.yMax += timRect.Ymin; + + if (freeTransformDepth > -1) { + int offsetX = (int) (SWF.unitDivisor * iconPanel.getWidth() / zoomDouble / 2 - timRect.getWidth() / 2); + int offsetY = (int) (SWF.unitDivisor * iconPanel.getHeight() / zoomDouble / 2 - timRect.getHeight() / 2); + if (offsetX < 0) { + offsetX = -offsetX; + } + if (offsetY < 0) { + offsetY = -offsetY; + } + viewRect.xMin -= offsetX; + viewRect.yMin -= offsetY; + //viewRect.xMax = viewRect.xMin + (int) (iconPanel.getWidth() * SWF.unitDivisor / zoomDouble); + //viewRect.yMax = viewRect.yMin + (int) (iconPanel.getHeight() * SWF.unitDivisor / zoomDouble); + viewRect.xMax = Math.max(viewRect.xMin, 0) + (int) (iconPanel.getWidth() * SWF.unitDivisor);// / zoomDouble); + viewRect.yMax = Math.max(viewRect.yMin, 0) + (int) (iconPanel.getHeight() * SWF.unitDivisor); // / zoomDouble); + + } return viewRect; } @@ -2265,30 +2356,97 @@ public final class ImagePanel extends JPanel implements MediaDisplay { synchronized (ImagePanel.this) { synchronized (lock) { Reference registrationPointRef = new Reference<>(registrationPoint); - Reference boundsRef = new Reference<>(bounds); + Reference boundsRef = new Reference<>(null); + + RECT rect = timelined.getRectWithStrokes(); _viewRect = getViewRect(); + + Matrix trans2 = transform == null ? null : transform.clone(); + AffineTransform tempTrans2 = transformUpdated == null ? null : new AffineTransform(transformUpdated); + + //HERE + + RECT timRect = timelined.getRectWithStrokes(); + int offsetX = (int) (SWF.unitDivisor * iconPanel.getWidth() / zoomDouble / 2 - timRect.getWidth() / 2); + int offsetY = (int) (SWF.unitDivisor * iconPanel.getHeight() / zoomDouble / 2 - timRect.getHeight() / 2); + offsetX *= zoomDouble; + offsetY *= zoomDouble; + offsetX /= SWF.unitDivisor; + offsetY /= SWF.unitDivisor; + + + + if (offsetX < 0) { + offsetX = -offsetX; + //offsetX = 0; + } + if (offsetY < 0) { + offsetY = -offsetY; + //offsetY = 0; + } + + offsetX = -offsetX; + offsetY = -offsetY; + + + + if (!autoPlayed) { - img = getImagePlay(); - /*new SerializableImage( - (int) (_viewRect.getWidth() / SWF.unitDivisor), - (int) (_viewRect.getHeight() / SWF.unitDivisor), - BufferedImage.TYPE_4BYTE_ABGR); - SerializableImage imgPlay = getImagePlay(); - Graphics g = img.getGraphics(); - int x = (int) (_viewRect.getWidth() / SWF.unitDivisor / 2 - imgPlay.getWidth() / 2); - int y = (int) (_viewRect.getHeight() / SWF.unitDivisor / 2 - imgPlay.getHeight() / 2); - g.drawImage(imgPlay.getBufferedImage(), - x, - y, - null);*/ + img = getImagePlay(); } else if (_viewRect.getHeight() < 0 || _viewRect.getWidth() < 0) { img = new SerializableImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR); } else { - img = getFrame(_viewRect, swf, frame, frozen ? 0 : time, timelined, renderContext, selectedDepth, freeTransformDepth, zoomDouble, registrationPointRef, boundsRef, transform, transformUpdated == null ? null : new Matrix(transformUpdated)); + Rectangle realRect = new Rectangle(rect.Xmin, rect.Ymin, rect.Xmax-rect.Xmin, rect.Ymax-rect.Ymin); + realRect.x *= zoomDouble; + realRect.y *= zoomDouble; + realRect.width *= zoomDouble; + realRect.height *= zoomDouble; + realRect.x /= SWF.unitDivisor; + realRect.y /= SWF.unitDivisor; + realRect.width /= SWF.unitDivisor; + realRect.height /= SWF.unitDivisor; + + if (freeTransformDepth > -1) { + realRect.x = -offsetX; + realRect.y = -offsetY; + if (_rect.x < 0) { + realRect.x += _rect.x; + } + if (_rect.y < 0) { + realRect.y += _rect.y; + } + } + + img = getFrame(realRect, rect, _viewRect, swf, frame, frozen ? 0 : time, timelined, renderContext, selectedDepth, freeTransformDepth, zoomDouble, registrationPointRef, boundsRef, trans2, tempTrans2 == null ? null : new Matrix(tempTrans2)); } - bounds = boundsRef.getVal(); - registrationPoint = registrationPointRef.getVal(); + /*if(freeTransformDepth > -1) { + Graphics2D gg = (Graphics2D)img.getBufferedImage().getGraphics(); + gg.setColor(Color.red); + gg.fillRect(0, 0, img.getWidth(), img.getHeight()); + }*/ + + + offsetX += _rect.x; + offsetY += _rect.y; + + Rectangle2D newBounds = boundsRef.getVal(); + if (newBounds!=null) { + newBounds = new Rectangle2D.Double( + newBounds.getMinX() + offsetX, + newBounds.getMinY() + offsetY, + newBounds.getWidth(), + newBounds.getHeight() + ); + if (registrationPoint == null) { + registrationPoint = new Point2D.Double( + newBounds.getCenterX(), + newBounds.getCenterY()); + } + } + if (newBounds != null) { + bounds = newBounds; + } } } @@ -2792,7 +2950,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Rectangle curRect = iconPanel.calcRect(zoom); Rectangle newRect = iconPanel.calcRect(newZoom); - + offsetPoint.x = (int) (aCursor.x + curRect.x + offsetPoint.x - aCursor.x * newZoom.value / zoom.value - newRect.x); offsetPoint.y = (int) (aCursor.y + curRect.y + offsetPoint.y - aCursor.y * newZoom.value / zoom.value - newRect.y); @@ -2814,13 +2972,13 @@ public final class ImagePanel extends JPanel implements MediaDisplay { Rectangle curRect = iconPanel.calcRect(zoom); Rectangle newRect = iconPanel.calcRect(newZoom); - + offsetPoint.x = (int) (aCursor.x + curRect.x + offsetPoint.x - aCursor.x * newZoom.value / zoom.value - newRect.x); offsetPoint.y = (int) (aCursor.y + curRect.y + offsetPoint.y - aCursor.y * newZoom.value / zoom.value - newRect.y); //zoom method does the opposite: offsetPoint.x = (int) (offsetPoint.x * zoom.value / newZoom.value); - offsetPoint.y = (int) (offsetPoint.y * zoom.value / newZoom.value); + offsetPoint.y = (int) (offsetPoint.y * zoom.value / newZoom.value); } zoom(newZoom); } diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index a7eac7550..ea707b5c6 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -4653,7 +4653,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (treeItem instanceof SWF) { SWF swf = (SWF) treeItem; if (internalViewer) { - previewPanel.showImagePanel(swf, swf, -1, true, Configuration.autoPlaySwfs.get() && Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + previewPanel.showImagePanel(swf, swf, -1, true, Configuration.autoPlaySwfs.get() && Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, true); } else { previewPanel.setParametersPanelVisible(false); //if (flashPanel != null) { //same for flashPanel2 @@ -4680,7 +4680,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se ImageTag imageTag = (ImageTag) treeItem; previewPanel.setImageReplaceButtonVisible(!((Tag) imageTag).isReadOnly() && imageTag.importSupported(), imageTag instanceof DefineBitsJPEG3Tag || imageTag instanceof DefineBitsJPEG4Tag, false, false); SWF imageSWF = makeTimelinedImage(imageTag); - previewPanel.showImagePanel(imageSWF, imageSWF, 0, false, true, true, true, true, false); + previewPanel.showImagePanel(imageSWF, imageSWF, 0, false, true, true, true, true, false, false); } else if (!isVideoButNotDrawable && (treeItem instanceof DrawableTag) && (!(treeItem instanceof TextTag)) && (!(treeItem instanceof FontTag)) && internalViewer) { final Tag tag = (Tag) treeItem; @@ -4696,11 +4696,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (treeItem instanceof ShapeTag) { previewPanel.setImageReplaceButtonVisible(false, false, !((Tag) treeItem).isReadOnly(), false); } - previewPanel.showImagePanel(timelined, tag.getSwf(), -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), treeItem instanceof ShapeTag, !Configuration.playFrameSounds.get(), (treeItem instanceof DefineSpriteTag) || (treeItem instanceof ButtonTag)); + previewPanel.showImagePanel(timelined, tag.getSwf(), -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), treeItem instanceof ShapeTag, !Configuration.playFrameSounds.get(), (treeItem instanceof DefineSpriteTag) || (treeItem instanceof ButtonTag), treeItem instanceof DefineSpriteTag); } else if (treeItem instanceof Frame && internalViewer) { Frame fn = (Frame) treeItem; SWF swf = (SWF) fn.getOpenable(); - previewPanel.showImagePanel(fn.timeline.timelined, swf, fn.frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + previewPanel.showImagePanel(fn.timeline.timelined, swf, fn.frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else if (treeItem instanceof ShowFrameTag) { SWF swf; if (timelinedContainer instanceof DefineSpriteTag) { @@ -4708,7 +4708,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } else { swf = (SWF) timelinedContainer; } - previewPanel.showImagePanel(timelinedContainer, swf, frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + previewPanel.showImagePanel(timelinedContainer, swf, frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) { previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32"))); previewPanel.setImageReplaceButtonVisible(false, false, false, !((Tag) treeItem).isReadOnly() && (treeItem instanceof DefineSoundTag)); @@ -4800,7 +4800,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se ShowFrameTag showFrameTag = new ShowFrameTag(swf); swf.addTag(showFrameTag); showFrameTag.setTimelined(swf); - previewPanel.showImagePanel(swf, swf, 0, true, true, !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + previewPanel.showImagePanel(swf, swf, 0, true, true, !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else { previewPanel.showEmpty(); } diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 97ef2f378..457fb064d 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -16,11 +16,13 @@ */ package com.jpexs.decompiler.flash.gui; +import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFHeader; import com.jpexs.decompiler.flash.action.parser.ActionParseException; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.PreviewExporter; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane; import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; import com.jpexs.decompiler.flash.gui.editor.LineMarkedEditorPane; @@ -29,19 +31,27 @@ import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; import com.jpexs.decompiler.flash.gui.player.MediaDisplay; import com.jpexs.decompiler.flash.gui.player.PlayerControls; import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; +import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.MetadataTag; +import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; +import com.jpexs.decompiler.flash.tags.PlaceObject3Tag; import com.jpexs.decompiler.flash.tags.ProductInfoTag; import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; +import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.UnknownTag; +import com.jpexs.decompiler.flash.tags.base.BoundedTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.timeline.Frame; import com.jpexs.decompiler.flash.timeline.TagScript; +import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; import com.jpexs.helpers.SerializableImage; import java.awt.BorderLayout; @@ -67,8 +77,13 @@ import java.io.StringWriter; import java.math.BigInteger; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; import java.util.TimeZone; import java.util.logging.Level; import java.util.logging.Logger; @@ -98,7 +113,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel private static final String GENERIC_TAG_CARD = "GENERICTAG"; private static final String BINARY_TAG_CARD = "BINARYTAG"; - + private static final String PRODUCTINFO_TAG_CARD = "PRODUCTINFOTAG"; private static final String UNKNOWN_TAG_CARD = "UNKNOWNTAG"; @@ -141,11 +156,11 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel // Image tag buttons private JButton replaceShapeButton; - + private JButton replaceShapeUpdateBoundsButton; - + private JButton replaceSoundButton; - + private JButton replaceImageButton; private JButton replaceImageAlphaButton; @@ -210,13 +225,17 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel //used only for flash player private TreeItem currentItem; - + private JLabel productValueLabel = new JLabel(); private JLabel editionValueLabel = new JLabel(); private JLabel versionValueLabel = new JLabel(); private JLabel buildValueLabel = new JLabel(); private JLabel compileDateValueLabel = new JLabel(); - + + private JButton imageFreeTransformButton; + + private JButton imageFreeTransformSaveButton; + private JButton imageFreeTransformCancelButton; public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; @@ -276,7 +295,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel parametersPanel.add(displayWithPreview, BorderLayout.CENTER); setRightComponent(parametersPanel); } - + private JPanel createImageButtonsPanel() { replaceShapeButton = new JButton(mainPanel.translate("button.replace"), View.getIcon("replaceshape16")); replaceShapeButton.setMargin(new Insets(3, 3, 3, 10)); @@ -287,7 +306,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } }); replaceShapeButton.setVisible(false); - + replaceShapeUpdateBoundsButton = new JButton(mainPanel.translate("button.replaceNoFill"), View.getIcon("replaceshape16")); replaceShapeUpdateBoundsButton.setMargin(new Insets(3, 3, 3, 10)); replaceShapeUpdateBoundsButton.addActionListener(new ActionListener() { @@ -297,7 +316,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } }); replaceShapeUpdateBoundsButton.setVisible(false); - + replaceSoundButton = new JButton(mainPanel.translate("button.replace"), View.getIcon("replacesound16")); replaceSoundButton.setMargin(new Insets(3, 3, 3, 10)); replaceSoundButton.addActionListener(new ActionListener() { @@ -307,7 +326,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } }); replaceSoundButton.setVisible(false); - + replaceImageButton = new JButton(mainPanel.translate("button.replace"), View.getIcon("replaceimage16")); replaceImageButton.setMargin(new Insets(3, 3, 3, 10)); replaceImageButton.addActionListener(new ActionListener() { @@ -429,7 +448,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel JPanel flashPlayPanel2 = new JPanel(new BorderLayout()); flashPlayPanel2.add(flashPlayPanel, BorderLayout.CENTER); - flashPlayPanel2.add(new PlayerControls(mainPanel, flashPanel), BorderLayout.SOUTH); + flashPlayPanel2.add(new PlayerControls(mainPanel, flashPanel, null), BorderLayout.SOUTH); leftComponent = flashPlayPanel2; } else { JPanel swtPanel = new JPanel(new GridBagLayout()); @@ -475,7 +494,26 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel imagePanel = new ImagePanel(); imagePanel.setLoop(Configuration.loopMedia.get()); previewCnt.add(imagePanel, BorderLayout.CENTER); - previewCnt.add(imagePlayControls = new PlayerControls(mainPanel, imagePanel), BorderLayout.SOUTH); + + JPanel buttonsPanel = new JPanel(new FlowLayout()); + + imageFreeTransformButton = new JButton(mainPanel.translate("button.freetransform"), View.getIcon("freetransform16")); + imageFreeTransformButton.setMargin(new Insets(3, 3, 3, 10)); + imageFreeTransformButton.addActionListener(this::freeTransformImageButtonActionPerformed); + + imageFreeTransformSaveButton = new JButton(mainPanel.translate("button.save"), View.getIcon("save16")); + imageFreeTransformSaveButton.setMargin(new Insets(3, 3, 3, 10)); + imageFreeTransformSaveButton.addActionListener(this::saveImageFreeTransformButtonActionPerformed); + + imageFreeTransformCancelButton = new JButton(mainPanel.translate("button.cancel"), View.getIcon("cancel16")); + imageFreeTransformCancelButton.setMargin(new Insets(3, 3, 3, 10)); + imageFreeTransformCancelButton.addActionListener(this::cancelImageFreeTransformButtonActionPerformed); + + buttonsPanel.add(imageFreeTransformButton); + buttonsPanel.add(imageFreeTransformSaveButton); + buttonsPanel.add(imageFreeTransformCancelButton); + + previewCnt.add(imagePlayControls = new PlayerControls(mainPanel, imagePanel, buttonsPanel), BorderLayout.SOUTH); imagePlayControls.setMedia(imagePanel); previewPanel.add(previewCnt, BorderLayout.CENTER); JLabel prevIntLabel = new HeaderLabel(mainPanel.translate("swfpreview.internal")); @@ -534,7 +572,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel binaryCard.add(createBinaryButtonsPanel(), BorderLayout.SOUTH); return binaryCard; } - + private JPanel createProductInfoCard() { JPanel productInfoCard = new JPanel(new FlowLayout(FlowLayout.LEFT)); JPanel tablePanel = new JPanel(new GridBagLayout()); @@ -550,45 +588,45 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel buildLabel.setHorizontalAlignment(JLabel.RIGHT); JLabel compileDateLabel = new JLabel(AppStrings.translate("productinfo.compileDate")); compileDateLabel.setHorizontalAlignment(JLabel.RIGHT); - - c.insets = new Insets(3,3,3,3); - + + c.insets = new Insets(3, 3, 3, 3); + c.weightx = 1; c.weighty = 1; - + c.gridy = 0; - - c.gridx = 0; + + c.gridx = 0; tablePanel.add(productLabel, c); c.gridx = 1; tablePanel.add(productValueLabel, c); - + c.gridy++; - c.gridx = 0; + c.gridx = 0; tablePanel.add(editionLabel, c); c.gridx = 1; tablePanel.add(editionValueLabel, c); - + c.gridy++; - c.gridx = 0; + c.gridx = 0; tablePanel.add(versionLabel, c); c.gridx = 1; tablePanel.add(versionValueLabel, c); - + c.gridy++; - c.gridx = 0; + c.gridx = 0; tablePanel.add(buildLabel, c); c.gridx = 1; tablePanel.add(buildValueLabel, c); - + c.gridy++; - c.gridx = 0; + c.gridx = 0; tablePanel.add(compileDateLabel, c); c.gridx = 1; tablePanel.add(compileDateValueLabel, c); - + productInfoCard.add(tablePanel); - + return productInfoCard; } @@ -617,7 +655,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel placeImagePanel = new ImagePanel(); //imagePanel.setLoop(Configuration.loopMedia.get()); previewCnt.add(placeImagePanel, BorderLayout.CENTER); - PlayerControls placeImagePlayControls = new PlayerControls(mainPanel, placeImagePanel); + PlayerControls placeImagePlayControls = new PlayerControls(mainPanel, placeImagePanel, null); previewCnt.add(placeImagePlayControls, BorderLayout.SOUTH); placeImagePlayControls.setMedia(placeImagePanel); previewPanel.add(previewCnt, BorderLayout.CENTER); @@ -686,10 +724,16 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel showCardLeft(FLASH_VIEWER_CARD); } - public void showImagePanel(Timelined timelined, SWF swf, int frame, boolean showObjectsUnderCursor, boolean autoPlay, boolean frozen, boolean alwaysDisplay, boolean muted, boolean mutable) { + public void showImagePanel(Timelined timelined, SWF swf, int frame, boolean showObjectsUnderCursor, boolean autoPlay, boolean frozen, boolean alwaysDisplay, boolean muted, boolean mutable, boolean allowFreeTransform) { showCardLeft(DRAW_PREVIEW_CARD); parametersPanel.setVisible(false); imagePlayControls.setMedia(imagePanel); + imageFreeTransformButton.setVisible(allowFreeTransform); + if ((timelined instanceof Tag) && ((Tag) timelined).isReadOnly()) { + imageFreeTransformButton.setVisible(false); + } + imageFreeTransformSaveButton.setVisible(false); + imageFreeTransformCancelButton.setVisible(false); imagePanel.setTimelined(timelined, swf, frame, showObjectsUnderCursor, autoPlay, frozen, alwaysDisplay, muted, mutable); } @@ -728,7 +772,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel private void showFontPage(FontTag fontTag) { if (!mainPanel.isAdobeFlashPlayerEnabled() /*|| ft instanceof GFxDefineCompactedFont*/) { - showImagePanel(MainPanel.makeTimelined(fontTag), fontTag.getSwf(), fontPageNum, true, true, true, true, true, false); + showImagePanel(MainPanel.makeTimelined(fontTag), fontTag.getSwf(), fontPageNum, true, true, true, true, true, false, false); } } @@ -746,7 +790,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel public void showTextPanel(TextTag textTag) { if (!mainPanel.isAdobeFlashPlayerEnabled() /*|| ft instanceof GFxDefineCompactedFont*/) { - showImagePanel(MainPanel.makeTimelined(textTag), textTag.getSwf(), 0, true, true, true, true, true, false); + showImagePanel(MainPanel.makeTimelined(textTag), textTag.getSwf(), 0, true, true, true, true, true, false, false); } showCardRight(CARDTEXTPANEL); @@ -816,7 +860,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel binaryPanel.setBinaryData(binaryDataTag); parametersPanel.setVisible(false); } - + public void showProductInfoPanel(ProductInfoTag productInfoTag) { showCardLeft(PRODUCTINFO_TAG_CARD); if (productInfoTag.productID == 0L) { @@ -830,7 +874,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } else { productValueLabel.setText("(" + productInfoTag.productID + ")"); } - + if (productInfoTag.edition == 0L) { editionValueLabel.setText("Developer Edition"); } else if (productInfoTag.edition == 1L) { @@ -848,16 +892,16 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } else { editionValueLabel.setText("(" + productInfoTag.productID + ")"); } - + versionValueLabel.setText("" + productInfoTag.majorVersion + "." + productInfoTag.minorVersion); BigInteger buildBigInteger = new BigInteger("" + productInfoTag.buildHigh); buildBigInteger = buildBigInteger.shiftLeft(32).add(new BigInteger("" + productInfoTag.buildLow)); buildValueLabel.setText("" + buildBigInteger); - - long compilationDate = (productInfoTag.compilationDateHigh << 32) + productInfoTag.compilationDateLow; + + long compilationDate = (productInfoTag.compilationDateHigh << 32) + productInfoTag.compilationDateLow; SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); df.setTimeZone(TimeZone.getTimeZone("UTC")); - + compileDateValueLabel.setText(df.format(new Date(compilationDate)) + " UTC"); parametersPanel.setVisible(false); } @@ -887,14 +931,14 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel showCardLeft(PLACE_TAG_CARD); placeTag = tag; oldMatrix = tag.getMatrix(); - placeSplitPane.setDividerLocation((int) (0.6 * this.getWidth())); + placeSplitPane.setDividerLocation((int) (0.6 * this.getWidth())); placeGenericPanel.setVisible(!readOnly); placeGenericPanel.setEditMode(false, tag); placeImagePanel.selectDepth(-1); placeImagePanel.setTimelined(((Tag) tag).getTimelined(), ((Tag) tag).getSwf(), frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); placeImagePanel.selectDepth(tag.getDepth()); parametersPanel.setVisible(false); - placeEditButton.setVisible(!tag.isReadOnly() && !readOnly); + placeEditButton.setVisible(!tag.isReadOnly() && !readOnly); placeEditButton.setEnabled(true); placeSaveButton.setVisible(false); placeCancelButton.setVisible(false); @@ -916,7 +960,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel prevFontsButton.setVisible(false); nextFontsButton.setVisible(false); } - + private void createAndRunTempSwf(TreeItem treeItem) { try { File extTempFile = File.createTempFile("ffdec_viewext_", ".swf"); @@ -1103,7 +1147,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel genericSaveButton.setVisible(false); genericCancelButton.setVisible(false); genericTagPanel.setEditMode(false, null); - mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), tag); + mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), tag); } } @@ -1131,7 +1175,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel SWF swf = tag.getSwf(); tag.getTimelined().resetTimeline(); mainPanel.refreshTree(swf); - hilightTag = tag; + hilightTag = tag; } placeGenericPanel.setEditMode(false, null); } @@ -1168,6 +1212,105 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel placeCancelButton.setVisible(true); } + private void saveImageFreeTransformButtonActionPerformed(ActionEvent evt) { + Matrix matrix = new Matrix(imagePanel.getNewMatrix()); + + imagePanel.freeTransformDepth(-1); + imageFreeTransformButton.setVisible(true); + imageFreeTransformCancelButton.setVisible(false); + imageFreeTransformSaveButton.setVisible(false); + + DefineSpriteTag item = (DefineSpriteTag)mainPanel.getCurrentTree().getCurrentTreeItem(); + for (Tag t:item.getTags()) { + if (t instanceof PlaceObjectTypeTag) { + PlaceObjectTypeTag pt = (PlaceObjectTypeTag)t; + MATRIX placeMatrix = pt.getMatrix(); + if (placeMatrix != null) { + pt.setMatrix(new Matrix(placeMatrix).preConcatenate(matrix).toMATRIX()); + pt.setModified(true); + } + } + } + item.resetTimeline(); + + mainPanel.reload(true); + } + + private void cancelImageFreeTransformButtonActionPerformed(ActionEvent evt) { + imagePanel.freeTransformDepth(-1); + imageFreeTransformButton.setVisible(true); + imageFreeTransformCancelButton.setVisible(false); + imageFreeTransformSaveButton.setVisible(false); + mainPanel.reload(true); + } + + private void freeTransformImageButtonActionPerformed(ActionEvent evt) { + TreeItem item = mainPanel.getCurrentTree().getCurrentTreeItem(); + if (item == null) { + return; + } + + //previewPanel.showImagePanel(fn.timeline.timelined, swf, fn.frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); + DefineSpriteTag sprite = (DefineSpriteTag) item; + + SWF fSwf = new SWF(sprite.getSwf().getCharset()); + fSwf.frameCount = 1; + fSwf.frameRate = sprite.getSwf().frameRate; + fSwf.displayRect = sprite.getSwf().getRect();//sprite.getRect(); + CharacterTag character = sprite; + Set needed = new LinkedHashSet<>(); + character.getNeededCharactersDeep(needed); + needed.remove(sprite.getCharacterId()); + needed.add(sprite.getCharacterId()); + + for (int n : needed) { + CharacterTag neededCharacter; + try { + neededCharacter = (CharacterTag) sprite.getSwf().getCharacter(n).cloneTag(); + } catch (InterruptedException | IOException ex) { + Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null, ex); + return; + } + neededCharacter.setSwf(fSwf); + neededCharacter.setTimelined(fSwf); + fSwf.addTag(neededCharacter); + } + + + DefineSpriteTag sprite2 = new DefineSpriteTag(fSwf); + sprite2.frameCount = 1; + PlaceObject3Tag placeTag = new PlaceObject3Tag(fSwf); + placeTag.depth = 1; + placeTag.characterId = sprite.getCharacterId(); + placeTag.placeFlagHasCharacter = true; + + placeTag.matrix = new MATRIX(); + placeTag.setTimelined(sprite2); + sprite2.addTag(placeTag); + ShowFrameTag showFrameTag = new ShowFrameTag(fSwf); + sprite2.addTag(showFrameTag); + + + placeTag = new PlaceObject3Tag(fSwf); + placeTag.depth = 1; + placeTag.characterId = sprite2.getCharacterId(); + placeTag.placeFlagHasCharacter = true; + + placeTag.matrix = new MATRIX(); + fSwf.addTag(placeTag); + placeTag.setTimelined(fSwf); + showFrameTag = new ShowFrameTag(fSwf); + fSwf.addTag(showFrameTag); + showFrameTag.setTimelined(fSwf); + + imagePanel.setTimelined(sprite2, fSwf, 0, true, true, true, true, true, false); + imagePanel.selectDepth(-1); + imagePanel.freeTransformDepth(placeTag.getDepth()); + imageFreeTransformButton.setVisible(false); + imageFreeTransformSaveButton.setVisible(true); + imageFreeTransformCancelButton.setVisible(true); + } + private void cancelPlaceTagButtonActionPerformed(ActionEvent evt) { if (placeEditMode == PLACE_EDIT_FREETRANSFORM) { placeImagePanel.selectDepth(placeTag.getDepth()); diff --git a/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java b/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java index 19543fc2c..0ce39df73 100644 --- a/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java @@ -478,9 +478,9 @@ public class SelectTagPositionDialog extends AppDialog { int f = ((MyFrame) tnode.getData()).frame; Object parent = ((MyTreeNode) tnode.getParent()).getData(); if (parent instanceof DefineSpriteTag) { - previewPanel.showImagePanel((DefineSpriteTag) parent, swf, f - 1, true, true, !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + previewPanel.showImagePanel((DefineSpriteTag) parent, swf, f - 1, true, true, !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else { - previewPanel.showImagePanel(swf, swf, f - 1, true, true, !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + previewPanel.showImagePanel(swf, swf, f - 1, true, true, !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } } else { previewPanel.showEmpty(); diff --git a/src/com/jpexs/decompiler/flash/gui/action/AddScriptDialog.java b/src/com/jpexs/decompiler/flash/gui/action/AddScriptDialog.java index 9ae56a307..4051bdf8f 100644 --- a/src/com/jpexs/decompiler/flash/gui/action/AddScriptDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/action/AddScriptDialog.java @@ -730,22 +730,22 @@ public class AddScriptDialog extends AppDialog { int f = ((MyFrame) ((MyTreeNode) tnode.getParent()).getData()).frame; Object parent = ((MyTreeNode) tnode.getParent().getParent()).getData(); if (parent instanceof DefineSpriteTag) { - instancePreviewPanel.showImagePanel((DefineSpriteTag) parent, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + instancePreviewPanel.showImagePanel((DefineSpriteTag) parent, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else { - instancePreviewPanel.showImagePanel(swf, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + instancePreviewPanel.showImagePanel(swf, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } } else if (tnode.getData() instanceof DefineSpriteTag) { instancePreviewPanel.selectImageDepth(-1); - instancePreviewPanel.showImagePanel((DefineSpriteTag) tnode.getData(), swf, -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + instancePreviewPanel.showImagePanel((DefineSpriteTag) tnode.getData(), swf, -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else if (tnode.getData() instanceof MyFrame) { instancePreviewPanel.selectImageDepth(-1); int f = ((MyFrame) tnode.getData()).frame; Object parent = ((MyTreeNode) tnode.getParent()).getData(); if (parent instanceof DefineSpriteTag) { - instancePreviewPanel.showImagePanel((DefineSpriteTag) parent, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + instancePreviewPanel.showImagePanel((DefineSpriteTag) parent, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else { - instancePreviewPanel.showImagePanel(swf, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + instancePreviewPanel.showImagePanel(swf, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } } checkEnabled(); @@ -759,7 +759,7 @@ public class AddScriptDialog extends AppDialog { checkEnabled(); return; } - spriteInitPreviewPanel.showImagePanel(spriteInitList.getSelectedValue(), swf, -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + spriteInitPreviewPanel.showImagePanel(spriteInitList.getSelectedValue(), swf, -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); checkEnabled(); } @@ -771,7 +771,7 @@ public class AddScriptDialog extends AppDialog { checkEnabled(); return; } - framePreviewPanel.showImagePanel(swf, swf, selectedIndex, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + framePreviewPanel.showImagePanel(swf, swf, selectedIndex, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); int f = selectedIndex + 1; if (!frameTextField.getText().equals("" + f)) { @@ -783,7 +783,7 @@ public class AddScriptDialog extends AppDialog { private void buttonValueChanged(ListSelectionEvent e) { buttonPreviewPanel.showEmpty(); if (buttonList.getSelectedIndex() >= 0) { - buttonPreviewPanel.showImagePanel(MainPanel.makeTimelined(buttonList.getSelectedValue()), swf, -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + buttonPreviewPanel.showImagePanel(MainPanel.makeTimelined(buttonList.getSelectedValue()), swf, -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } checkEnabled(); @@ -799,14 +799,14 @@ public class AddScriptDialog extends AppDialog { } MyTreeNode tnode = (MyTreeNode) selection.getLastPathComponent(); if (tnode.getData() instanceof DefineSpriteTag) { - spriteFramePreviewPanel.showImagePanel((DefineSpriteTag) tnode.getData(), swf, -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + spriteFramePreviewPanel.showImagePanel((DefineSpriteTag) tnode.getData(), swf, -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else if (tnode.getData() instanceof MyFrame) { int f = ((MyFrame) tnode.getData()).frame; Object parent = ((MyTreeNode) tnode.getParent()).getData(); if (parent instanceof DefineSpriteTag) { - spriteFramePreviewPanel.showImagePanel((DefineSpriteTag) parent, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + spriteFramePreviewPanel.showImagePanel((DefineSpriteTag) parent, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } else { - spriteFramePreviewPanel.showImagePanel(swf, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true); + spriteFramePreviewPanel.showImagePanel(swf, swf, f - 1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false); } if (!spriteFrameTextField.getText().equals("" + f)) { spriteFrameTextField.setText("" + f); diff --git a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java index 5558d24dc..89df81aaa 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java +++ b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java @@ -141,7 +141,7 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { underlinedFont = font.deriveFont(fontAttributes); } - public PlayerControls(final MainPanel mainPanel, MediaDisplay display) { + public PlayerControls(final MainPanel mainPanel, MediaDisplay display, JPanel middleButtonsPanel) { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); @@ -209,6 +209,9 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { displayButtonsPanel.add(muteButton); graphicControls.add(displayButtonsPanel, BorderLayout.WEST); + if (middleButtonsPanel != null) { + graphicControls.add(middleButtonsPanel, BorderLayout.CENTER); + } graphicControls.add(graphicButtonsPanel, BorderLayout.EAST); graphicControls.setVisible(false);