Search in sources :

Example 26 with Tile

use of org.pepsoft.worldpainter.Tile in project WorldPainter by Captain-Chaos.

the class Background3DTileRenderer method run.

@Override
public void run() {
    if (logger.isDebugEnabled()) {
        logger.debug("Background 3D rendering thread started");
    }
    try {
        while (running) {
            synchronized (this) {
                Tile3DRenderJob job = jobQueue.takeJob();
                Tile tile = job.getTile();
                renderTile(tile);
            }
        }
    } catch (InterruptedException e) {
        if (running) {
            throw new RuntimeException("Thread interrupted while waiting for render job", e);
        }
    }
    if (logger.isDebugEnabled()) {
        logger.debug("Background 3D rendering thread halted");
    }
}
Also used : Tile(org.pepsoft.worldpainter.Tile)

Example 27 with Tile

use of org.pepsoft.worldpainter.Tile in project WorldPainter by Captain-Chaos.

the class ThreeDeeView method actionPerformed.

// ActionListener
@Override
public void actionPerformed(ActionEvent e) {
    // Send tiles to be rendered
    if ((!tilesWaitingToBeRendered.isEmpty()) && ((System.currentTimeMillis() - lastTileChange) > 250)) {
        tilesWaitingToBeRendered.forEach(threeDeeRenderManager::renderTile);
        tilesWaitingToBeRendered.clear();
    }
    // Collect rendered tiles
    Set<RenderResult> renderResults = threeDeeRenderManager.getRenderedTiles();
    Rectangle repaintArea = null;
    for (RenderResult renderResult : renderResults) {
        Tile tile = renderResult.getTile();
        int x = tile.getX(), y = tile.getY();
        renderedTiles.put(tile, renderResult.getImage());
        Rectangle tileBounds = zoom(getTileBounds(x, y));
        if (repaintArea == null) {
            repaintArea = tileBounds;
        } else {
            repaintArea = repaintArea.union(tileBounds);
        }
    }
    if (repaintArea != null) {
        // System.out.println("Repainting " + repaintArea);
        repaint(repaintArea);
    }
}
Also used : Rectangle(java.awt.Rectangle) Tile(org.pepsoft.worldpainter.Tile) Point(java.awt.Point)

Example 28 with Tile

use of org.pepsoft.worldpainter.Tile in project WorldPainter by Captain-Chaos.

the class ThreeDeeView method paintComponent.

