Package tiled.view

Source Code of tiled.view.MapView

/*
*  Tiled Map Editor, (c) 2004-2006
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  Adam Turk <aturk@biggeruniverse.com>
*  Bjorn Lindeijer <bjorn@lindeijer.nl>
*/

package tiled.view;

import java.awt.Graphics;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;

import tiled.core.Map;
import tiled.core.MapLayer;
import tiled.core.MultilayerPlane;
import tiled.core.ObjectGroup;
import tiled.core.TileLayer;
import tiled.mapeditor.brush.Brush;
import tiled.mapeditor.selection.SelectionLayer;

import com.onpositive.mapper.editors.MapEditor;
import com.onpositive.mapper.painting.ISpecialLayerPainter;
import com.onpositive.mapper.painting.ObjectSelectionLayerPainter;

/**
* The base class for map views. This is meant to be extended for different tile
* map orientations, such as orthagonal and isometric.
*
* @version $Id$
*/
public abstract class MapView extends Composite implements PaintListener {
  private static final int UNSELECTED_LAYER_ALPHA = 100;
  public static final int PF_BOUNDARYMODE = 0x02;
  public static final int PF_COORDINATES = 0x04;
  public static final int PF_NOSPECIAL = 0x08;
 
  public static int ZOOM_NORMALSIZE = 5;

  protected Map map;
  protected Brush currentBrush;
  protected int modeFlags;
  protected double zoom = 1.0;
  protected int zoomLevel = ZOOM_NORMALSIZE;

  // Grid properties
  protected boolean showGrid;
  protected boolean antialiasGrid;
  protected Color gridColor;
  protected int gridOpacity = 180;

  protected boolean highlightSelectedLayer = false;

  protected static double[] zoomLevels = { 0.0625, 0.125, 0.25, 0.5, 0.75,
      1.0, 1.5, 2.0, 3.0, 4.0 };

  private static final RGB DEFAULT_BACKGROUND_COLOR = new RGB(64, 64, 64);
  /** The default grid color (black). */
  public static final RGB DEFAULT_GRID_COLOR = new RGB(0, 0, 0);
  protected static final int SEL_HOVER_ALPHA = 50;
  protected static final int OPAQUE = 255;

  protected static Image propertyFlagImage;

  protected Color defaultBgColor;
  protected Color defaultGridColor;
  protected int pointerState;
  protected List<ISpecialLayerPainter> specialLayerPainters = new ArrayList<ISpecialLayerPainter>();
  private int currentLayer = 0;
 
  protected boolean drawResizeAnchors = true;

  /**
   * Creates a new <code>MapView</code> that displays the specified map.
   *
   * @param map
   *            the map to be displayed by this map view
   */
  protected MapView(Composite parent, Map map) {
    super(parent, SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED);
    // Setup static bits on first invocation
    if (MapView.propertyFlagImage == null) {
      try {
        // MapView.propertyFlagImage = //TODO
        // Resources.getImage("propertyflag-12.png");
      } catch (Exception e) {
      }
    }

    this.map = map;
    defaultBgColor = new Color(getDisplay(), DEFAULT_BACKGROUND_COLOR);
    defaultGridColor = new Color(getDisplay(), DEFAULT_GRID_COLOR);
    addPaintListener(this);
    // setOpaque(true);
        Point preferredSize = getPreferredSize();
        setBounds(0,0,preferredSize.x,preferredSize.y);
  }

  public void toggleMode(int modeModifier) {
    modeFlags ^= modeModifier;
    redraw();
  }

  public void setMode(int modeModifier, boolean value) {
    if (value) {
      modeFlags |= modeModifier;
    } else {
      modeFlags &= ~modeModifier;
    }
    redraw();
  }

  public boolean getMode(int modeModifier) {
    return (modeFlags & modeModifier) != 0;
  }

  public void setGridColor(Color gridColor) {
    this.gridColor = gridColor;
    redraw();
  }

  public void setGridOpacity(int gridOpacity) {
    this.gridOpacity = gridOpacity;
    redraw();
  }

  public void setAntialiasGrid(boolean antialiasGrid) {
    this.antialiasGrid = antialiasGrid;
    redraw();
  }

  public boolean isShowGrid() {
    return showGrid;
  }

  public void setShowGrid(boolean showGrid) {
    this.showGrid = showGrid;
    redraw();
  }

  /**
   * Sets a new brush. The brush can draw a preview of the change while
   * editing.
   *
   * @param brush
   *            the new brush
   */
  public void setBrush(Brush brush) {
    currentBrush = brush;
  }

