/*
* Copyright (c) 2014 tabletoptool.com team.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* rptools.com team - initial implementation
* tabletoptool.com team - further development
*/
package com.t3.model;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.math.NumberUtils;
import com.t3.guid.GUID;
import com.t3.guid.UniquelyIdentifiable;
import com.t3.model.grid.Grid;
import com.t3.persistence.FileUtil;
import com.t3.xstreamversioned.version.SerializationVersion;
@SerializationVersion(0)
public class LightSource implements Comparable<LightSource>, UniquelyIdentifiable {
@SerializationVersion(0)
public enum Type {
NORMAL,
AURA
}
private List<Light> lightList;
private String name;
private GUID id;
private Type type;
private ShapeType shapeType;
public LightSource() {
// for serialization
}
public LightSource(String name) {
id = new GUID();
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof LightSource)) {
return false;
}
return ((LightSource) obj).id.equals(id);
}
public double getMaxRange() {
double range = 0;
for (Light light : getLightList()) {
range = Math.max(range, light.getRadius());
}
return range;
}
@Override
public int hashCode() {
return id.hashCode();
}
public void setId(GUID id) {
this.id = id;
}
@Override
public GUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void add(Light source) {
getLightList().add(source);
}
public void remove(Light source) {
getLightList().remove(source);
}
public List<Light> getLightList() {
if (lightList == null) {
lightList = new LinkedList<Light>();
}
return lightList;
}
public Type getType() {
return type != null ? type : Type.NORMAL;
}
public void setType(Type type) {
this.type = type;
}
public void setShapeType(ShapeType type) {
this.shapeType = type;
}
public ShapeType getShapeType() {
return shapeType != null ? shapeType : ShapeType.CIRCLE;
}
/**
* Area for a single light, subtracting any previous lights
*/
public Area getArea(Token token, Zone zone, Direction position, Light light) {
Area area = light.getArea(token, zone);
// TODO: This seems horribly inefficient
// Subtract out the lights that are previously defined
for (int i = getLightList().indexOf(light) - 1; i >= 0; i--) {
Light lessLight = getLightList().get(i);
area.subtract(getArea(token, zone, position, lessLight.getArea(token, zone)));
}
return getArea(token, zone, position, area);
}
/**
* Area for all lights combined
*/
public Area getArea(Token token, Zone zone, Direction position) {
Area area = new Area();
for (Light light : getLightList()) {
area.add(light.getArea(token, zone));
}
return getArea(token, zone, position, area);
}
private Area getArea(Token token, Zone zone, Direction position, Area area) {
Grid grid = zone.getGrid();
Rectangle footprintBounds = token.getFootprint(grid).getBounds(grid, grid.convert(new ZonePoint(token.getX(), token.getY())));
int tx = 0;
int ty = 0;
switch (position) {
case NW:
tx -= footprintBounds.width / 2;
ty -= footprintBounds.height / 2;
break;
case N:
ty -= footprintBounds.height / 2;
break;
case NE:
tx += footprintBounds.width / 2;
ty -= footprintBounds.height / 2;
break;
case W:
tx -= footprintBounds.width / 2;
break;
case CENTER:
break;
case E:
tx += footprintBounds.width / 2;
break;
case SW:
tx -= footprintBounds.width / 2;
ty += footprintBounds.height / 2;
break;
case S:
ty += footprintBounds.height / 2;
break;
case SE:
tx += footprintBounds.width / 2;
ty += footprintBounds.height / 2;
break;
}
area.transform(AffineTransform.getTranslateInstance(tx, ty));
return area;
}
public void render(Graphics2D g, Token token, Grid grid) {
}
@SuppressWarnings("unchecked")
public static Map<String, List<LightSource>> getDefaultLightSources() {
Object defaultLights = FileUtil.objFromResource(LightSource.class,"defaultLightSourcesMap.xml");
return (Map<String, List<LightSource>>) defaultLights;
}
@Override
public String toString() {
return name;
}
private Object readResolve() {
if (type == null) {
type = Type.NORMAL;
}
return this;
}
/*
* (non-Javadoc)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(LightSource o) {
if (o != this) {
Integer nameLong = NumberUtils.toInt(name, Integer.MIN_VALUE);
Integer onameLong = NumberUtils.toInt(o.name, Integer.MIN_VALUE);
if (nameLong != Integer.MIN_VALUE && onameLong != Integer.MIN_VALUE)
return nameLong - onameLong;
return name.compareTo(o.name);
}
return 0;
}
}