@Override
protected void paintComponent(Graphics g) {
    // System.out.println("Drawing");
    Graphics2D g2 = (Graphics2D) g;
    if (zoom != 1) {
        double scaleFactor = Math.pow(2.0, zoom - 1);
        // System.out.println("Scaling with factor " + scaleFactor);
        g2.scale(scaleFactor, scaleFactor);
        if (zoom > 1) {
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        } else {
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        }
    }
    if (upsideDown) {
        g2.scale(1.0, -1.0);
        g2.translate(0, -getHeight());
    }
    Rectangle visibleRect = unzoom(getVisibleRect());
    // System.out.println("Unzoomed visible rectangle: " + visibleRect);
    int centerX = visibleRect.x + visibleRect.width / 2;
    int centerY = visibleRect.y + visibleRect.height / 2 + waterLevel;
    Tile mostCentredTile = null;
    int smallestDistance = Integer.MAX_VALUE;
    Rectangle clipBounds = g.getClipBounds();
    for (Tile tile : zSortedTiles) {
        Rectangle tileBounds = getTileBounds(tile.getX(), tile.getY());
        // System.out.print("Tile bounds: " + tileBounds);
        if (tileBounds.intersects(clipBounds)) {
            // System.out.println(" intersects");
            int dx = tileBounds.x + tileBounds.width / 2 - centerX;
            int dy = tileBounds.y + tileBounds.height - TILE_SIZE / 2 - centerY;
            int dist = (int) Math.sqrt((dx * dx) + (dy * dy));
            if (dist < smallestDistance) {
                smallestDistance = dist;
                mostCentredTile = tile;
            }
            BufferedImage tileImg = renderedTiles.get(tile);
            if (tileImg != null) {
                g.drawImage(tileImg, tileBounds.x, tileBounds.y, null);
            } else {
                tilesWaitingToBeRendered.add(0, tile);
            }
        // } else {
        // System.out.println(" does NOT intersect");
        }
    }
    if (mostCentredTile != null) {
        centreTile = new Point(mostCentredTile.getX(), mostCentredTile.getY());
    }
    if (highlightTile != null) {
        g.setColor(Color.RED);
        Rectangle rect = getTileBounds(highlightTile.x, highlightTile.y);
        g.drawRect(rect.x, rect.y, rect.width, rect.height);
    }
    if (highlightPoint != null) {
        g.setColor(Color.RED);
        g.drawLine(highlightPoint.x - 2, highlightPoint.y, highlightPoint.x + 2, highlightPoint.y);
        g.drawLine(highlightPoint.x, highlightPoint.y - 2, highlightPoint.x, highlightPoint.y + 2);
    }
// for (Map.Entry<Point, BufferedImage> entry: renderedTiles.entrySet()) {
// Point tileCoords = entry.getKey();
// BufferedImage tileImg = entry.getValue();
// Rectangle tileBounds = getTileBounds(tileCoords.x, tileCoords.y);
// if (tileBounds.intersects(clipBounds)) {
// g.drawImage(tileImg, tileBounds.x, tileBounds.y, null);
// //                g.setColor(Color.RED);
// //                g.drawRect(tileBounds.x, tileBounds.y, tileBounds.width, tileBounds.height);
// }
// }
}
Also used : Rectangle(java.awt.Rectangle) Tile(org.pepsoft.worldpainter.Tile) Point(java.awt.Point) Point(java.awt.Point) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D)

Example 29 with Tile

use of org.pepsoft.worldpainter.Tile in project WorldPainter by Captain-Chaos.

the class SelectionHelper method copySelection.