  // Zooming

  public boolean zoomIn() {
    if (zoomLevel < zoomLevels.length - 1) {
      setZoomLevel(zoomLevel + 1);
    }

    return zoomLevel < zoomLevels.length - 1;
  }

  public boolean zoomOut() {
    if (zoomLevel > 0) {
      setZoomLevel(zoomLevel - 1);
    }

    return zoomLevel > 0;
  }

  public void setZoom(double zoom) {
    if (zoom > 0) {
      this.zoom = zoom;
      // revalidate();
      setSize(computeSize(-1, -1));
    }
  }

  public void setZoomLevel(int zoomLevel) {
    if (zoomLevel >= 0 && zoomLevel < zoomLevels.length) {
      this.zoomLevel = zoomLevel;
      setZoom(zoomLevels[zoomLevel]);
    }
  }

  public double getZoom() {
    return zoom;
  }

  public int getZoomLevel() {
    return zoomLevel;
  }

  // Scrolling

  public abstract Point getPreferredSize();

  public Point getPreferredScrollableViewportSize() {
    return getPreferredSize();
  }

  @Override
  public Point computeSize(int wHint, int hHint) {
    return getPreferredSize();
  }

  public boolean getScrollableTracksViewportHeight() {
    return false;
  }

  public boolean getScrollableTracksViewportWidth() {
    return false;
  }

  public abstract int getScrollableBlockIncrement(Rectangle visibleRect,
      int orientation, int direction);

  public abstract int getScrollableUnitIncrement(Rectangle visibleRect,
      int orientation, int direction);

  /**
   * Creates a MapView instance that will render the map in the right
   * orientation.
   *
   * @param p
   *            the Map to create a view for
   * @return a suitable instance of a MapView for the given Map
   * @see Map#getOrientation()
   */
  public static MapView createViewforMap(Composite parent, Map p) {
    MapView mapView = null;

    int orientation = p.getOrientation();

    if (orientation == Map.ORIENTATION_ISOMETRIC) {
      mapView = new IsoMapView(parent, p);
    } else if (orientation == Map.ORIENTATION_ORTHOGONAL) {
      mapView = new OrthoMapView(parent, p);
      mapView.addSpecialLayerPainter(new ObjectSelectionLayerPainter());
    } else if (orientation == Map.ORIENTATION_HEXAGONAL) {
      mapView = new HexMapView(parent, p);
    } else if (orientation == Map.ORIENTATION_SHIFTED) {
      mapView = new ShiftedMapView(parent, p);
    }

    return mapView;
  }

  // Painting

