/*
* Copyright (C) 2006 Clam <clamisgood@gmail.com>
* Copyright (C) 2008 IsmAvatar <IsmAvatar@gmail.com>
* Copyright (C) 2008, 2009 Quadduc <quadduc@gmail.com>
*
* This file is part of LateralGM.
* LateralGM is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*/
package org.lateralgm.resources.sub;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.EnumMap;
import java.util.Random;
import org.lateralgm.file.ProjectFile;
import org.lateralgm.main.UpdateSource;
import org.lateralgm.main.UpdateSource.UpdateEvent;
import org.lateralgm.main.UpdateSource.UpdateListener;
import org.lateralgm.main.UpdateSource.UpdateTrigger;
import org.lateralgm.resources.Background;
import org.lateralgm.resources.ResourceReference;
import org.lateralgm.resources.Room;
import org.lateralgm.util.PropertyMap;
import org.lateralgm.util.PropertyMap.PropertyUpdateEvent;
import org.lateralgm.util.PropertyMap.PropertyUpdateListener;
import org.lateralgm.util.PropertyMap.PropertyValidationException;
import org.lateralgm.util.PropertyMap.PropertyValidator;
public class Tile implements Room.Piece,UpdateListener,PropertyValidator<Tile.PTile>
{
private ResourceReference<?> background = null; //kept for listening purposes
public final PropertyMap<PTile> properties;
private final ResourceReference<Room> room;
private final TilePropertyListener tpl = new TilePropertyListener();
private final UpdateTrigger updateTrigger = new UpdateTrigger();
public final UpdateSource updateSource = new UpdateSource(this,updateTrigger);
public enum PTile
{
BG_X,BG_Y,ROOM_X,ROOM_Y,WIDTH,HEIGHT,DEPTH,BACKGROUND,NAME,ID,LOCKED,COLOR,ALPHA,SCALE_X,SCALE_Y,
ROTATION,SELECTED
}
private static final EnumMap<PTile,Object> DEFS = PropertyMap.makeDefaultMap(PTile.class,0,0,0,0,
0,0,0,null,"tile",0,false,4294967295L,255,1.0,1.0,0.0,false);
/**
* Do not call this constructor unless you intend
* to handle your own tile ID. See Tile(Room r, GmFile f).
*/
public Tile(Room r)
{
room = r.reference;
properties = new PropertyMap<PTile>(PTile.class,this,DEFS);
properties.getUpdateSource(PTile.BACKGROUND).addListener(tpl);
properties.getUpdateSource(PTile.SELECTED).addListener(tpl);
properties.put(PTile.NAME, "tile_" + String.format("%08X", new Random().nextInt()));
}
public Tile(Room r, int id)
{
this(r);
properties.put(PTile.ID,id);
}
/**
* Constructs a tile for this GmFile, and determines ID via the last tile id.
* Notice that a tile initializes with no settings.
*/
public Tile(Room r, ProjectFile f)
{
this(r,++f.lastTileId);
}
protected void fireUpdate(UpdateEvent e)
{
if (e == null) e = updateTrigger.getEvent();
updateTrigger.fire(e);
Room r = room == null ? null : room.get();
if (r != null) r.tileUpdated(e);
}
@Override
public void setName(String name)
{
properties.put(PTile.NAME, name);
}
@Override
public String getName()
{
return properties.get(PTile.NAME);
}
public Point getBackgroundPosition()
{
int x = properties.get(PTile.BG_X);
int y = properties.get(PTile.BG_Y);
return new Point(x,y);
}
public void setBackgroundPosition(Point p)
{
properties.put(PTile.BG_X,p.x);
properties.put(PTile.BG_Y,p.y);
fireUpdate(null);
}
public double getRotation()
{
return properties.get(PTile.ROTATION);
}
public void setRotation(double degrees)
{
properties.put(PTile.ROTATION,degrees);
}
public Point getPosition()
{
int x = properties.get(PTile.ROOM_X);
int y = properties.get(PTile.ROOM_Y);
return new Point(x,y);
}
public void setPosition(Point p)
{
properties.put(PTile.ROOM_X,p.x);
properties.put(PTile.ROOM_Y,p.y);
}
public void setColor(Color color)
{
properties.put(PTile.COLOR,color);
}
public int getAlpha()
{
return properties.get(PTile.ALPHA);
}
public void setAlpha(int alpha)
{
properties.put(PTile.ALPHA,alpha);
}
public Dimension getSize()
{
int w = properties.get(PTile.WIDTH);
int h = properties.get(PTile.HEIGHT);
return new Dimension(w,h);
}
public void setSelected(boolean selected)
{
properties.put(PTile.SELECTED,selected);
}
public boolean isSelected()
{
return (Boolean) properties.get(PTile.SELECTED);
}
public void setSize(Dimension s)
{
properties.put(PTile.WIDTH,s.width);
properties.put(PTile.HEIGHT,s.height);
fireUpdate(null);
}
public void setScale(Point2D scale)
{
properties.put(PTile.SCALE_X,scale.getX());
properties.put(PTile.SCALE_Y,scale.getY());
}
public void setColor(long color)
{
properties.put(PTile.COLOR,color);
}
public Point2D getScale()
{
return new Point2D.Double((Double) properties.get(PTile.SCALE_X),
(Double) properties.get(PTile.SCALE_Y));
}
public long getColor()
{
return properties.get(PTile.COLOR);
}
public int getDepth()
{
return properties.get(PTile.DEPTH);
}
public void setDepth(int d)
{
properties.put(PTile.DEPTH,d);
}
public void updated(UpdateEvent e)
{
fireUpdate(e);
}
public boolean isLocked()
{
return properties.get(PTile.LOCKED);
}
public void setLocked(boolean l)
{
properties.put(PTile.LOCKED,l);
}
public Object validate(PTile k, Object v)
{
if (k == PTile.BACKGROUND)
{
ResourceReference<?> r = (ResourceReference<?>) v;
if (r != null)
{
Object o = r.get();
if (o == null)
r = null;
else if (!(o instanceof Background)) throw new PropertyValidationException();
}
if (background != null) background.updateSource.removeListener(this);
background = r;
if (background != null) background.updateSource.addListener(this);
}
return v;
}
private class TilePropertyListener extends PropertyUpdateListener<PTile>
{
@Override
public void updated(PropertyUpdateEvent<PTile> e)
{
if (e.key == PTile.BACKGROUND) fireUpdate(null);
if (e.key == PTile.SELECTED) fireUpdate(null);
}
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((properties == null) ? 0 : properties.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof Tile)) return false;
Tile other = (Tile) obj;
if (properties == null)
{
if (other.properties != null) return false;
}
else if (!properties.equals(other.properties)) return false;
return true;
}
}