public void copySelection(int targetX, int targetY, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled {
    Rectangle bounds = getSelectionBounds();
    if (bounds == null) {
        // No selection
        return;
    }
    final int dx = targetX - bounds.x;
    final int dy = targetY - bounds.y;
    if ((dx == 0) && (dy == 0)) {
        // Target is at the same location as the selection
        return;
    }
    final int tileX1 = bounds.x >> TILE_SIZE_BITS;
    final int tileX2 = (bounds.x + bounds.width - 1) >> TILE_SIZE_BITS;
    final int tileY1 = bounds.y >> TILE_SIZE_BITS;
    final int tileY2 = (bounds.y + bounds.height - 1) >> TILE_SIZE_BITS;
    // Make sure to copy in the right direction to avoid problems if the
    // destination overlaps the selection
    clearUndoOnNewTileCreation = options.createNewTiles;
    if (dx > 0) {
        // Shifting right
        if (dy > 0) {
            // Shifting right and down
            for (int tileX = tileX2; tileX >= tileX1; tileX--) {
                for (int tileY = tileY2; tileY >= tileY1; tileY--) {
                    Tile tile = dimension.getTile(tileX, tileY);
                    if (tile != null) {
                        for (int xInTile = TILE_SIZE - 1; xInTile >= 0; xInTile--) {
                            for (int yInTile = TILE_SIZE - 1; yInTile >= 0; yInTile--) {
                                processColumn(tile, xInTile, yInTile, dx, dy);
                            }
                        }
                    }
                }
                if (progressReceiver != null) {
                    progressReceiver.setProgress((float) (tileX2 - tileX + 1) / (tileX2 - tileX1 + 1));
                }
            }
        } else {
            // Shifting right or right and up
            for (int tileX = tileX2; tileX >= tileX1; tileX--) {
                for (int tileY = tileY1; tileY <= tileY2; tileY++) {
                    Tile tile = dimension.getTile(tileX, tileY);
                    if (tile != null) {
                        for (int xInTile = TILE_SIZE - 1; xInTile >= 0; xInTile--) {
                            for (int yInTile = 0; yInTile < TILE_SIZE; yInTile++) {
                                processColumn(tile, xInTile, yInTile, dx, dy);
                            }
                        }
                    }
                }
                if (progressReceiver != null) {
                    progressReceiver.setProgress((float) (tileX2 - tileX + 1) / (tileX2 - tileX1 + 1));
                }
            }
        }
    } else {
        // Shifting left or not horizontally
        if (dy > 0) {
            // Shifting down or left and down
            for (int tileX = tileX1; tileX <= tileX2; tileX++) {
                for (int tileY = tileY2; tileY >= tileY1; tileY--) {
                    Tile tile = dimension.getTile(tileX, tileY);
                    if (tile != null) {
                        for (int xInTile = 0; xInTile < TILE_SIZE; xInTile++) {
                            for (int yInTile = TILE_SIZE - 1; yInTile >= 0; yInTile--) {
                                processColumn(tile, xInTile, yInTile, dx, dy);
                            }
                        }
                    }
                }
                if (progressReceiver != null) {
                    progressReceiver.setProgress((float) (tileX - tileX1 + 1) / (tileX2 - tileX1 + 1));
                }
            }
        } else {
            // Shifting up or left and up
            for (int tileX = tileX1; tileX <= tileX2; tileX++) {
                for (int tileY = tileY1; tileY <= tileY2; tileY++) {
                    Tile tile = dimension.getTile(tileX, tileY);
                    if (tile != null) {
                        for (int xInTile = 0; xInTile < TILE_SIZE; xInTile++) {
                            for (int yInTile = 0; yInTile < TILE_SIZE; yInTile++) {
                                processColumn(tile, xInTile, yInTile, dx, dy);
                            }
                        }
                    }
                }
                if (progressReceiver != null) {
                    progressReceiver.setProgress((float) (tileX - tileX1 + 1) / (tileX2 - tileX1 + 1));
                }
            }
        }
    }
}
Also used : Tile(org.pepsoft.worldpainter.Tile)

Example 30 with Tile

use of org.pepsoft.worldpainter.Tile in project WorldPainter by Captain-Chaos.

the class SelectionHelper method editSelection.

private void editSelection(Shape shape, boolean add) {
    // Determine the bounding box of the selection in tile coordinates
    final Rectangle shapeBounds = shape.getBounds();
    final int tileX1 = shapeBounds.x >> TILE_SIZE_BITS;
    final int tileX2 = (shapeBounds.x + shapeBounds.width - 1) >> TILE_SIZE_BITS;
    final int tileY1 = shapeBounds.y >> TILE_SIZE_BITS;
    final int tileY2 = (shapeBounds.y + shapeBounds.height - 1) >> TILE_SIZE_BITS;
    // Iterate over all the tiles in the bounding box
    for (int tileX = tileX1; tileX <= tileX2; tileX++) {
        for (int tileY = tileY1; tileY <= tileY2; tileY++) {
            Tile tile = dimension.getTileForEditing(tileX, tileY);
            if (tile != null) {
                Rectangle tileBounds = new Rectangle(tileX << TILE_SIZE_BITS, tileY << TILE_SIZE_BITS, TILE_SIZE, TILE_SIZE);
                if (shape.contains(tileBounds)) {
                    // The tile lies entirely inside the selection
                    if (add) {
                        tile.clearLayerData(SelectionBlock.INSTANCE);
                        fillTile(tile, SelectionChunk.INSTANCE);
                    } else {
                        tile.clearLayerData(SelectionBlock.INSTANCE);
                        tile.clearLayerData(SelectionChunk.INSTANCE);
                    }
                } else if (shape.intersects(tileBounds)) {
                    // lie entirely inside it; go chunk by chunk
                    for (int chunkX = 0; chunkX < TILE_SIZE; chunkX += 16) {
                        for (int chunkY = 0; chunkY < TILE_SIZE; chunkY += 16) {
                            Rectangle chunkBounds = new Rectangle(tileBounds.x + chunkX, tileBounds.y + chunkY, 16, 16);
                            if (shape.contains(chunkBounds)) {
                                // selection
                                if (add) {
                                    clearTile(tile, SelectionBlock.INSTANCE, chunkX, chunkY, 16, 16);
                                    tile.setBitLayerValue(SelectionChunk.INSTANCE, chunkX, chunkY, true);
                                } else {
                                    clearTile(tile, SelectionBlock.INSTANCE, chunkX, chunkY, 16, 16);
                                    tile.setBitLayerValue(SelectionChunk.INSTANCE, chunkX, chunkY, false);
                                }
                            } else if (shape.intersects(chunkBounds)) {
                                // go block by block
                                if (add && (!tile.getBitLayerValue(SelectionChunk.INSTANCE, chunkX, chunkY))) {
                                    // The chunk is not yet entirely selected
                                    for (int dx = 0; dx < 16; dx++) {
                                        for (int dy = 0; dy < 16; dy++) {
                                            int blockX = chunkBounds.x + dx;
                                            int blockY = chunkBounds.y + dy;
                                            if (shape.contains(blockX, blockY)) {
                                                tile.setBitLayerValue(SelectionBlock.INSTANCE, chunkX + dx, chunkY + dy, true);
                                            }
                                        }
                                    }
                                } else if (!add) {
                                    if (tile.getBitLayerValue(SelectionChunk.INSTANCE, chunkX, chunkY)) {
                                        // The chunk is entirely selected
                                        tile.setBitLayerValue(SelectionChunk.INSTANCE, chunkX, chunkY, false);
                                        for (int dx = 0; dx < 16; dx++) {
                                            for (int dy = 0; dy < 16; dy++) {
                                                int blockX = chunkBounds.x + dx;
                                                int blockY = chunkBounds.y + dy;
                                                tile.setBitLayerValue(SelectionBlock.INSTANCE, chunkX + dx, chunkY + dy, !shape.contains(blockX, blockY));
                                            }
                                        }
                                    } else {
                                        for (int dx = 0; dx < 16; dx++) {
                                            for (int dy = 0; dy < 16; dy++) {
                                                int blockX = chunkBounds.x + dx;
                                                int blockY = chunkBounds.y + dy;
                                                if (shape.contains(blockX, blockY)) {
                                                    tile.setBitLayerValue(SelectionBlock.INSTANCE, chunkX + dx, chunkY + dy, false);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : Tile(org.pepsoft.worldpainter.Tile)

Aggregations

Tile (org.pepsoft.worldpainter.Tile)31 Dimension (org.pepsoft.worldpainter.Dimension)6 CombinedLayer (org.pepsoft.worldpainter.layers.CombinedLayer)5 Point (java.awt.Point)4 FileOutputStream (java.io.FileOutputStream)4 Terrain (org.pepsoft.worldpainter.Terrain)4 World2 (org.pepsoft.worldpainter.World2)4 Rectangle (java.awt.Rectangle)3 BufferedImage (java.awt.image.BufferedImage)3 File (java.io.File)3 FileInputStream (java.io.FileInputStream)3 ObjectInputStream (java.io.ObjectInputStream)3 GZIPInputStream (java.util.zip.GZIPInputStream)3 SubProgressReceiver (org.pepsoft.util.SubProgressReceiver)3 Layer (org.pepsoft.worldpainter.layers.Layer)3 Graphics2D (java.awt.Graphics2D)2 ObjectOutputStream (java.io.ObjectOutputStream)2 PrintWriter (java.io.PrintWriter)2 java.util (java.util)2 List (java.util.List)2