  /**
   * Draws all the visible layers of the map. Takes several flags into account
   * when drawing, and will also draw the grid, and any 'special' layers.
   *
   * @param g
   *            the GC object to paint to
   * @see javax.swing.JComponent#paintComponent(Graphics)
   * @see MapLayer
   * @see SelectionLayer
   */
  public void paintControl(PaintEvent e) {
    GC gc = e.gc;

    MapLayer layer;
    Rectangle clip = gc.getClipping();

    gc.setLineWidth(2);

    // Do an initial fill with the background color
    // todo: make background color configurable
    // try {
    // String colorString = displayPrefs.get("backgroundColor", "");
    // g2d.setColor(Color.decode(colorString));
    // } catch (NumberFormatException e) {
    // }
    gc.setBackground(defaultBgColor);
    gc.fillRectangle(clip.x, clip.y, clip.width, clip.height);

    paintSubMap(map, gc, 1.0f);

    if (!getMode(PF_NOSPECIAL)) {
      Iterator<?> li = map.getLayersSpecial();

      while (li.hasNext()) {
        layer = (MapLayer) li.next();
        if (layer.isVisible()) {
          if (layer instanceof SelectionLayer) {
            // g2d.setComposite(AlphaComposite.getInstance(
            // AlphaComposite.SRC_ATOP, 0.3f));
            gc.setForeground(((SelectionLayer) layer)
                .getHighlightColor());
            gc.setBackground(((SelectionLayer) layer)
                .getHighlightColor());
          }
          if (layer instanceof TileLayer)
            paintLayer(gc, (TileLayer) layer);
          else if (layer instanceof ObjectGroup) {
            boolean needRegularPaint = true;
            for (ISpecialLayerPainter painter : specialLayerPainters) {
              needRegularPaint = needRegularPaint && painter.needRegularPaint(layer);
            }
            if (needRegularPaint)
              paintObjectGroup(gc, (ObjectGroup) layer);
            for (ISpecialLayerPainter painter : specialLayerPainters) {
              painter.paintSpecialLayer(gc, layer);
            }
          }
          gc.setAlpha(255);
        }
      }

      // Paint Brush
      // if (currentBrush != null) {
      // currentBrush.drawPreview(g2d, this);
      // }
    }

    // Grid color (also used for coordinates)
    if (gridColor != null)
      gc.setForeground(gridColor);
    else
      gc.setForeground(defaultGridColor);

    if (showGrid) {
      // Grid opacity
      gc.setAlpha(gridOpacity);
      // if (gridOpacity < 255) {
      // g2d.setComposite(AlphaComposite.getInstance(
      // AlphaComposite.SRC_ATOP,
      // (float) gridOpacity / 255.0f));
      // }
      // else {
      // g2d.setComposite(AlphaComposite.SrcOver);
      // }

      // Configure grid antialiasing
      // if (antialiasGrid) {
      // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
      // RenderingHints.VALUE_ANTIALIAS_ON);
      // }
      // else {
      // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
      // RenderingHints.VALUE_ANTIALIAS_OFF);
      // }

      gc.setLineWidth(1);
      paintGrid(gc);
    }

    if (getMode(PF_COORDINATES)) {
      // g2d.setComposite(AlphaComposite.SrcOver);
      paintCoordinates(gc);
    }

    // if (editor != null && editor.getCurrentLayer() instanceof TileLayer)
    // {
    // g2d.setComposite(AlphaComposite.SrcOver);
    //
    // TileLayer tl = (TileLayer) editor.getCurrentLayer();
    // if (tl != null && tl.isVisible()) {
    // paintPropertyFlags(g2d, tl);
    // }
    // }
  }

  public void paintSubMap(MultilayerPlane m, GC gc, float mapOpacity) {
    Iterator<?> li = m.getLayers();
    MapLayer layer;

    while (li.hasNext()) {
      layer = (MapLayer) li.next();
      if (layer != null) {
        float opacity = layer.getOpacity() * mapOpacity;
        if (layer.isVisible() && opacity > 0.0f) {
          // if (opacity < 1.0f) {
          // g2d.setComposite(AlphaComposite.getInstance(
          // AlphaComposite.SRC_ATOP, opacity));
          // }
          // else {
          // g2d.setComposite(AlphaComposite.SrcOver);
          // }
          if (highlightSelectedLayer
              && m.getLayer(currentLayer) != layer)
            gc.setAlpha(UNSELECTED_LAYER_ALPHA); //Make unselected layers half-transparent
          if (layer instanceof TileLayer) {
            paintLayer(gc, (TileLayer) layer);
          } else if (layer instanceof ObjectGroup) {
            paintObjectGroup(gc, (ObjectGroup) layer);
          }
          gc.setAlpha(255);
        }
      }
    }
  }

  /**
   * Draws a TileLayer. Implemented in a subclass.
   *
   * @param g2d
   *            the graphics context to draw the layer onto
   * @param layer
   *            the TileLayer to be drawn
   */
  protected abstract void paintLayer(GC g2d, TileLayer layer);

  /**
   * Draws an ObjectGroup. Implemented in a subclass.
   *
   * @param g2d
   *            the graphics context to draw the object group onto
   * @param og
   *            the ObjectGroup to be drawn
   */
  protected abstract void paintObjectGroup(GC g2d, ObjectGroup og);

  protected void paintEdge(GC g2d, MapLayer layer, int x, int y) {
    /*
     * Polygon grid = createGridPolygon(x, y, 0); PathIterator itr =
     * grid.getPathIterator(null); double nextPoint[] = new double[6];
     * double prevPoint[], firstPoint[];
     *
     * Point p = screenToTileCoords(x, y); int tx = p.x; int ty = p.y;
     *
     * itr.currentSegment(nextPoint); firstPoint = prevPoint = nextPoint;
     *
     * // Top itr.next(); nextPoint = new double[6];
     * itr.currentSegment(nextPoint); if (layer.getTileAt(tx, ty - 1) ==
     * null) { g.drawLine( (int)prevPoint[0], (int)prevPoint[1],
     * (int)nextPoint[0], (int)nextPoint[1]); }
     *
     * // Right itr.next(); prevPoint = nextPoint; nextPoint = new
     * double[6]; itr.currentSegment(nextPoint); if (layer.getTileAt(tx + 1,
     * ty) == null) { g.drawLine( (int)prevPoint[0], (int)prevPoint[1],
     * (int)nextPoint[0], (int)nextPoint[1]); }
     *
     * // Left itr.next(); prevPoint = nextPoint; nextPoint = new double[6];
     * itr.currentSegment(nextPoint); if (layer.getTileAt(tx, ty + 1) ==
     * null) { g.drawLine( (int)prevPoint[0], (int)prevPoint[1],
     * (int)nextPoint[0], (int)nextPoint[1]); }
     *
     * // Bottom if (layer.getTileAt(tx - 1, ty) == null) { g.drawLine(
     * (int)nextPoint[0], (int)nextPoint[1], (int)firstPoint[0],
     * (int)firstPoint[1]); }
     */
  }

