Package ch.fusun.baron.swt.isometry.components

Source Code of ch.fusun.baron.swt.isometry.components.IsometryWidget

package ch.fusun.baron.swt.isometry.components;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
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.widgets.Composite;

import ch.fusun.baron.swt.isometry.SpriteSelectionListener;

/**
* Widget to display sprites in an isometric world
*/
public class IsometryWidget extends Composite {

  private int mapWidth;
  private int mapHeight;
  private int mapAltitude;

  Map<String, Image> map = new HashMap<String, Image>();
  Map<Point3D, List<Sprite>> spriteMap = new HashMap<Point3D, List<Sprite>>();
  Sprite selectedSprite;
  private final int spriteHeight;
  private final int spriteWidth;
  private final int spriteAltitude;
  private int deltaX;
  private int deltaY;
  private final Map<Sprite, Object> modelMap = new HashMap<Sprite, Object>();
  private final List<SpriteSelectionListener> selectionListeners = new LinkedList<SpriteSelectionListener>();
  private IsometricRotation rotation = IsometricRotation.ROTATION_0;

  /**
   * Constructor
   *
   * @param parent
   *            The parent composite
   * @param style
   *            The SWT style
   * @param width
   *            The width (x)
   * @param height
   *            The height (y)
   * @param altitude
   *            The altitude (z)
   * @param spriteWidth
   *            The sprite width
   * @param spriteHeight
   *            The sprite height
   * @param spriteAltitude
   *            The sprite altitude
   */
  public IsometryWidget(Composite parent, int style, final int width,
      final int height, final int altitude, final int spriteWidth,
      final int spriteHeight, final int spriteAltitude) {
    super(parent, SWT.NO_BACKGROUND);

    this.spriteWidth = spriteWidth;
    this.spriteHeight = spriteHeight;
    this.spriteAltitude = spriteAltitude;

    setDimension(width, height, altitude);

    this.addMouseListener(new MouseListener() {

      @Override
      public void mouseDoubleClick(MouseEvent e) {
        // Do nothing on double click
      }

      @Override
      public void mouseDown(MouseEvent e) {
        int x = e.x;
        int y = e.y;
        selectedSprite = null;
        Point3D size = new Point3D(mapWidth - 1, mapHeight - 1,
            mapAltitude - 1); // The -1 is important
        for (Entry<Point3D, List<Sprite>> entry : spriteMap.entrySet()) {
          Point3D point = rotation.transform(entry.getKey(), size);
          for (Sprite sprite : entry.getValue()) {
            if (sprite.getMask() != null) {
              int width = spriteWidth;
              int height = spriteHeight;
              int adjustedX = -calcX(point.x(), point.y()) + x;
              int adjustedY = -calcY(point.x(), point.y(),
                  point.z())
                  + y;
              if ((adjustedX < width) && (adjustedX > 0)
                  && (adjustedY < height) && (adjustedY > 0)) {
                if (sprite.isSensitive(adjustedX, adjustedY)) {
                  if (selectedSprite == null) {
                    selectedSprite = sprite;
                  } else if (moreInForeground(sprite,
                      selectedSprite)) {
                    selectedSprite = sprite;
                  }
                }
              }
            }
          }
        }
        notifySelectionListeners();
        redraw();
      }

      @Override
      public void mouseUp(MouseEvent e) {
        // Do nothing
      }
    });
    this.addPaintListener(new PaintListener() {
      @Override
      public void paintControl(PaintEvent event) {
        Image image = new Image(getDisplay(), getClientArea());
        GC gc = new GC(image);
        gc.setBackground(new Color(getDisplay(), 0, 0, 0));
        gc.fillRectangle(0, 0, image.getBounds().width,
            image.getBounds().height);
        Point3D size = new Point3D(mapWidth - 1, mapHeight - 1,
            mapAltitude - 1); // The -1 is important :)
        for (int k = 0; k < mapAltitude; k++) {
          for (int i = 0; i < mapWidth; i++) {
            for (int j = 0; j < mapHeight; j++) {
              Point3D point = rotation.getInverse().transform(
                  new Point3D(i, j, k), size);
              if (spriteMap.get(point) != null) {
                for (Sprite sprite : spriteMap.get(point)) {
                  gc.drawImage(rotation.getImage(sprite),
                      calcX(i, j), calcY(i, j, k));
                  if (selectedSprite == sprite) {
                    gc.drawImage(
                        sprite.getHalfTransparentMask(),
                        calcX(i, j), calcY(i, j, k));
                  }
                }
              }
            }
          }
        }
        event.gc.drawImage(image, 0, 0);
        gc.dispose();
        image.dispose();
      }

    });
  }

