@Override
  public Transition2DInstruction[] getInstructions(float progress, Dimension size) {
    if (type == OUT) {
      progress = 1 - progress;
    }
    progress = (float) Math.pow(progress, .5);

    float ySize = (size.height) * .05f;
    float xSize = (size.width) * .05f;
    Vector<RectangularShape> v = new Vector<RectangularShape>();
    float angleProgress = (float) Math.pow(1 - Math.min(progress, 1), .5);
    // pop it over 1:
    float progressZ = 1.3f * progress;
    double w = xSize * progressZ;
    double h = ySize * progressZ;
    float min = (float) (Math.min(w, h));
    for (float y = 0; y < size.height; y += ySize) {
      for (float x = 0; x < size.width; x += xSize) {
        v.add(
            new RoundRectangle2D.Double(
                x + xSize / 2 - w / 2,
                y + ySize / 2 - h / 2,
                w * progress + (1 - progress) * min,
                h * progress + (1 - progress) * min,
                w * angleProgress * progress + (1 - progress) * min * angleProgress,
                h * angleProgress * progress + (1 - progress) * min * angleProgress));
      }
    }
    ImageInstruction[] instr = new ImageInstruction[v.size() + 1];
    instr[0] = new ImageInstruction(false);
    for (int a = 0; a < v.size(); a++) {
      float progress2 = progress; // (float)Math.pow(progress, .9+.2*random.nextFloat());
      RectangularShape r = v.get(a);
      Point2D p1 = new Point2D.Double(r.getCenterX(), r.getCenterY());
      Point2D p2 = new Point2D.Double(r.getCenterX(), r.getCenterY());
      AffineTransform transform = new AffineTransform();
      transform.translate(r.getCenterX(), r.getCenterY());
      transform.scale(30 * (1 - progress) + 1, 30 * (1 - progress) + 1);
      transform.translate(-r.getCenterX(), -r.getCenterY());

      transform.rotate(.3 * (1 - progress2), size.width / 3, size.height / 2);

      transform.transform(p1, p2);
      transform.setToTranslation(p1.getX() - p2.getX(), p1.getY() - p2.getY());
      Shape shape = transform.createTransformedShape(r);
      instr[a + 1] = new ImageInstruction(true, transform, shape);
    }
    if (type == IN) {
      for (int a = 0; a < instr.length; a++) {
        instr[a].isFirstFrame = !instr[a].isFirstFrame;
      }
    }

    return instr;
  }
 private void zoom(final Zoomable dst, final Point2D center, final double ratio, final int dt) {
   if (dst == null) return;
   final RectangularShape src = dst.getZoom();
   final double w = src.getWidth() * ratio;
   final double h = src.getHeight() * ratio;
   final double cx, cy;
   if (center == null) {
     cx = src.getCenterX();
     cy = src.getCenterY();
   } else {
     cx = center.getX();
     cy = center.getY();
   }
   zoom(dst, new Rectangle2D.Double(cx - w / 2, cy - h / 2, Math.abs(w), Math.abs(h)), dt);
 }