  /**
   * Tells this view a certain region of the map needs to be repainted.
   * <p>
   * Same as calling repaint() unless implemented more efficiently in a
   * subclass.
   *
   * @param region
   *            the region that has changed in tile coordinates
   */
  public void repaintRegion(Rectangle region) {
    redraw(region.x, region.y, region.width, region.height, true);
  }

  /**
   * Draws the map grid.
   *
   * @param g2d
   *            the graphics context to draw the grid onto
   */
  protected abstract void paintGrid(GC g2d);

  /**
   * Draws the coordinates on each tile.
   *
   * @param g2d
   *            the graphics context to draw the coordinates onto
   */
  protected abstract void paintCoordinates(GC g2d);

  protected abstract void paintPropertyFlags(GC g2d, TileLayer layer);

  /**
   * Returns a Polygon that matches the grid around the specified <b>Map</b>.
   *
   * @param tx
   * @param ty
   * @param border
   * @return the created polygon
   */
  protected abstract Polygon createGridPolygon(int tx, int ty, int border);

  // Conversion functions

  public abstract Point screenToTileCoords(int x, int y);

  /**
   * Returns the pixel coordinates on the map based on the given screen
   * coordinates. The map pixel coordinates may be different in more ways than
   * the zoom level, depending on the projection the view implements.
   *
   * @param x
   *            x in screen coordinates
   * @param y
   *            y in screen coordinates
   * @return the position in map pixel coordinates
   */
  public abstract Point screenToPixelCoords(int x, int y);

  /**
   * Returns the location on the screen of the top corner of a tile.
   *
   * @param x
   * @param y
   * @return Point
   */
  public abstract Point tileToScreenCoords(int x, int y);

  public void setCurrentPointerState(int pointerState) {
    this.pointerState = pointerState;
    drawResizeAnchors = pointerState == MapEditor.PS_RESIZEOBJ;
  }

  protected boolean shouldPaintBrushTile() {
    return /* MapEditor.PS_ADDOBJ == pointerState || */MapEditor.PS_PAINT == pointerState
        || MapEditor.PS_POUR == pointerState;
  }

  public void setCurrentLayer(int currentLayer) {
    this.currentLayer = currentLayer;
    if (highlightSelectedLayer)
      redraw();
  }

  public boolean isHighlightSelectedLayer() {
    return highlightSelectedLayer;
  }

  public void setHighlightSelectedLayer(boolean highlightSelectedLayer) {
    this.highlightSelectedLayer = highlightSelectedLayer;
  }

  public void repaintRegion(Rectangle redraw, Point brushSize) {
    redraw(redraw.x,redraw.y,redraw.width,redraw.height,true);
  }
 
  public Point getSnappedVector(Point vector) {
    return vector;
  }
 
  public int getSnappedScalarX(int scalar) {
    return scalar;
  }
 
  public int getSnappedScalarY(int scalar) {
    return scalar;
  }

  public Map getMap() {
    return map;
  }

  public int getCurrentLayer() {
    return currentLayer;
  }

  public boolean isDrawResizeAnchors() {
    return drawResizeAnchors;
  }

  public void setDrawResizeAnchors(boolean drawResizeAnchors) {
    this.drawResizeAnchors = drawResizeAnchors;
  }
 
  public void addSpecialLayerPainter(ISpecialLayerPainter layerPainter) {
    specialLayerPainters.add(layerPainter);
  }
 
  public void removeSpecialLayerPainter(ISpecialLayerPainter layerPainter) {
    specialLayerPainters.remove(layerPainter);
  }
}
TOP

Related Classes of tiled.view.MapView

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.