package com.nilunder.bdx.inputs;
import java.util.*;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.nilunder.bdx.*;
public class InputMaps extends HashMap<String, InputMaps.Inputs> {
public static class Input{
public boolean forceHit;
public boolean forceDown;
public boolean forceUp;
public String[] parsedDescriptor;
public static class FnHDU{
public FnBool[] eval(String d1){
return null;
}
}
public static class FnBool{
public boolean eval(){
return false;
}
}
public FnBool[] hdu;
public Input(){
hdu = new FnBool[3];
}
public Input(String descriptor){
this();
final String[] d = descriptor.split(":");
parsedDescriptor = d;
if (d[0].contains("g") && d[0].length() == 1) // There's not a gamepad id number, so add in "0" for the first
parsedDescriptor = new String[]{d[0] + "0", d[1]};
if (d[0].equals("k")){
hdu[0] = new FnBool(){
public boolean eval(){
boolean r = Bdx.keyboard.keyHit(d[1]) || forceHit;
forceHit = false;
return r;
}
};
hdu[1] = new FnBool(){
public boolean eval(){
boolean r = Bdx.keyboard.keyDown(d[1]) || forceDown;
forceDown = false;
return r;
}
};
hdu[2] = new FnBool(){
public boolean eval(){
boolean r = Bdx.keyboard.keyUp(d[1]) || forceUp;
forceUp = false;
return r;
}
};
}else if (d[0].equals("m")){
hdu[0] = new FnBool(){
public boolean eval(){
boolean r = Bdx.mouse.btnHit(d[1]) || forceHit;
forceHit = false;
return r;
}
};
hdu[1] = new FnBool(){
public boolean eval(){
boolean r = Bdx.mouse.btnDown(d[1]) || forceDown;
forceDown = false;
return r;
}
};
hdu[2] = new FnBool(){
public boolean eval(){
boolean r = Bdx.mouse.btnUp(d[1]) || forceUp;
forceUp = false;
return r;
}
};
}else if (d[0].contains("g")){
final int gpIndex;
// GWT doesn't implement Character.getNumericValue(), so do this instead
gpIndex = Integer.parseInt("" + parsedDescriptor[0].charAt(1), 36);
hdu[0] = new FnBool(){
public boolean eval(){
if (Bdx.gamepads.size() > gpIndex) {
boolean r = Bdx.gamepads.get(gpIndex).btnHit(d[1]) || forceHit;
forceHit = false;
return r;
}
return false;
}
};
hdu[1] = new FnBool(){
public boolean eval(){
if (Bdx.gamepads.size() > gpIndex) {
boolean r = Bdx.gamepads.get(gpIndex).btnDown(d[1]) || forceDown;
forceDown = false;
return r;
}
return false;
}
};
hdu[2] = new FnBool(){
public boolean eval(){
if (Bdx.gamepads.size() > gpIndex) {
boolean r = Bdx.gamepads.get(gpIndex).btnUp(d[1]) || forceUp;
forceUp = false;
return r;
}
return false;
}
};
}else if (customDescriptorsHDU.containsKey(d[0])){
hdu = customDescriptorsHDU.get(d[0]).eval(d[1]);
}else{
throw new RuntimeException("Invalid descriptor \"" + descriptor + "\".");
}
}
}
public static class Inputs extends ArrayList<Input>{
public boolean status(int fnIdx){
for (Input input : this){
if (input.hdu[fnIdx].eval())
return true;
}
return false;
}
public void forceInput(int inputType){
for (Input input : this){
if (inputType == 0)
input.forceHit = true;
else if (inputType == 1)
input.forceDown = true;
else if (inputType == 2)
input.forceUp = true;
}
}
}
public static class Logger extends HashMap<String, Array<String>> {
public int currentFrame;
public int maxFrame;
public void record(){
Array<String> recordedInputs = new Array<String>();
for (String input : Bdx.imaps.keySet()){
if (Bdx.imaps.hit(input))
recordedInputs.add(input + "_hit");
if (Bdx.imaps.down(input))
recordedInputs.add(input + "_down");
if (Bdx.imaps.up(input))
recordedInputs.add(input + "_up");
}
if (recordedInputs.size > 0) {
if (currentFrame < maxFrame)
put(Integer.toString(currentFrame), recordedInputs);
else
put(Integer.toString(currentFrame + 1), recordedInputs);
}
currentFrame++;
maxFrame = Math.max(maxFrame, currentFrame);
}
public void clear(){
super.clear();
currentFrame = 0;
maxFrame = 0;
}
public void play(){
Array<String> recData = this.get(Integer.toString(currentFrame));
if (!atLastFrame()) {
if (recData != null) {
for (String input : recData) {
if (input.substring(0, input.lastIndexOf("_")).equals(""))
continue;
if (input.contains("_hit"))
Bdx.imaps.forceHit(input.substring(0, input.indexOf("_hit")));
if (input.contains("_down"))
Bdx.imaps.forceDown(input.substring(0, input.indexOf("_down")));
if (input.contains("_up"))
Bdx.imaps.forceUp(input.substring(0, input.indexOf("_up")));
}
}
currentFrame++;
}
}
public boolean atLastFrame(){
return currentFrame >= maxFrame;
}
public void save(String filePath){
Json json = new Json();
json.toJson(this, Gdx.files.external(filePath));
}
public void load(String filePath) {
Json json = new Json();
Logger l = json.fromJson(Logger.class, Gdx.files.external(filePath));
ArrayList<Integer> values = new ArrayList<Integer>();
for (String k : l.keySet()) {
values.add(Integer.valueOf(k));
}
Collections.sort(values);
l.maxFrame = values.get(values.size() - 1);
Bdx.imaps.logger = l;
}
public void remap(String inputName, String newInputName) {
for (Array<String> keys : this.values()) {
for (String k : new Array<String>(keys)) {
keys.removeValue(k, true);
String n = k.replace(inputName, newInputName);
keys.add(n);
}
}
}
}
public static Logger logger;
public static HashMap<String, Input.FnHDU> customDescriptorsHDU;
public InputMaps(){
logger = new Logger();
customDescriptorsHDU = new HashMap<String, Input.FnHDU>();
}
public void put(String name, String... descriptors){
Inputs ic = new Inputs();
for (String d : descriptors){
ic.add(new Input(d));
}
put(name, ic);
}
public boolean hit(String name){
return get(name).status(0);
}
public boolean down(String name){
return get(name).status(1);
}
public boolean up(String name){
return get(name).status(2);
}
public int iHit(String name){
return hit(name)?1:0;
}
public int iDown(String name){
return down(name)?1:0;
}
public int iUp(String name){
return up(name)?1:0;
}
public void forceHit(String name){
get(name).forceInput(0);
}
public void forceDown(String name){
get(name).forceInput(1);
}
public void forceUp(String name){
get(name).forceInput(2);
}
}