/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.pepsoft.worldpainter.objects;
import org.pepsoft.minecraft.Entity;
import org.pepsoft.minecraft.Material;
import org.pepsoft.minecraft.TileEntity;
import javax.vecmath.Point3i;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author pepijn
*/
public class RotatedObject extends AbstractObject {
/**
* A rotated version of another object.
*
* @param object The object to rotate;
* @param steps The number of 90 degree steps to rotate clockwise. Must be
* between 0 and 3 (inclusive).
*/
public RotatedObject(WPObject object, int steps) {
if ((steps < 0) || (steps > 3)) {
throw new IllegalArgumentException(Integer.toString(steps));
}
this.object = object;
this.steps = steps;
Point3i origDim = object.getDimensions();
Map<String, Serializable> attributes = (object.getAttributes() != null) ? new HashMap<>(object.getAttributes()) : new HashMap<>();
Point3i offset = object.getOffset();
switch (steps) {
case 0:
dimensions = origDim;
break;
case 1:
dimensions = new Point3i(origDim.y, origDim.x, origDim.z);
offset = new Point3i(-(origDim.y - (-offset.y) - 1), offset.x, offset.z);
break;
case 2:
dimensions = origDim;
offset = new Point3i(-(origDim.x - (-offset.x) - 1), -(origDim.y - (-offset.y) - 1), offset.z);
break;
case 3:
dimensions = new Point3i(origDim.y, origDim.x, origDim.z);
offset = new Point3i(offset.y, -(origDim.x - (-offset.x) - 1), offset.z);
break;
default:
throw new InternalError();
}
if ((offset.x != 0) || (offset.y != 0) || (offset.z != 0)) {
attributes.put(ATTRIBUTE_OFFSET.key, offset);
} else {
attributes.remove(ATTRIBUTE_OFFSET.key);
}
if (! attributes.isEmpty()) {
this.attributes = attributes;
} else {
this.attributes = null;
}
}
@Override
public Point3i getDimensions() {
return dimensions;
}
@Override
public Material getMaterial(int x, int y, int z) {
switch (steps) {
case 0:
return object.getMaterial(x, y, z);
case 1:
return object.getMaterial(y, dimensions.x - x - 1, z).rotate(1);
case 2:
return object.getMaterial(dimensions.x - x - 1, dimensions.y - y - 1, z).rotate(2);
case 3:
return object.getMaterial(dimensions.y - y - 1, x, z).rotate(3);
default:
throw new InternalError();
}
}
@Override
public boolean getMask(int x, int y, int z) {
switch (steps) {
case 0:
return object.getMask(x, y, z);
case 1:
return object.getMask(y, dimensions.x - x - 1, z);
case 2:
return object.getMask(dimensions.x - x - 1, dimensions.y - y - 1, z);
case 3:
return object.getMask(dimensions.y - y - 1, x, z);
default:
throw new InternalError();
}
}
@Override
public List<Entity> getEntities() {
List<Entity> objectEntities = object.getEntities();
if (objectEntities != null) {
List<Entity> entities = new ArrayList<>(objectEntities.size());
for (Entity objectEntity: objectEntities) {
Entity entity = (Entity) objectEntity.clone();
if (steps != 0) {
double[] objectPos = objectEntity.getPos();
double[] pos = entity.getPos();
switch (steps) {
case 1:
pos[0] = dimensions.x - objectPos[2];
pos[2] = objectPos[0];
break;
case 2:
pos[0] = dimensions.x - objectPos[0];
pos[2] = dimensions.y - objectPos[2];
break;
case 3:
pos[0] = objectPos[2];
pos[2] = dimensions.y - objectPos[0];
break;
default:
throw new InternalError();
}
entity.setPos(pos);
}
entities.add(entity);
}
return entities;
} else {
return null;
}
}
@Override
public List<TileEntity> getTileEntities() {
if (steps == 0) {
return object.getTileEntities();
} else {
List<TileEntity> objectTileEntities = object.getTileEntities();
if (objectTileEntities != null) {
List<TileEntity> tileEntities = new ArrayList<>(objectTileEntities.size());
for (TileEntity objectTileEntity: objectTileEntities) {
TileEntity tileEntity = (TileEntity) objectTileEntity.clone();
switch (steps) {
case 1:
tileEntity.setX(dimensions.x - objectTileEntity.getZ() - 1);
tileEntity.setZ(objectTileEntity.getX());
break;
case 2:
tileEntity.setX(dimensions.x - objectTileEntity.getX() - 1);
tileEntity.setZ(dimensions.y - objectTileEntity.getZ() - 1);
break;
case 3:
tileEntity.setX(objectTileEntity.getZ());
tileEntity.setZ(dimensions.y - objectTileEntity.getX() - 1);
break;
default:
throw new InternalError();
}
tileEntities.add(tileEntity);
}
return tileEntities;
} else {
return null;
}
}
}
@Override
public String getName() {
return object.getName();
}
@Override
public void setName(String name) {
throw new UnsupportedOperationException("Not supported");
}
@Override
public Map<String, Serializable> getAttributes() {
return attributes;
}
@Override
public void setAttributes(Map<String, Serializable> attributes) {
throw new UnsupportedOperationException("Not supported");
}
@Override
public <T extends Serializable> void setAttribute(AttributeKey<T> key, T value) {
throw new UnsupportedOperationException("Not supported");
}
private final WPObject object;
private final int steps;
private final Point3i dimensions;
private final Map<String, Serializable> attributes;
private static final long serialVersionUID = 1L;
}