various minor architecture changes
M core/src/net/dermetfan/jigsawPuzzle/puzzle/JigsawPuzzle.java +44 -86
@@ 30,100 30,59 @@ import com.badlogic.gdx.utils.Array;
 import com.badlogic.gdx.utils.Pools;
 import net.dermetfan.jigsawPuzzle.Constants;
 import net.dermetfan.jigsawPuzzle.utils.PolygonRegionDrawable;
-import net.dermetfan.utils.libgdx.math.GeometryUtils;
 import net.dermetfan.utils.libgdx.scene2d.Scene2DUtils;
 
 /** represents a puzzle and manages {@link Piece Pieces}
  *  @author dermetfan */
 public class JigsawPuzzle {
 
-	private final Array<Piece> placedPieces, remainingPieces;
+	private final Array<Piece> pieces;
 
 	public JigsawPuzzle() {
-		remainingPieces = new Array<>(Piece.class);
-		placedPieces = new Array<>(Piece.class);
+		pieces = new Array<>(Piece.class);
 	}
 
 	/** @param pieces the amount of pieces that will probably be in this puzzle */
 	public JigsawPuzzle(int pieces) {
-		remainingPieces = new Array<>(pieces);
-		placedPieces = new Array<>(pieces);
-	}
-
-	/** @param pieces the {@link #remainingPieces remaining pieces} */
-	public JigsawPuzzle(Piece... pieces) {
-		remainingPieces = new Array<>(pieces);
-		placedPieces = new Array<>(pieces.length);
+		this.pieces = new Array<>(pieces);
 	}
 
-	/** Solves the puzzle by {@link #place(Piece) placing} all {@link #remainingPieces remaining pieces}.
-	 *  @param relativeTo the piece relative to which the puzzle should be solved */
-	public void solve(Piece relativeTo) {
-		if(placedPieces.contains(relativeTo, true) || remainingPieces.contains(relativeTo, true))
-			for(Piece piece : remainingPieces) {
-				if(piece == relativeTo)
-					continue;
-				place(piece);
-			}
-		else
-			throw new IllegalArgumentException("the reference piece is not part of the puzzle");
-	}
-
-	/** moves all {@link #placedPieces} to {@link #remainingPieces} */
-	public void unsolve() {
-		remainingPieces.addAll(placedPieces);
-		placedPieces.clear();
-		placedPieces.ensureCapacity(remainingPieces.size); // just for performance
+	/** @param pieces the {@link #pieces} */
+	public JigsawPuzzle(Piece... pieces) {
+		this.pieces = new Array<>(pieces);
 	}
 
-	/** Places the given piece in its spot on the puzzle. If no piece was {@link #placedPieces placed} yet, it's position is assumed to be correct (hence it will simply be moved to {@link #placedPieces})
-	 *  @param piece the piece to automatically place in its spot on the puzzle */
-	public void place(Piece piece) {
-		if(!remainingPieces.removeValue(piece, true))
-			throw new IllegalArgumentException("the given piece is not remaining and hence cannot be automatically placed");
-		Piece ref = placedPieces.size > 0 ? placedPieces.first() : piece;
-		piece.snap(ref);
-		placedPieces.add(piece);
-	}
-
-	/** @param piece the piece to add to {@link #remainingPieces} */
-	public void addRemaining(Piece piece) {
-		placedPieces.removeValue(piece, true);
-		remainingPieces.add(piece);
+	/** solves the puzzle by letting all {@link #pieces} {@link Piece#place(Piece) snap} into their spot
+	 *  @param relativeTo the piece relative to which the puzzle should be solved */
+	public void solve(Piece relativeTo) {
+		if(!pieces.contains(relativeTo, true))
+			throw new IllegalArgumentException("the reference piece is not part of the puzzle");
+		for(Piece piece : pieces) {
+			if(piece == relativeTo)
+				continue;
+			piece.place(relativeTo);
+		}
 	}
 
-	/** @return if the puzzle is solved */
-	public boolean isSolved() {
-		return remainingPieces.size == 0;
+	/** @param piece the piece to add to {@link #pieces} */
+	public void add(Piece piece) {
+		if(!pieces.contains(piece, true))
+			pieces.add(piece);
 	}
 
-	/** Checks if the given piece is correctly positioned. Always returns true if no piece was placed yet.
-	 *  @param piece the piece which position to check
-	 *  @param tolerance the distance by which the piece is allowed to be off
-	 *  @return if the given piece is correctly placed in relation to {@link #placedPieces} */
-	public boolean isCorrectlyPlaced(Piece piece, float tolerance) {
-		return placedPieces.size <= 0 || piece.inRelationTo(placedPieces.first(), tolerance);
-	}
-
-	/** usually not necessary, {@link #isSolved()} should return the right result
-	 *  @param tolerance the distance by which each piece is allowed to be off
-	 * 	@return if the {@link #placedPieces} are really correctly placed */
-	public boolean checkPlaced(float tolerance) {
-		Piece reference = placedPieces.first();
-		for(Piece piece : placedPieces)
-			if(!piece.inRelationTo(reference, tolerance))
+	/** @param tolerance the distance by which each piece is allowed to be off
+	 *  @return if the puzzle is solved */
+	public boolean isSolved(float tolerance) {
+		Piece reference = pieces.first();
+		for(Piece piece : pieces)
+			if(!piece.isPlacedCorrectly(reference, tolerance))
 				return false;
 		return true;
 	}
 
-	/** @return the {@link #placedPieces} */
-	public Array<Piece> getPlacedPieces() {
-		return placedPieces;
-	}
-
-	/** @return the {@link #remainingPieces} */
-	public Array<Piece> getRemainingPieces() {
-		return remainingPieces;
+	/** @return the {@link #pieces} */
+	public Array<Piece> getPieces() {
+		return pieces;
 	}
 
 	public Source createSource(final Group board, final DragAndDrop dnd) {

          
@@ 181,11 140,10 @@ public class JigsawPuzzle {
 				Actor dragged = payload.getDragActor();
 				Scene2DUtils.addAtStageCoordinates(dragged, board);
 				if(dragged instanceof Piece) {
-					Piece piece = (Piece) dragged;
-					if(isCorrectlyPlaced(piece, Constants.tolerance)) {
-						if(remainingPieces.contains(piece, true)) // TODO remove this condition (not the body!) when Puzzle doesn't know the difference between remaining and placed Pieces anymore
-							place(piece); // snap it into its perfect position in relation to some already placed piece
-						if(isSolved() && solvedCallback != null)
+					Piece piece = (Piece) dragged, ref = pieces.first();
+					if(piece.isPlacedCorrectly(ref, Constants.tolerance)) {
+						piece.place(ref); // snap it into its perfect position in relation to some already placed piece
+						if(isSolved(Constants.tolerance) && solvedCallback != null)
 							solvedCallback.run();
 					}
 				}

          
@@ 197,7 155,7 @@ public class JigsawPuzzle {
 	 *  @author dermetfan */
 	public static class Piece extends Image {
 
-		/** the position of the piece on the puzzle (the minX and minY of its vertices) */
+		/** the position of the piece on the puzzle (the {@link PolygonRegionDrawable#getPolygonX() minX} and {@link PolygonRegionDrawable#getPolygonY() minY} of its vertices) */
 		private float slotX, slotY;
 
 		public Piece(PolygonRegionDrawable drawable) {

          
@@ 224,27 182,27 @@ public class JigsawPuzzle {
 			if(hit == this && drawable != null) {
 				tmpPolygon.setVertices(drawable.getRegion().getVertices());
 				tmpPolygon.setPosition(-slotX, -slotY);
-				if(!tmpPolygon.contains(x / getWidth() * GeometryUtils.width(tmpPolygon.getVertices()), y / getHeight() * GeometryUtils.height(tmpPolygon.getVertices())))
+				if(!tmpPolygon.contains(x / getWidth() * drawable.getPolygonWidth(), y / getHeight() * drawable.getPolygonHeight()))
 					return null;
 			}
 			return hit;
 		}
 
-		/** @param ref the piece in relation to which to snap into this piece's spot */
-		public void snap(Piece ref) {
-			Vector2 refPuzzlePoint = Pools.obtain(Vector2.class).set(ref.getX(), ref.getY()).sub(ref.slotX, ref.slotY);
+		/** @param reference the piece in relation to which to this piece should snap in its spot */
+		public void place(Piece reference) {
+			Vector2 refPuzzlePoint = Pools.obtain(Vector2.class).set(reference.getX(), reference.getY()).sub(reference.slotX, reference.slotY);
 			setPosition(refPuzzlePoint.x + slotX, refPuzzlePoint.y + slotY);
 			Pools.free(refPuzzlePoint);
 		}
 
-		/** @param ref the piece in which relation this piece should be
-		 *  @param tolerance the tolerance in the x and y axis
-		 *  @return if this piece is in relation to the given piece with the given tolerance */
-		public boolean inRelationTo(Piece ref, float tolerance) {
+		/** @param reference the piece in relation to which this piece's position should be checked
+		 *  @param tolerance the distance by which each piece is allowed to be off
+		 *  @return if this piece is placed correctly in relation to the given reference piece with the given tolerance */
+		public boolean isPlacedCorrectly(Piece reference, float tolerance) {
 			// get puzzle points (bottom left corner of the puzzle)
-			Vector2 puzzlePoint = Pools.obtain(Vector2.class).set(-slotX, -slotY), refPuzzlePoint = Pools.obtain(Vector2.class).set(-ref.slotX, -ref.slotY);
+			Vector2 puzzlePoint = Pools.obtain(Vector2.class).set(-slotX, -slotY), refPuzzlePoint = Pools.obtain(Vector2.class).set(-reference.slotX, -reference.slotY);
 			localToStageCoordinates(puzzlePoint);
-			ref.localToStageCoordinates(refPuzzlePoint);
+			reference.localToStageCoordinates(refPuzzlePoint);
 
 			// see if they're the same
 			boolean rel = puzzlePoint.epsilonEquals(refPuzzlePoint, tolerance);

          
M core/src/net/dermetfan/jigsawPuzzle/screens/PlayScreen.java +1 -1
@@ 83,7 83,7 @@ public class PlayScreen extends ScreenAd
 		float nextX = 0, tallest = 0;
 		for(FileHandle psh : Assets.puzzlePSHs(level)) { // set up the pieces on the bank
 			Piece piece = new Piece(new PolygonRegionDrawable(Assets.manager.get(psh.path(), PolygonRegion.class)));
-			puzzle.addRemaining(piece);
+			puzzle.add(piece);
 			board.addActor(piece);
 			piece.setX(nextX);
 			nextX += piece.getWidth();

          
M core/src/net/dermetfan/jigsawPuzzle/utils/PolygonRegionDrawable.java +10 -0
@@ 99,4 99,14 @@ public class PolygonRegionDrawable exten
 		return polygonY;
 	}
 
+	/** @return the {@link #polygonWidth} */
+	public float getPolygonWidth() {
+		return polygonWidth;
+	}
+
+	/** @return the {@link #polygonHeight} */
+	public float getPolygonHeight() {
+		return polygonHeight;
+	}
+
 }