From c528228104cad1b10e4c5d99c1078274e97f2d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Thu, 13 Mar 2014 09:32:50 +0100 Subject: [PATCH] Issue 533 Object under cursor fix --- trunk/src/com/jpexs/decompiler/flash/SWF.java | 2 +- .../decompiler/flash/exporters/Matrix.java | 6 + .../decompiler/flash/gui/ImagePanel.java | 226 ++++++++++++++---- .../decompiler/flash/timeline/Frame.java | 61 ----- .../decompiler/flash/timeline/Timeline.java | 63 +++++ 5 files changed, 245 insertions(+), 113 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index b02e7c783..6b0653d55 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -2351,7 +2351,7 @@ public final class SWF implements TreeItem, Timelined { drawable.toImage(dframe, layer.ratio, stateUnderCursor, mouseButton, img, m, clrTrans); //if(stateUnderCursor == layer){ - /* if(true){ + /* if(true){ Graphics2D gg = (Graphics2D)img.getGraphics(); gg.setStroke(new BasicStroke(3)); gg.setPaint(Color.red); diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java b/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java index de880522b..f2974452b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java @@ -102,6 +102,12 @@ public class Matrix { public Point transform(Point point) { return transform(point.x, point.y); } + + public java.awt.Point transform(java.awt.Point point) { + Point p= transform(point.x, point.y); + return new java.awt.Point((int)p.x,(int)p.y); + } + public ExportRectangle transform(ExportRectangle rect) { double minX = Double.MAX_VALUE; diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index b024726ea..f56628839 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -42,7 +42,9 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.Point; import java.awt.Rectangle; +import java.awt.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; @@ -51,10 +53,17 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseMotionListener; import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.imageio.ImageIO; +import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JColorChooser; @@ -65,7 +74,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis static final String ACTION_SELECT_BKCOLOR = "SELECTCOLOR"; - private JLabel label = new JLabel(); + //private JLabel label = new JLabel(); private Timelined timelined; private boolean stillFrame = false; private Timer timer; @@ -77,33 +86,114 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis private DepthState stateUnderCursor = null; private MouseEvent lastMouseEvent = null; private List soundPlayers = new ArrayList<>(); + private IconPanel iconPanel; + + private class IconPanel extends JPanel { + + private SerializableImage img; + + private Rectangle rect = null; + private List dss; + private List outlines; + + + public void setImg(SerializableImage img,List dss, List outlines) { + this.img = img; + this.dss = dss; + this.outlines = outlines; + calcRect(); + repaint(); + } + + public List getObjectsUnderPoint(Point p){ + List ret=new ArrayList<>(); + for(int i=0;i h2) { + w = w1 * h2 / h1; + h = h2; + } else { + w = w2; + } + } + + rect = new Rectangle(getWidth() / 2 - w / 2, getHeight() / 2 - h / 2, w, h); + } + } + + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setPaint(View.transparentPaint); + g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); + g2d.setComposite(AlphaComposite.SrcOver); + g2d.setPaint(View.swfBackgroundColor); + g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); + if (img != null) { + calcRect(); + g2d.setComposite(AlphaComposite.SrcOver); + g2d.drawImage(img.getBufferedImage(), rect.x, rect.y, rect.x+rect.width, rect.y+rect.height, 0, 0, img.getWidth(), img.getHeight(), null); + } + + } + } @Override public void setBackground(Color bg) { - if (label != null) { - label.setBackground(bg); + if (iconPanel != null) { + iconPanel.setBackground(bg); } super.setBackground(bg); } @Override public synchronized void addMouseListener(MouseListener l) { - label.addMouseListener(l); + iconPanel.addMouseListener(l); } @Override public synchronized void removeMouseListener(MouseListener l) { - label.removeMouseListener(l); + iconPanel.removeMouseListener(l); } @Override public synchronized void addMouseMotionListener(MouseMotionListener l) { - label.addMouseMotionListener(l); + iconPanel.addMouseMotionListener(l); } @Override public synchronized void removeMouseMotionListener(MouseMotionListener l) { - label.removeMouseMotionListener(l); + iconPanel.removeMouseMotionListener(l); } private void updatePos(MouseEvent e) { @@ -119,18 +209,25 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis RECT rect = bounded.getRect(); int width = rect.getWidth(); double scale = 1.0; - if (width > swf.displayRect.getWidth()) { + /*if (width > swf.displayRect.getWidth()) { scale = (double) swf.displayRect.getWidth() / (double) width; - } + }*/ Matrix m = new Matrix(); m.translate(-rect.Xmin, -rect.Ymin); m.scale(scale); - List objs = tim.frames.get(frame).getObjectsUnderCursor(e.getPoint(), mouseButton, m); + Point p=e.getPoint(); + p = iconPanel.toImagePoint(p); + int x = p.x; + int y = p.y; + List objs = new ArrayList<>(); + objs=iconPanel.getObjectsUnderPoint(p); String ret = ""; - ret += " [" + e.getX() + "," + e.getY() + "] : "; + + ret += " [" + x + "," + y + "] : "; boolean first = true; - for (DepthState ds : objs) { + for (int i=0;i(),new ArrayList()); + } catch (IOException ex) { + Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE, null, ex); + } } public void setTimelined(final Timelined drawable, final SWF swf, int frame) { @@ -284,7 +372,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis loaded = true; if (drawable.getTimeline().frames.isEmpty()) { - label.setIcon(null); + iconPanel.setImg(null, new ArrayList(),new ArrayList()); return; } frame = 0; @@ -299,8 +387,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis timelined = null; loaded = true; stillFrame = true; - ImageIcon icon = new ImageIcon(image.getBufferedImage()); - label.setIcon(icon); + iconPanel.setImg(image,new ArrayList(),new ArrayList()); } @Override @@ -361,24 +448,51 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis int width = rect.getWidth(); int height = rect.getHeight(); double scale = 1.0; - if (width > swf.displayRect.getWidth()) { - scale = (double) swf.displayRect.getWidth() / (double) width; - width = swf.displayRect.getWidth(); - } + /*if (width > swf.displayRect.getWidth() || height > swf.displayRect.getHeight()) { + //scale = (double) swf.displayRect.getWidth() / (double) width; + //width = swf.displayRect.getWidth(); + + int w1 = width; + int h1 = height; + int w2 = swf.displayRect.getWidth(); + int h2 = swf.displayRect.getHeight(); + + int w; + int h = h1 * w2 / w1; + if (h > h2) { + w = w1 * h2 / h1; + h = h2; + } else { + w = w2; + } + scale = (double) w / (double) width; + + width = w; + height = h; + }*/ SerializableImage image = new SerializableImage((int) (width / SWF.unitDivisor) + 1, (int) (height / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB); image.fillTransparent(); Matrix m = new Matrix(); m.translate(-rect.Xmin, -rect.Ymin); + /*m.translate(-rect.getWidth(), -rect.getHeight()); m.scale(scale); + m.translate(rect.getWidth()*scale, rect.getHeight()*scale);*/ drawable.getTimeline().toImage(frame, frame, stateUnderCursor, mouseButton, image, m, new ColorTransform()); - - /* Graphics2D gg = (Graphics2D)image.getGraphics(); - gg.setStroke(new BasicStroke(3)); - gg.setPaint(Color.green); - gg.setTransform(AffineTransform.getTranslateInstance(0, 0)); - gg.draw(SHAPERECORD.twipToPixelShape(drawable.getTimeline().getOutline(frame, frame, stateUnderCursor, mouseButton, m))); - */ + + Graphics2D gg = (Graphics2D)image.getGraphics(); + gg.setStroke(new BasicStroke(3)); + gg.setPaint(Color.green); + gg.setTransform(AffineTransform.getTranslateInstance(0, 0)); + List dss=new ArrayList<>(); + List os=new ArrayList<>(); + /*drawable.getTimeline().getObjectsOutlines(frame, frame, stateUnderCursor, mouseButton, m, dss, os); + + //gg.setTransform(AffineTransform.getTranslateInstance(0, 0)); + for(Shape s:os){ + gg.draw(SHAPERECORD.twipToPixelShape(s)); + }*/ + img = image; } else if (drawable instanceof FontTag) { // only DefineFont tags @@ -397,7 +511,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis Matrix mat = new Matrix(); mat.translateX = swf.displayRect.Xmin; mat.translateY = swf.displayRect.Ymin; - ImageIcon icon = new ImageIcon(getFrame(swf, frame, timelined, stateUnderCursor, mouseButton).getBufferedImage()); + BufferedImage img = getFrame(swf, frame, timelined, stateUnderCursor, mouseButton).getBufferedImage(); List sounds = timelined.getTimeline().getSounds(frame, stateUnderCursor, mouseButton); for (int sndId : sounds) { CharacterTag c = swf.characters.get(sndId); @@ -420,7 +534,17 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis } } - label.setIcon(icon); + Matrix m = new Matrix(); + RECT rect= timelined.getTimeline().displayRect; + m.translate(-rect.Xmin, -rect.Ymin); + m.scale(1); + List objs = new ArrayList<>(); + List outlines=new ArrayList<>(); + timelined.getTimeline().getObjectsOutlines(frame, frame, stateUnderCursor, mouseButton, m, objs, outlines); + for(int i=0;i getObjectsUnderCursor(Point mousePos, int mouseButton, Matrix transformation) { - List ret = new ArrayList<>(); - List keys = new ArrayList<>(layers.keySet()); - DepthState maxds = null; - Stack clips = new Stack<>(); - for (int d : keys) { - DepthState ds = layers.get(d); - Clip currentClip = null; - for (int j = clips.size() - 1; j >= 0; j--) { - Clip cl = clips.get(j); - if (cl.depth >= d) { - clips.remove(j); - } - } - if (!clips.isEmpty()) { - currentClip = clips.peek(); - } - CharacterTag c = timeline.swf.characters.get(ds.characterId); - if (c instanceof DrawableTag) { - Matrix m = new Matrix(ds.matrix).preConcatenate(transformation); - int frame = ds.time % ((DrawableTag) c).getNumFrames(); - if (c instanceof ButtonTag) { - frame = ButtonTag.FRAME_HITTEST; - } - Shape outline = SHAPERECORD.twipToPixelShape(((DrawableTag) c).getOutline(frame, ds.ratio, null, mouseButton, m)); - - Area checkArea = new Area(outline); - if (currentClip != null) { - Area a = new Area(checkArea.getBounds()); - a.subtract(new Area(currentClip.shape)); - checkArea.subtract(a); - } - if (ds.clipDepth > -1) { - Clip clip = new Clip(checkArea, ds.clipDepth); - clips.push(clip); - } else if (checkArea.contains(mousePos)) { - maxds = ds; - } - } - } - if (maxds == null) { - return ret; - } - ret.add(maxds); - - CharacterTag c = timeline.swf.characters.get(maxds.characterId); - if (c instanceof Timelined) { - Timelined tc = ((Timelined) c); - - int frame = maxds.time % ((DrawableTag) c).getNumFrames();; - if (tc instanceof ButtonTag) { - frame = ButtonTag.FRAME_HITTEST; - } - - ret.addAll(tc.getTimeline().frames.get(frame).getObjectsUnderCursor(mousePos, mouseButton, new Matrix(maxds.matrix).preConcatenate(transformation))); - } - - return ret; - } - } diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java index 4bc5ec88a..a37eac3bf 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -206,6 +206,69 @@ public class Timeline { } return ret; } + + public void getObjectsOutlines(int frame, int ratio,DepthState stateUnderCursor, int mouseButton, Matrix transformation,List objs,List outlines){ + Frame fr = this.frames.get(frame); + Stack clips = new Stack<>(); + for (int d = this.getMaxDepth(); d >= 0; d--) { + Clip currentClip = null; + for (int i = clips.size() - 1; i >= 0; i--) { + Clip cl = clips.get(i); + if (cl.depth <= d) { + clips.remove(i); + } + } + if (!clips.isEmpty()) { + currentClip = clips.peek(); + } + DepthState ds = fr.layers.get(d); + if (ds == null) { + continue; + } + if (!ds.isVisible) { + continue; + } + CharacterTag c = swf.characters.get(ds.characterId); + if ((c instanceof DrawableTag) && (c instanceof BoundedTag)) { + Matrix m = new Matrix(ds.matrix); + m = m.preConcatenate(transformation); + + int dframe = 0; + if(c instanceof Timelined){ + dframe = ds.time % ((Timelined) c).getTimeline().frames.size(); + if (c instanceof ButtonTag) { + ButtonTag bt = (ButtonTag) c; + dframe = ButtonTag.FRAME_UP; + if (stateUnderCursor == ds) { + if (mouseButton > 0) { + dframe = ButtonTag.FRAME_DOWN; + } else { + dframe = ButtonTag.FRAME_OVER; + } + } + } + } + Shape cshape = ((DrawableTag) c).getOutline(dframe, ds.ratio, stateUnderCursor, mouseButton, m); + + Area addArea = new Area(cshape); + if (currentClip != null) { + Area a = new Area(new Rectangle(displayRect.Xmin, displayRect.Ymin, displayRect.getWidth(), displayRect.getHeight())); + a.subtract(new Area(currentClip.shape)); + addArea.subtract(a); + } + if (ds.clipDepth > -1) { + Clip clip = new Clip(addArea, ds.clipDepth); + clips.push(clip); + } else { + objs.add(ds); + outlines.add(addArea); + } + if(c instanceof Timelined){ + ((Timelined)c).getTimeline().getObjectsOutlines(dframe, ds.ratio, stateUnderCursor, mouseButton, m, objs, outlines); + } + } + } + } public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { Frame fr = this.frames.get(frame);