package com.pointcliki.dizgruntled;
import org.json.JSONException;
import org.json.JSONObject;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Vector2f;
import com.pointcliki.core.PointClikiGame;
import com.pointcliki.core.ISavable;
import com.pointcliki.dizgruntled.editor.EditorScene;
import com.pointcliki.dizgruntled.map.Map;
import com.pointcliki.dizgruntled.map.MapManager;
import com.pointcliki.dizgruntled.rez.MonolithWWD;
import com.pointcliki.input.MouseEvent;
import com.pointcliki.ui.UIEntity;
/**
* This interface describes an in-game logic
*
* @author Hugheth
* @since alpha 2.5
*/
public abstract class Logic extends UIEntity implements ISavable {
/**
* Serial key
*/
private static final long serialVersionUID = -6041735096435980806L;
protected Vector2f fStart;
protected int fFixed = 0;
protected boolean fSelected;
protected boolean fSnapToGrid = false;
protected Map fMap;
protected LogicProperty[] fProperties;
/**
* Import the logic from a WWD file
* @param logic The type of logic i.e. EyeCandy
* @param file The image file i.e. GAME/IMAGEZ/WAPWORLDONLY/TRIGGER
* @param animation The optional animation file i.e. GAME/ANIZ/WATER1.ANI, null otherwise
* @param data The byte data following these, containing e.g. smarts, health, rects
*/
public void importFromWWD(String logic, String image, String animation, byte[] data) {
Vector2f pos = MonolithWWD.readPosition(data);
if (fSnapToGrid) position(new Vector2f((int) Math.round((pos.x - 16f) / 32f) * 32f + 16f, (int) Math.round((pos.y - 16f) / 32f) * 32f + 16f));
else position(pos);
order((int) position().y);
}
/**
* Export the logic to WWD logic format
* @return The array of bytes to export, starting with the logic string, then file and animation if there is one, followed by the remaining logic data
*/
public abstract byte[] exportToWWD();
/**
* Import from JSON
* @param object The JSON serialization of the logic
*/
public void importFromJSON(JSONObject object) {
String[] str = object.optString("xy").split(" ");
Vector2f pos = new Vector2f(Float.valueOf(str[0]), Float.valueOf(str[1]));
if (fSnapToGrid) position(new Vector2f((int) Math.round((pos.x - 16f) / 32f) * 32f + 16f, (int) Math.round((pos.y - 16f) / 32f) * 32f + 16f));
else position(pos);
order((int) position().y);
}
/**
* Export to JSON
* @return THe JSON serialization of the logic
* @throws JSONException
*/
public JSONObject exportToJSON() throws JSONException {
JSONObject obj = new JSONObject();
obj.put("logic", name());
obj.put("xy", (int)Math.floor(fPosition.x) + " " + (int)Math.floor(fPosition.y));
return obj;
}
/**
* Initialize the logic once it has been added to a scene
*/
public void init(Map map) {
fMap = map;
initProperties();
if (!map().editing()) disable();
}
/**
* Initialize the logic properties
*/
public abstract void initProperties();
public void select() {
fMap.selectLogic(this);
fSelected = true;
if (map().editing()) {
editorScene().setEditingLogic(this);
}
}
/**
* De-select the logic
*/
public void deselect() {
fSelected = false;
if (map().editing()) editorScene().setEditingLogic(null);
}
@Override
public void cleanup() {
map().unregisterLogic(this);
super.cleanup();
}
@Override
public void render(Graphics graphics, long currentTime) {
super.render(graphics, currentTime);
if (fMap.editing() && fOpacity > 0.5f && (fHovering || fSelected)) {
if (fCapturing) graphics.setColor(Color.white);
else if (fSelected) graphics.setColor(Color.green);
else graphics.setColor(Color.cyan);
graphics.drawRect(fSpan.getX(), fSpan.getY(), fSpan.getWidth(), fSpan.getHeight());
graphics.drawRect(fSpan.getX() - 2, fSpan.getY() - 2, fSpan.getWidth() + 4, fSpan.getHeight() + 4);
}
}
@Override
public void order(int o) {
if (fFixed == 0) super.order(o);
else fOrder = fFixed;
}
@Override
public void handleUIMouseEvent(String type, Vector2f local, MouseEvent event) {
if (fOpacity < 0.5f) return;
fDispatcher.dispatchEvent(type, event);
if (type.equals("mouse.down")) {
fStart = local;
if (fEnabled) select();
}
if (!fMap.editing()) return;
if (type.equals("mouse.drag")) {
Vector2f change = local.sub(fStart);
if (fSnapToGrid)
change = new Vector2f((int) Math.round(change.x / 32f) * 32f, (int) Math.round(change.y / 32f) * 32f);
position(position().add(change));
order((int) position().y);
}
}
@Override
public boolean capturePoint(String type, Vector2f v, MouseEvent event) {
if (fMap.editing() && fSelected && PointClikiGame.inputManager().isCtrlPressed() && type.equals("mouse.down") && event.button() == 0) return true;
if (event.button() == 1) return false;
return super.capturePoint(type, v, event);
}
public boolean selected() {
return fSelected;
}
public LevelScene levelScene() {
return scene(LevelScene.class);
}
public EditorScene editorScene() {
return scene(EditorScene.class);
}
public EffectManager effectManager() {
return manager(EffectManager.class);
}
public PressureManager pressureManager() {
return manager(PressureManager.class);
}
public MapManager mapManager() {
return manager(MapManager.class);
}
public Map map() {
return fMap;
}
public abstract String name();
@Override
public boolean greedyCapture(String type, Vector2f v, MouseEvent event) {
return (fMap.editing() && !PointClikiGame.inputManager().isCtrlPressed());
}
public LogicProperty[] properties() {
return fProperties;
}
}