package tk.amberide.ide.gui.editor.map.tool;
import tk.amberide.engine.data.map.Direction;
import tk.amberide.engine.data.map.Layer;
import tk.amberide.engine.data.map.Tile;
import static tk.amberide.engine.data.map.Angle.*;
import tk.amberide.engine.data.map.TileModel;
import tk.amberide.engine.data.math.Angles;
import tk.amberide.ide.data.res.Tileset;
import tk.amberide.engine.gl.camera.EulerCamera;
import tk.amberide.engine.gl.tess.ITesselator;
import tk.amberide.engine.gl.tess.ImmediateTesselator;
import tk.amberide.ide.gui.editor.map.MapContext;
import java.awt.Component;
import static org.lwjgl.opengl.GL11.*;
import static tk.amberide.engine.input.AbstractKeyboard.*;
import org.lwjgl.util.vector.Vector2f;
import tk.amberide.engine.data.map.Angle;
import tk.amberide.engine.data.map.TileType;
/**
* @author Tudor
*/
public class BrushTool extends AbstractTool {
protected EulerCamera camera;
protected Angle angle = HORIZONTAL;
protected ITesselator tess = new ImmediateTesselator();
public BrushTool(MapContext context, EulerCamera camera) {
super(context);
this.camera = camera;
}
@Override
public void doScroll(int delta) {
if (delta >= 1) {
angle = angle == SLANTED ? HORIZONTAL : (angle == VERTICAL ? SLANTED : angle);
} else if (delta <= -1) {
angle = angle == SLANTED ? VERTICAL : (angle == HORIZONTAL ? SLANTED : angle);
}
}
public boolean apply(int x, int y, int z) {
boolean modified = false;
switch (context.drawType) {
case MapContext.TYPE_TILE:
if (context.tileSelection != null) {
Tileset.TileSprite[][] sel = context.tileSelection.clone();
int w = sel.length;
int h = sel[0].length;
for (int sx = 0; sx != w; sx++) {
for (int sy = 0; sy != h; sy++) {
boolean tiled = setAngledTile(x, y, z, sx, sy, h, w, camera.getFacingDirection(), angle, sel);
if (!modified) {
modified = tiled;
}
}
}
}
break;
case MapContext.EXT_TYPE_MODEL:
if (context.EXT_modelSelection != null) {
Layer l = context.map.getLayer(context.layer);
if (l instanceof Layer) {
Layer l3d = (Layer) l;
if (isInBounds(x, y)) {
TileModel p = l3d.getModel(x, y, z);
if (p == null || p.getModel() != context.EXT_modelSelection) {
l3d.setModel(x, y, z, new TileModel(context.EXT_modelSelection));
modified = true;
}
}
}
}
break;
}
return modified;
}
protected final boolean setAngledTile(int x, int y, int z, int sx, int sy, int h, int w, Direction dir, Angle angle, Tileset.TileSprite[][] sel) {
// It works, that's all you need to know.
switch (angle) {
case HORIZONTAL:
switch (dir.toCardinal()) {
case NORTH:
return setTile(x + sy, y + sx, z, sel[sx][h - sy - 1], dir, angle);
case EAST:
return setTile(sx + x - w + 1, sy + y, z, sel[w - sx - 1][h - sy - 1], dir, angle);
case SOUTH:
return setTile(x + sy - h + 1, y + sx - w + 1, z, sel[w - sx - 1][sy], dir, angle);
case WEST:
return setTile(sx + x, sy + y - h + 1, z, sel[sx][sy], dir, angle);
}
case VERTICAL:
switch (dir.toCardinal()) {
case NORTH:
return setTile(x, y + sx, z + sy, sel[sx][h - sy - 1], dir, angle);
case EAST:
return setTile(sx + x - w + 1, y, z + sy, sel[w - sx - 1][h - sy - 1], dir, angle);
case SOUTH:
return setTile(x, y + sx - w + 1, z + sy, sel[w - sx - 1][h - sy - 1], dir, angle);
case WEST:
return setTile(sx + x, y, z + sy, sel[sx][h - sy - 1], dir, angle);
}
case SLANTED:
switch (dir.toCardinal()) {
case NORTH:
return setTile(x + sy, y + sx, z + sy, sel[sx][h - sy - 1], dir, angle);
case EAST:
return setTile(sx + x - w + 1, sy + y, z + sy, sel[w - sx - 1][h - sy - 1], dir, angle);
case SOUTH:
return setTile(x - sy, y + sx - w + 1, z + sy, sel[w - sx - 1][h - sy - 1], dir, angle);
case WEST:
return setTile(sx + x, y - sy, z + sy, sel[sx][h - sy - 1], dir, angle);
}
}
return false;
}
protected boolean setTile(int x, int y, int z, Tileset.TileSprite tile, Direction dir, Angle angle) {
Layer lay = context.map.getLayer(context.layer);
boolean modified = false;
if (isInBounds(x, y)) {
Tile r = lay.getTile(x, y, z);
if (tile != null) {
modified = r == null || !tile.equals(r.getSprite());
TileType type;
if (isKeyDown(KEY_Z) && !isKeyDown(KEY_X)) {
type = TileType.TILE_CORNER;
} else if (isKeyDown(KEY_X) && !isKeyDown(KEY_Z)) {
type = TileType.TILE_CORNER_INVERSED;
} else {
type = TileType.TILE_NORMAL;
}
lay.setTile(x, y, z, new Tile(tile, dir, angle, type));
} else {
modified = r != null;
lay.setTile(x, y, z, null);
}
}
return modified;
}
public void draw(int x, int y, int z) {
if (context.drawType == MapContext.EXT_TYPE_MODEL && context.EXT_modelSelection != null) {
glPushAttrib(GL_CURRENT_BIT | GL_POLYGON_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
tess.drawModel(new TileModel(context.EXT_modelSelection), x, z, y);
glPopAttrib();
} else if (context.tileSelection != null) {
glPushMatrix();
float tx = x, tz = z, rot = 0;
switch (camera.getFacingDirection().toCardinal()) {
case SOUTH:
tx+=1;
tz+=1;
rot = 180;
break;
case WEST:
tz+=1;
rot = 90;
break;
case EAST:
tx+=1;
rot = 270;
break;
}
glTranslatef(tx, (float) y, tz);
float y1, y2, y3, y4;
y1 = y2 = y3 = y4 = 0;
Vector2f ix;
Direction dir = camera.getFacingDirection();
if (isKeyDown(KEY_Z) && !isKeyDown(KEY_X) && !dir.cardinal()) {
switch (dir) {
case NORTH_EAST:
case SOUTH_WEST:
y3++;
break;
case NORTH_WEST:
case SOUTH_EAST:
y2++;
break;
}
ix = Angles.circleIntercept(HORIZONTAL.intValue(), 0, 0, context.tileSelection[0].length);
} else if (isKeyDown(KEY_X) && !isKeyDown(KEY_Z) && !dir.cardinal()) {
switch (dir) {
case NORTH_EAST:
case SOUTH_WEST:
y4++;
y3++;
y2++;
break;
case NORTH_WEST:
case SOUTH_EAST:
y1++;
y2++;
y3++;
break;
}
ix = Angles.circleIntercept(HORIZONTAL.intValue(), 0, 0, context.tileSelection[0].length);
} else {
ix = Angles.circleIntercept(angle.intValue(), 0, 0, context.tileSelection[0].length);
}
glRotatef(rot, 0, 1, 0);
glBegin(GL_LINE_LOOP);
{
int w = context.tileSelection.length;
glVertex3f(0, 0 + y1, 0);
glVertex3f(ix.x, ix.y + y2, 0);
glVertex3f(ix.x, ix.y + y3, w);
glVertex3f(0, 0 + y4, w);
}
glEnd();
glPopMatrix();
}
}
public Component getContextComponent() {
return null;
}
}