package com.clearlyspam23.GLE.basic.layers.tile.gui; import java.awt.BasicStroke; import java.awt.Color; import java.awt.geom.Line2D; import java.util.ArrayList; import java.util.List; import org.piccolo2d.PCamera; import org.piccolo2d.PNode; import com.clearlyspam23.GLE.GUI.util.AnimatedOutlineRectNode; import com.clearlyspam23.GLE.GUI.util.FixedWidthOutlineRectNode; import com.clearlyspam23.GLE.GUI.util.FixedWidthStroke; import com.clearlyspam23.GLE.GUI.util.LineNode; import com.clearlyspam23.GLE.basic.layers.tile.Tile; import com.clearlyspam23.GLE.basic.layers.tile.TileLocation; public class ImmovableTileSelection implements TileSelection{ private PNode overlayNode = new PNode(); private LineNode linesNode; private LineNode linesNode2; private List<TileLocation> selectedLocations = new ArrayList<TileLocation>(); // private List<FixedWidthOutlineRectNode> outlineRect; private int width; private int height; private TileLocation offset; private TileLayerPNode tileLayer; public ImmovableTileSelection(List<TileLocation> locations, TileLayerPNode layer, PCamera camera){ tileLayer = layer; linesNode = new LineNode(new FixedWidthStroke(2, camera)); linesNode.setPaint(Color.YELLOW); linesNode.setPickable(false); linesNode2 = new LineNode(new FixedWidthStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 1.0f, new float[]{3, 6}, 0, camera)); linesNode2.setPaint(Color.BLACK); linesNode2.setPickable(false); overlayNode.addChild(linesNode); overlayNode.addChild(linesNode2); recalculateTiles(locations); } private void recalculateTiles(List<TileLocation> locations){ selectedLocations.clear(); tileLayer.silentlyIgnoreInput(true); int minX = Integer.MAX_VALUE; int maxX = 0; int minY = Integer.MAX_VALUE; int maxY = 0; for(TileLocation loc : locations){ tileLayer.getNodeAt(loc).silentlyIgnoreInput(false); minX = Math.min(minX, loc.gridX); maxX = Math.max(maxX, loc.gridX); minY = Math.min(minY, loc.gridY); maxY = Math.max(maxY, loc.gridY); } offset = new TileLocation(minX, minY); for(TileLocation loc : locations){ selectedLocations.add(new TileLocation(loc.gridX - offset.gridX, loc.gridY - offset.gridY)); } width = maxX-minX+1; height = maxY-minY+1; if(selectedLocations.isEmpty()){ if(tileLayer.getBase().getSelection()==this){ tileLayer.getBase().anchorSelection(); } return; } calculateBoundingRect(); } public List<Tile> onCopy() { List<Tile> answer = new ArrayList<Tile>(); for(TileLocation loc : selectedLocations){ if(tileLayer.isValidLocation(loc.gridX+offset.gridX, loc.gridY+offset.gridY)){ answer.add(new Tile(tileLayer.getNodeAt(loc.gridX+offset.gridX, loc.gridY+offset.gridY).getTileData(), loc, offset)); } } return answer; } // public List<Tile> onCut() { // List<Tile> answer = onCopy(); // onClear(); // return answer; // } @Override public void onClear() { for(TileLocation t : selectedLocations){ if(tileLayer.isValidLocation(t.gridX+offset.gridX, t.gridY+offset.gridY)){ tileLayer.getNodeAt(t.gridX+offset.gridX, t.gridY+offset.gridY).resetTileset(); } } } public int getTileWidth(){ return width; } public int getTileHeight(){ return height; } public void onRemove(){ tileLayer.silentlyIgnoreInput(false); } public int getTileCount(){ return selectedLocations.size(); } private void calculateBoundingRect(){ List<FixedWidthOutlineRectNode> boundingRect = new ArrayList<FixedWidthOutlineRectNode>(); boundingRect.clear(); int[][] sideGrid = new int[width][height]; TileLocation[][] grid = new TileLocation[width][height]; for(TileLocation l : selectedLocations){ grid[l.gridX][l.gridY] = l; } for(int i = 0; i < grid.length; i++){ sideGrid[i] = new int[grid[i].length]; for(int j = 0; j < grid[i].length; j++){ sideGrid[i][j] = AnimatedOutlineRectNode.NONE; if(grid[i][j]==null) continue; //perform edge detection, if any edges are detected, create a node if(i-1<0||grid[i-1][j]==null) sideGrid[i][j]|=AnimatedOutlineRectNode.LEFT; if(i+1>=grid.length||grid[i+1][j]==null) sideGrid[i][j]|=AnimatedOutlineRectNode.RIGHT; if(j-1<0||grid[i][j-1]==null) sideGrid[i][j]|=AnimatedOutlineRectNode.TOP; if(j+1>=grid[i].length||grid[i][j+1]==null) sideGrid[i][j]|=AnimatedOutlineRectNode.BOTTOM; } } //try to build the largest lines possible List<Line2D> lines = new ArrayList<Line2D>(); for(int i = 0; i < sideGrid.length; i++){ for(int j = 0; j < sideGrid[i].length; j++){ if((sideGrid[i][j]&AnimatedOutlineRectNode.LEFT)==AnimatedOutlineRectNode.LEFT){ int k = 0; for(; k + j < sideGrid[i].length&&(sideGrid[i][k+j]&AnimatedOutlineRectNode.LEFT)==AnimatedOutlineRectNode.LEFT; k++){ sideGrid[i][j+k] &=~AnimatedOutlineRectNode.LEFT; } lines.add(new Line2D.Double(i, j, i, j+k)); } if((sideGrid[i][j]&AnimatedOutlineRectNode.RIGHT)==AnimatedOutlineRectNode.RIGHT){ int k = 0; for(; k + j < sideGrid[i].length&&(sideGrid[i][k+j]&AnimatedOutlineRectNode.RIGHT)==AnimatedOutlineRectNode.RIGHT; k++){ sideGrid[i][j+k] &=~AnimatedOutlineRectNode.RIGHT; } lines.add(new Line2D.Double(i+1, j, i+1, j+k)); } if((sideGrid[i][j]&AnimatedOutlineRectNode.TOP)==AnimatedOutlineRectNode.TOP){ int k = 0; for(; k + i < sideGrid.length&&(sideGrid[i+k][j]&AnimatedOutlineRectNode.TOP)==AnimatedOutlineRectNode.TOP; k++){ sideGrid[i+k][j] &=~AnimatedOutlineRectNode.TOP; } lines.add(new Line2D.Double(i, j, i+k, j)); } if((sideGrid[i][j]&AnimatedOutlineRectNode.BOTTOM)==AnimatedOutlineRectNode.BOTTOM){ int k = 0; for(; k + i < sideGrid.length&&(sideGrid[i+k][j]&AnimatedOutlineRectNode.BOTTOM)==AnimatedOutlineRectNode.BOTTOM; k++){ sideGrid[i+k][j] &=~AnimatedOutlineRectNode.BOTTOM; } lines.add(new Line2D.Double(i, j+1, i+k, j+1)); } } } linesNode.setLines(lines); linesNode2.setLines(lines); linesNode.setBounds(tileLayer.getGridWidth()*offset.gridX, tileLayer.getGridHeight()*offset.gridY, Math.min(tileLayer.getGridWidth()*width, tileLayer.getWidth()-tileLayer.getGridWidth()*offset.gridX), Math.min(tileLayer.getGridHeight()*height, tileLayer.getHeight()-tileLayer.getGridHeight()*offset.gridY)); linesNode2.setBounds(tileLayer.getGridWidth()*offset.gridX, tileLayer.getGridHeight()*offset.gridY, Math.min(tileLayer.getGridWidth()*width, tileLayer.getWidth()-tileLayer.getGridWidth()*offset.gridX), Math.min(tileLayer.getGridHeight()*height, tileLayer.getHeight()-tileLayer.getGridHeight()*offset.gridY)); linesNode.repaint(); linesNode2.repaint(); } public PNode getOverlayNode() { return overlayNode; } @Override public boolean isNodeInSelection(TilePNode node) { TileLocation loc = node.getTile().getLocation(); for(TileLocation l : selectedLocations){ if(loc.equals(l, offset)) return true; } return false; } @Override public void onAnchor() { // TODO Auto-generated method stub } @Override public PNode getSelectionNode() { return null; } public void removeFromSelection(List<TileLocation> toRemove) { for(TileLocation l : toRemove){ selectedLocations.remove(new TileLocation(l.gridX - offset.gridX, l.gridY - offset.gridY)); } for(TileLocation l : selectedLocations){ l.set(l.gridX+offset.gridX, l.gridY+offset.gridY); } recalculateTiles(new ArrayList<TileLocation>(selectedLocations)); } public void addToSelection(List<TileLocation> toAdd) { for(TileLocation l : selectedLocations){ l.set(l.gridX+offset.gridX, l.gridY+offset.gridY); } selectedLocations.addAll(toAdd); recalculateTiles(new ArrayList<TileLocation>(selectedLocations)); } @Override public void setToTiles(List<Tile> tiles) { selectedLocations.clear(); tileLayer.silentlyIgnoreInput(true); if(!tiles.isEmpty()) offset = tiles.get(0).offset.copy(); for(Tile t : tiles){ tileLayer.getNodeAt(t.getLocation()).silentlyIgnoreInput(false); tileLayer.setTile(t); selectedLocations.add(t.relativeLocation.copy()); } calculateBoundingRect(); } @Override public void onLift() { // TODO Auto-generated method stub } }