package tools.mapEditor;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import math.ADXTransform;
import org.lwjgl.input.Keyboard;
import org.newdawn.slick.Color;
import io.ADXIniParser;
import io.ADXInput;
import io.ADXTextFile;
import render.ADXGraphics;
import render.ADXSprite;
import shapes.ADXRectangle;
import frame.ADXGame;
import frame.ADXRoom;
public class ADXMapEditor extends ADXRoom {
private static final Color COLOR_GRAY_10 = new Color(0.1f, 0.1f, 0.1f, 1.0f);
private static final Color COLOR_GRAY_25 = new Color(0.25f, 0.25f, 0.25f, 1.0f);
private static final Color COLOR_GRAY_50 = new Color(0.5f, 0.5f, 0.5f, 1.0f);
private static final Color COLOR_GRAY_75 = new Color(0.75f, 0.75f, 0.75f, 1.0f);
private String optionPath;
private ArrayList<Asset> lAsset = new ArrayList<Asset>();
private ArrayList<PlacableAsset> lPAsset = new ArrayList<PlacableAsset>();
private ArrayList<Layer> lLayer = new ArrayList<Layer>();
private int selectedAsset = 0;
private int selectedLayer = 0;
private boolean drawAssets = true;
private int viewX = 0;
private int viewY = 0;
private float viewScale = 1;
private int gridXSize = 32;
private int gridYSize = 32;
private int mouseGridX = 0;
private int mouseGridY = 0;
private int mapWidth = 16;
private int mapHeight = 120;
private boolean sResize = false;
private boolean sAutoResize = false;
private String fileName = null;
public ADXMapEditor(int roomID, String optionsPath) {
super(roomID);
this.optionPath = optionsPath;
}
private class Asset {
public int code;
public String name;
public ADXSprite sprite;
public boolean canSpray;
public int maximum;
public int width;
public int height;
public Asset(int code, String name, String spritePath, boolean canSpray, int maximum) {
this.code = code;
this.name = name;
sprite = new ADXSprite(spritePath);
width = sprite.getWidth() / gridXSize;
height = sprite.getHeight() / gridYSize;
this.canSpray = canSpray;
this.maximum = maximum;
}
}
private class PlacableAsset {
Asset asset;
int x;
int y;
int layer;
public PlacableAsset(Asset asset, int x, int y, int layer) {
this.asset = asset;
this.x = x;
this.y = y;
this.layer = layer;
}
}
private class Layer {
public int code;
public String name;
public Layer(int code, String name) {
this.code = code;
this.name = name;
}
}
@Override
public void init(ADXGame game) {
// LoadĀ options
ADXIniParser ini = new ADXIniParser(optionPath);
if (ini.containsCategory("GLOBAL")) {
if (ini.containsKey("GLOBAL", "gridXSize")) {
gridXSize = ini.getIntValue("GLOBAL", "gridXSize");
}
if (ini.containsKey("GLOBAL", "gridYSize")) {
gridYSize = ini.getIntValue("GLOBAL", "gridYSize");
}
if (ini.containsKey("GLOBAL", "mapWidth")) {
mapWidth = ini.getIntValue("GLOBAL", "mapWidth");
}
if (ini.containsKey("GLOBAL", "mapHeight")) {
mapHeight = ini.getIntValue("GLOBAL", "mapHeight");
}
int assets = ini.getIntValue("GLOBAL", "assets");
String id;
for (int i = 0; i < assets; i++) {
id = "a" + i;
if (ini.containsCategory(id)) {
lAsset.add(new Asset(
ini.getIntValue(id, "id"),
ini.getValue(id, "name"),
ini.getValue(id, "path"),
ini.getIntValue(id, "canSpray") == 1,
ini.getIntValue(id, "canMultiple")
));
}
}
int layers = ini.getIntValue("GLOBAL", "layers");
for (int i = 0; i < layers; i++) {
id = "l" + i;
if (ini.containsCategory(id)) {
lLayer.add(new Layer(
ini.getIntValue(id, "id"),
ini.getValue(id, "name")
));
}
}
}
sResize = game.isResizable();
sAutoResize = game.isAutoResize();
game.setResizable(true);
game.setAutoResize(true);
viewX = -(game.getWidth() - gridXSize * mapWidth) / 2;
viewY = -(game.getHeight() - gridYSize * mapHeight) / 2;
}
@Override
public void update(ADXGame game, ADXInput input) {
// Calculate mouse grid position
mouseGridX = (int) Math.floor((input.getMouseX() + viewX * viewScale + game.getWidth() / 2 * (viewScale - 1)) / gridXSize / viewScale);
mouseGridY = (int) Math.floor((input.getMouseY() + viewY * viewScale + game.getHeight() / 2 * (viewScale - 1)) / gridYSize / viewScale);
// Select assets
if (input.getKeyPressed(Keyboard.KEY_TAB)) {
drawAssets = !drawAssets;
}
if (input.getButton(ADXInput.MOUSE_LEFT)) {
if (drawAssets && (input.getMouseX() <= 256 || input.getMouseX() >= game.getWidth() - 256)) {
if (input.getMouseX() <= 256) {
// Assets
int index = input.getMouseY() / 48;
if (index >= 0 && index < lAsset.size()) {
selectedAsset = index;
}
} else {
// Layer
int index = input.getMouseY() / 48;
if (index >= 0 && index < lLayer.size()) {
selectedLayer = index;
}
}
input.releaseButton(ADXInput.MOUSE_LEFT);
} else {
// Place asset in editor
if (selectedAsset != -1) {
Asset asset = lAsset.get(selectedAsset);
boolean canPlace = true;
if (!asset.canSpray && !input.getButtonPressed(ADXInput.MOUSE_LEFT)) {
canPlace = false;
}
if (asset.maximum > 0) {
int total = 0;
for (PlacableAsset a : lPAsset) {
if (a.asset.code == asset.code) {
total++;
if (total >= asset.maximum) {
canPlace = false;
break;
}
}
}
}
if (canPlace) {
PlacableAsset a = new PlacableAsset(asset, mouseGridX, mouseGridY, selectedLayer);
ADXRectangle r = new ADXRectangle(mouseGridX, mouseGridY, a.asset.width, a.asset.height);
ADXRectangle r2 = new ADXRectangle(0, 0, 1, 1);
boolean place = true;
for (PlacableAsset p : lPAsset) {
r2.setX(p.x);
r2.setY(p.y);
r2.setWidth(p.asset.width);
r2.setHeight(p.asset.height);
if (r.collides(r2)) {
place = false;
break;
}
}
if (place) {
lPAsset.add(a);
}
}
}
}
}
if (input.getButton(ADXInput.MOUSE_RIGHT)) {
if (!drawAssets || input.getMouseX() > 256) {
Layer l = lLayer.get(selectedLayer);
ADXRectangle r = new ADXRectangle(mouseGridX, mouseGridY, 1, 1);
ADXRectangle r2 = new ADXRectangle(0, 0, 1, 1);
PlacableAsset p;
for (int i = lPAsset.size() - 1; i >= 0; i--) {
p = lPAsset.get(i);
if (p.layer == l.code) {
r2.setX(p.x);
r2.setY(p.y);
r2.setWidth(p.asset.width);
r2.setHeight(p.asset.height);
if (r.collides(r2)) {
lPAsset.remove(i);
}
}
}
}
}
// Zoom in and out
if (input.getMouseWheel() > 0 && viewScale < 4) {
viewScale *= 2;
}
if (input.getMouseWheel() < 0 && viewScale > 1 / 8.0f) {
viewScale /= 2;
}
// Load level
if (input.getKeyPressed(Keyboard.KEY_O) && input.getKey(Keyboard.KEY_LCONTROL)) {
loadLevel();
input.releaseKey(Keyboard.KEY_O);
}
// Save level
if (input.getKeyPressed(Keyboard.KEY_S) && input.getKey(Keyboard.KEY_LCONTROL)) {
saveLevel(input.getKey(Keyboard.KEY_LSHIFT));
input.releaseKey(Keyboard.KEY_S);
}
// Move view
int speed = 8;
if (input.getKey(Keyboard.KEY_D)) {
viewX += (int)(speed / viewScale);
}
if (input.getKey(Keyboard.KEY_A)) {
viewX -= (int)(speed / viewScale);
}
if (input.getKey(Keyboard.KEY_S)) {
viewY += (int)(speed / viewScale);
}
if (input.getKey(Keyboard.KEY_W)) {
viewY -= (int)(speed / viewScale);
}
}
@Override
public void render(ADXGame game, ADXGraphics g) {
int i;
int decalX;
int decalY;
g.drawRectangle(0, 0, game.getWidth(), game.getHeight(), COLOR_GRAY_10);
g.pushTransformation(ADXTransform.T_TRANSLATE, -viewX, -viewY);
g.pushTransformation(ADXTransform.T_SCALE_FROM, game.getWidth() / 2, game.getHeight() / 2, viewScale, viewScale);
// Draw grid
decalX = (int) Math.floor((viewX * viewScale + game.getWidth() / 2 * (viewScale - 1)) / gridXSize / viewScale);
decalY = (int) Math.floor((viewY * viewScale + game.getHeight() / 2 * (viewScale - 1)) / gridYSize / viewScale);
for (i = decalX; i < decalX + (game.getWidth() / gridXSize / viewScale) + 1; i++) {
g.drawRectangle(i * gridXSize, decalY * gridYSize, 1 / viewScale, (game.getHeight() + gridYSize) / viewScale, COLOR_GRAY_25);
}
for (i = decalY; i < decalY + (game.getHeight() / gridYSize / viewScale) + 1; i++) {
g.drawRectangle(decalX * gridXSize, i * gridYSize, (game.getWidth() + gridXSize) / viewScale, 1 / viewScale, COLOR_GRAY_25);
}
// Draw map grid
for (i = 0; i < mapWidth + 1; i++) {
g.drawRectangle(i * gridXSize, 0, 1 / viewScale, mapHeight * gridYSize, COLOR_GRAY_75);
}
for (i = 0; i < mapHeight + 1; i++) {
g.drawRectangle(0, i * gridYSize, mapWidth * gridXSize, 1 / viewScale, COLOR_GRAY_75);
}
// Draw placable assets
for (PlacableAsset a : lPAsset) {
if (a.layer == selectedLayer) {
g.drawSprite(a.asset.sprite, a.x * gridXSize, a.y * gridYSize, Color.white);
} else {
g.drawSprite(a.asset.sprite, a.x * gridXSize, a.y * gridYSize, new Color(1.0f, 1.0f, 1.0f, 0.25f));
}
}
g.drawRectangle(mouseGridX * gridXSize, mouseGridY * gridYSize, gridXSize, gridYSize, new Color(1.0f, 1.0f, 1.0f, 0.5f));
g.popTransformation();
g.popTransformation();
// Draw assets
if (drawAssets) {
g.drawRectangle(0, 0, 256, game.getHeight(), COLOR_GRAY_25);
int yPlus = 0;
int asset = 0;
for (Asset a : lAsset) {
if (asset == selectedAsset) {
g.drawRectangle(0, yPlus + 1, 256, 47, COLOR_GRAY_50);
}
g.drawRectangle(0, yPlus + 48, 256, 1, Color.black);
g.drawSprite(a.sprite, 8, yPlus + 8, Color.white);
yPlus += 48;
asset++;
}
g.drawRectangle(game.getWidth() - 256, 0, 256, game.getWidth(), COLOR_GRAY_25);
yPlus = 0;
int layer = 0;
for (i = 0; i < lLayer.size(); i++) {
if (layer == selectedLayer) {
g.drawRectangle(game.getWidth() - 256, yPlus + 1, 256, 47, COLOR_GRAY_50);
}
g.drawRectangle(game.getWidth() - 256, yPlus + 48, 256, 1, Color.black);
yPlus += 48;
layer++;
}
}
}
@Override
public void exit(ADXGame game, ADXRoom nextRoom) {
super.exit(game, nextRoom);
game.setResizable(sResize);
game.setAutoResize(sAutoResize);
}
public void loadLevel() {
JFileChooser fc = new JFileChooser();
int result = fc.showOpenDialog(null);
if (result != JFileChooser.APPROVE_OPTION) {
return;
}
fileName = fc.getSelectedFile().getAbsolutePath();
ADXTextFile file = new ADXTextFile(fileName);
String line;
String[] split;
int layer;
int index = 0;
int assetCode = 0;
Asset asset = null;
while ((line = file.readLine()) != null) {
index = 0;
split = line.split(";");
layer = Integer.parseInt(split[index++]);
while (index < split.length) {
assetCode = Integer.parseInt(split[index++]);
for (Asset a : lAsset) {
if (a.code == assetCode) {
asset = a;
break;
}
}
lPAsset.add(new PlacableAsset(asset, Integer.parseInt(split[index++]), Integer.parseInt(split[index++]), layer));
}
}
}
public void saveLevel(boolean forcePick) {
if (forcePick || fileName == null) {
JFileChooser fc = new JFileChooser();
int result = fc.showSaveDialog(null);
if (result != JFileChooser.APPROVE_OPTION) {
return;
}
fileName = fc.getSelectedFile().getAbsolutePath();
}
ADXTextFile file = new ADXTextFile(fileName);
file.clearLines();
String[] text = new String[lLayer.size()];
int i = 0;
for (Layer l : lLayer) {
text[i] = "" + l.code;
i++;
}
for (PlacableAsset a : lPAsset) {
text[a.layer] += ";" + a.asset.code + ";" + a.x + ";" + a.y;
}
for (String s : text) {
file.insertLine(s);
}
file.close();
}
}