  /**
   * @param newSprite
   *            The sprite
   * @param original
   *            The original
   * @return is the new sprite in front of the original?
   */
  protected boolean moreInForeground(Sprite newSprite, Sprite original) {
    Point3D pos1 = getPosition(original);
    Point3D pos2 = getPosition(newSprite);
    return (pos1.x() < pos2.x()) || (pos1.y() < pos2.y())
        || original.getPriority() < newSprite.getPriority();
  }

  private Point3D getPosition(Sprite sprite) {
    for (Point3D point : spriteMap.keySet()) {
      for (Sprite element : spriteMap.get(point)) {
        if (element == sprite) {
          return point;
        }
      }
    }
    return new Point3D(0, 0, 0);
  }

  /**
   * Notifies selection listeners on a new selection
   */
  protected void notifySelectionListeners() {
    if (selectedSprite != null) {
      for (SpriteSelectionListener listener : selectionListeners) {
        listener.itemSelected(getSelection());
      }
    }
  }

  /**
   * Calculates real x from i and j in model space
   *
   * @param i
   * @param j
   * @return The calculated position
   */
  protected int calcX(int i, int j) {
    return (i - j) * spriteWidth / 2 + deltaX;
  }

  /**
   * Calculates real y from i and j in model space
   *
   * @param i
   * @param j
   * @return The calculated position
   */
  protected int calcY(int i, int j, int k) {
    return spriteHeight / 2 + (j + i) * spriteHeight / 4 + deltaY
        - spriteAltitude * k;
  }

  /**
   * @param model
   *            The model representing the sprite
   * @param x
   *            The x position of the sprite
   * @param y
   *            The y position of the sprite
   * @param sprite
   */
  public void addItem(Object model, int x, int y, Sprite sprite) {
    addItem(model, x, y, 0, sprite);
  }

  /**
   *
   * @param model
   * @param x
   * @param y
   * @param z
   *            height
   * @param sprite
   */
  public void addItem(Object model, int x, int y, int z, Sprite sprite) {
    Point3D point = new Point3D(x, y, z);
    if (spriteMap.get(point) == null) {
      spriteMap.put(point, new LinkedList<Sprite>());
    }
    spriteMap.get(point).add(sprite);
    modelMap.put(sprite, model);
    Collections.sort(spriteMap.get(point), new Comparator<Sprite>() {

      @Override
      public int compare(Sprite o1, Sprite o2) {
        return o1.getPriority() - o2.getPriority();
      }
    });
  }

  /**
   * Sets the dimensions of the map
   *
   * @param width
   *            The width
   * @param height
   *            The height
   * @param altitude
   *            The altitude
   */
  public void setDimension(int width, int height, int altitude) {
    this.mapWidth = width;
    this.mapHeight = height;
    this.mapAltitude = altitude;

    deltaX = mapHeight * spriteWidth / 2;
    deltaY = spriteAltitude * mapAltitude;
  }

  /**
   * Clears all sprites from the map
   */
  public void clear() {
    this.selectedSprite = null;
    this.map.clear();
    this.spriteMap.clear();
    this.modelMap.clear();
  }

  /**
   * @param spriteSelectionListener
   *            the listener to add
   */
  public void addSelectionListener(
      SpriteSelectionListener spriteSelectionListener) {
    this.selectionListeners.add(spriteSelectionListener);
  }

  /**
   * @return The current selection
   */
  public IStructuredSelection getSelection() {
    if (selectedSprite != null) {
      if (modelMap.get(selectedSprite) != null) {
        return new StructuredSelection(modelMap.get(selectedSprite));
      }
    }
    return new StructuredSelection();
  }

  /**
   * @param selection
   *            The selection to set
   */
  public void setSelection(IStructuredSelection selection) {
    this.selectedSprite = null;
    Object model = selection.getFirstElement();
    if (model != null) {
      for (Entry<Sprite, Object> o : modelMap.entrySet()) {
        if (model.equals(o.getValue())) {
          this.selectedSprite = o.getKey();
          return;
        }
      }
    }
  }

  /**
   * Turns the map clockwise
   */
  public void turn() {
    this.rotation = this.rotation.clockWise();
    redraw();
  }

  /**
   * Turns the map counterclockwise
   */
  public void turnCounterClockWise() {
    this.rotation = this.rotation.counterClockWise();
    redraw();
  }
}
TOP

Related Classes of ch.fusun.baron.swt.isometry.components.IsometryWidget

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.