Package com.jcloisterzone.ui.grid.layer

Source Code of com.jcloisterzone.ui.grid.layer.FarmHintsLayer$FarmHint

package com.jcloisterzone.ui.grid.layer;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.jcloisterzone.board.Location;
import com.jcloisterzone.board.Position;
import com.jcloisterzone.board.Tile;
import com.jcloisterzone.event.MeepleEvent;
import com.jcloisterzone.event.TileEvent;
import com.jcloisterzone.feature.Farm;
import com.jcloisterzone.feature.Feature;
import com.jcloisterzone.feature.visitor.FeatureVisitor;
import com.jcloisterzone.figure.Barn;
import com.jcloisterzone.figure.Follower;
import com.jcloisterzone.figure.Meeple;
import com.jcloisterzone.ui.grid.GridPanel;
import com.jcloisterzone.ui.resources.ResourceManager;

public class FarmHintsLayer extends AbstractGridLayer {

    private static final int FULL_SIZE = 300;
    private static final AlphaComposite HINT_ALPHA_COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .4f);

    private boolean visible;
    private boolean doRefreshHints;
    final Map<Tile, Map<Location, Area>> areas = new HashMap<>();
    private final List<FarmHint> hints = new ArrayList<>();

    public FarmHintsLayer(GridPanel gridPanel) {
        super(gridPanel);
        refreshHints();
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
        gridPanel.repaint();
    }

    @Override
    public void paint(Graphics2D g2) {
        if (!visible) return;

        Composite old = g2.getComposite();
        g2.setComposite(HINT_ALPHA_COMPOSITE);
        int sqSize = getSquareSize();
        Double scale = sqSize == FULL_SIZE ? null : (double) sqSize / FULL_SIZE;
        TextureFactory textures = new TextureFactory(sqSize);

        if (doRefreshHints) {
            doRefreshHints = false;
            fillHints();
        }

        for (FarmHint fh : hints) {
            if (fh.scaledArea == null) {
                if (scale == null) {
                    fh.scaledArea = fh.area;
                } else {
                    fh.scaledArea = fh.area.createTransformedArea(AffineTransform.getScaleInstance(scale, scale));
                }
            }
            Area area = transformArea(fh.scaledArea, fh.position);
            if (fh.colors.length > 1) {
                g2.setPaint(textures.createMultiColor(fh.colors));
                g2.fill(area);
            } else {
                g2.setPaint(textures.create(fh.colors[0]));
                g2.fill(area);
            }
        }
        g2.setPaint(null);
        g2.setComposite(old);
    }

    public void tileEvent(TileEvent ev) {
        Tile tile = ev.getTile();
        if (ev.getType() == TileEvent.PLACEMENT) {
            ResourceManager resourceManager = getClient().getResourceManager();
            Set<Location> farmLocations = new HashSet<>();
            for (Feature f : tile.getFeatures()) {
                if (f instanceof Farm) {
                    farmLocations.add(f.getLocation());
                }
            }
            if (farmLocations.isEmpty()) return;
            Map<Location, Area> tAreas = resourceManager.getFeatureAreas(tile, FULL_SIZE, farmLocations);
            areas.put(tile, tAreas);
            refreshHints();
        }
        if (ev.getType() == TileEvent.REMOVE) {
            areas.remove(tile);
            refreshHints();
        }

    }

    public void meepleEvent(MeepleEvent ev) {
        if (
            (ev.getFrom() != null && ev.getFrom().getLocation().isFarmLocation()) ||
            (ev.getTo() != null && ev.getTo().getLocation().isFarmLocation())
        ) {
            refreshHints();
        }
    }


    public void refreshHints() {
        doRefreshHints = true;
    }

    private void fillHints() {
        hints.clear();
        final Set<Feature> processed = new HashSet<>();
        for (Entry<Tile, Map<Location, Area>> entry : areas.entrySet()) {
            for (Feature f : entry.getKey().getFeatures()) {
                if (!(f instanceof Farm)) continue;
                if (processed.contains(f)) continue;

                FarmHint fh = f.walk(new FeatureVisitor<FarmHint>() {
                    FarmHint result = new FarmHint(new Area(), null);
                    int x = Integer.MAX_VALUE;
                    int y = Integer.MAX_VALUE;
                    int size = 0;
                    boolean hasCity = false;
                    int[] power = new int[getGame().getAllPlayers().length];

                    @Override
                    public boolean visit(Feature feature) {
                        Farm f = (Farm) feature;
                        processed.add(f);
                        size++;
                        hasCity = hasCity || f.getAdjoiningCities() != null || f.isAdjoiningCityOfCarcassonne();
                        for (Meeple m : f.getMeeples()) {
                            if (m instanceof Follower) {
                                power[m.getPlayer().getIndex()] += ((Follower)m).getPower();
                            }
                            if (m instanceof Barn) {
                                power[m.getPlayer().getIndex()] += 1;
                            }
                        }
                        Position pos = f.getTile().getPosition();
                        if (pos.x < x) {
                            if (x != Integer.MAX_VALUE) result.area.transform(AffineTransform.getTranslateInstance(FULL_SIZE * (x-pos.x), 0));
                            x = pos.x;
                        }
                        if (pos.y < y) {
                            if (y != Integer.MAX_VALUE) result.area.transform(AffineTransform.getTranslateInstance(0, FULL_SIZE * (y-pos.y)));
                            y = pos.y;
                        }
                        Map<Location, Area> tileAreas = areas.get(f.getTile());
                        if (tileAreas != null) { //sync issue, feature can be extended in other thread, so it is not registered in areas yet
                            Area featureArea = new Area(tileAreas.get(f.getLocation()));
                            featureArea.transform(AffineTransform.getTranslateInstance(FULL_SIZE * (pos.x-x), FULL_SIZE*(pos.y-y)));
                            result.area.add(featureArea);
                        }
                        return true;
                    }

                    @Override
                    public FarmHint getResult() {
                        result.position = new Position(x, y);

                        int bestPower = 0;
                        List<Integer> bestPlayerIndexes = new ArrayList<>();
                        for (int i = 0; i < power.length; i++) {
                            if (power[i] == bestPower) {
                                bestPlayerIndexes.add(i);
                            }
                            if (power[i] > bestPower) {
                                bestPower = power[i];
                                bestPlayerIndexes.clear();
                                bestPlayerIndexes.add(i);
                            }
                        }
                        if (bestPower == 0) {
                            if (size < 2 || !hasCity) return null; //don't display unimportant farms
                            result.colors = new Color[] { Color.DARK_GRAY };
                        } else {
                            result.colors = new Color[bestPlayerIndexes.size()];
                            int i = 0;
                            for (Integer index : bestPlayerIndexes) {
                                result.colors[i++] = getGame().getPlayer(index).getColors().getMeepleColor();
                            }
                        }
                        return result;
                    }
                });
                if (fh == null) continue; //to small farm
                hints.add(fh);
            }
        }
    }

    @Override
    public void zoomChanged(int squareSize) {
        for (FarmHint fh : hints) {
            fh.scaledArea = null;
        }
    }

    static class FarmHint {
        public Area area;
        public Area scaledArea;
        public Position position;
        public Color colors[];

        public FarmHint(Area area, Position position) {
            this.area = area;
            this.position = position;
        }
    }

}
TOP

Related Classes of com.jcloisterzone.ui.grid.layer.FarmHintsLayer$FarmHint

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.