Moved and renamed InputChecker to GamepadChecker, perhaps fixed InputChecker not working, added callbacks for ButtonDown and buttonUp to states for cleaner button 'debounce' code

This commit is contained in:
2021-11-07 08:55:06 -06:00
parent eda5fcf4c1
commit 1c51d46476
4 changed files with 138 additions and 72 deletions

View File

@@ -1,58 +0,0 @@
package org.cyberarm.container;
import android.util.Log;
import com.qualcomm.robotcore.hardware.Gamepad;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
public class InputChecker {
private Gamepad gamepad;
private HashMap<String, Byte> buttons;
private ArrayList<String> buttonList;
private byte NULL = 0,
PRESSED = 1,
RELEASED= 2;
public InputChecker(Gamepad gamepad) {
this.gamepad = gamepad;
buttons = new HashMap<>();
buttonList = new ArrayList<>();
buttonList.add("a"); buttonList.add("b"); buttonList.add("x"); buttonList.add("y");
buttonList.add("start"); buttonList.add("guide"); buttonList.add("back");
buttonList.add("left_bumper"); buttonList.add("right_bumper");
buttonList.add("left_stick_button"); buttonList.add("right_stick_button");
buttonList.add("dpad_left"); buttonList.add("dpad_right");
buttonList.add("dpad_up"); buttonList.add("dpad_down");
}
public void update() {
for (int i = 0; i < buttonList.size(); i++) {
try {
Field field = gamepad.getClass().getDeclaredField(buttonList.get(i));
if (field.getBoolean(gamepad)) {
buttons.put(buttonList.get(i), PRESSED);
} else {
if (buttons.get(buttonList.get(i)) != null && buttons.get(buttonList.get(i)) == PRESSED) {
buttons.put(buttonList.get(i), RELEASED);
}
}
} catch (NoSuchFieldException|IllegalAccessException e) {
e.printStackTrace();
}
}
}
public boolean check(String button) {
boolean state = false;
if (buttons.containsKey(button) && buttons.get(button) == RELEASED) {
Log.d("InputChecker","button \""+button+"\" has been released on \"gamepad"+gamepad.getGamepadId()+"\"");
state = true;
buttons.put(button, NULL);
}
return state;
}
}

View File

@@ -3,6 +3,7 @@ package org.cyberarm.engine.V2;
import android.util.Log;
import com.qualcomm.robotcore.eventloop.opmode.OpMode;
import com.qualcomm.robotcore.hardware.Gamepad;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -15,13 +16,15 @@ public abstract class CyberarmEngine extends OpMode {
public static CyberarmEngine instance;
//Array To Hold States
private CopyOnWriteArrayList<CyberarmState> cyberarmStates = new CopyOnWriteArrayList<>();
final private CopyOnWriteArrayList<CyberarmState> cyberarmStates = new CopyOnWriteArrayList<>();
private int activeStateIndex = 0;
private boolean isRunning;
private static String TAG = "PROGRAM.ENGINE";
private final static String TAG = "PROGRAM.ENGINE";
public boolean showStateChildrenListInTelemetry = false;
private GamepadChecker gamepadCheckerGamepad1, gamepadCheckerGamepad2;
/**
* Called when INIT button on Driver Station is pushed
* ENSURE to call super.init() if you override this method
@@ -29,6 +32,8 @@ public abstract class CyberarmEngine extends OpMode {
public void init() {
CyberarmEngine.instance = this;
isRunning = false;
gamepadCheckerGamepad1 = new GamepadChecker(this, gamepad1);
gamepadCheckerGamepad2 = new GamepadChecker(this, gamepad2);
setup();
@@ -43,12 +48,12 @@ public abstract class CyberarmEngine extends OpMode {
* Setup states for engine to use
* For example:
* <pre>
* @<code>
* {@code
* public void setup() {
* addState(new TestState());
* addState(new AnotherState(100, 500));
* }
* </code>
* }
* </pre>
*/
public abstract void setup();
@@ -102,6 +107,9 @@ public abstract class CyberarmEngine extends OpMode {
} else {
stateTelemetry(state);
}
gamepadCheckerGamepad1.update();
gamepadCheckerGamepad2.update();
}
/**
@@ -167,14 +175,11 @@ public abstract class CyberarmEngine extends OpMode {
final CyberarmState finalState = state;
// if (state.isRunning()) { return; } // Assume that we have already started running this state
new Thread(new Runnable() {
@Override
public void run() {
finalState.prestart();
finalState.start();
finalState.startTime = System.currentTimeMillis();
finalState.run();
}
new Thread(() -> {
finalState.prestart();
finalState.start();
finalState.startTime = System.currentTimeMillis();
finalState.run();
}).start();
for (CyberarmState kid : state.children) {
@@ -199,7 +204,7 @@ public abstract class CyberarmEngine extends OpMode {
* Inserts state after the query state plus an offset to ensure logical insertion
* @param query State to add state after
* @param state State to be inserted
* @return
* @return CyberarmState
*/
public CyberarmState insertState(CyberarmState query, CyberarmState state) {
int index = cyberarmStates.indexOf(query) + query.insertOffset;
@@ -213,6 +218,48 @@ public abstract class CyberarmEngine extends OpMode {
return state;
}
private void buttonDownForStates(CyberarmState state, Gamepad gamepad, String button) {
state.buttonDown(gamepad, button);
for (CyberarmState child : state.children) {
child.buttonDown(gamepad, button);
}
}
private void buttonUpForStates(CyberarmState state, Gamepad gamepad, String button) {
state.buttonUp(gamepad, button);
for (CyberarmState child : state.children) {
child.buttonUp(gamepad, button);
}
}
/**
* Called by GamepadChecker when it detects that a gamepad button has been pressed
* @param gamepad Gamepad
* @param button String
*/
protected void buttonDown(Gamepad gamepad, String button) {
try {
buttonDownForStates(cyberarmStates.get(activeStateIndex), gamepad, button);
} catch(IndexOutOfBoundsException e){
/* loop will handle this in a few milliseconds */
}
}
/**
* Called by GamepadChecker when it detects that a gamepad button has been released
* @param gamepad Gamepad
* @param button String
*/
protected void buttonUp(Gamepad gamepad, String button) {
try {
buttonUpForStates(cyberarmStates.get(activeStateIndex), gamepad, button);
} catch(IndexOutOfBoundsException e){
/* loop will handle this in a few milliseconds */
}
}
/**
* This will return false while Engine.setup() is executing, and be true after.
* @return Whether the engine main loop is running

View File

@@ -2,6 +2,8 @@ package org.cyberarm.engine.V2;
import android.util.Log;
import com.qualcomm.robotcore.hardware.Gamepad;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -65,6 +67,23 @@ public abstract class CyberarmState implements Runnable {
public void stop() {
}
/**
* Called when GamepadChecker detects that a gamepad button has been pressed
* @param gamepad Gamepad
* @param button String
*/
public void buttonDown(Gamepad gamepad, String button) {
}
/**
* Called when GamepadChecker detects that a gamepad button has been released
* @param gamepad Gamepad
* @param button String
*/
public void buttonUp(Gamepad gamepad, String button) {
}
/**
* Add a state which runs in parallel with this one
*/
@@ -139,7 +158,7 @@ public abstract class CyberarmState implements Runnable {
/**
* Set whether state has finished or not
* @param value
* @param value boolean
*/
public void setHasFinished(boolean value) {
hasFinished = value;

View File

@@ -0,0 +1,58 @@
package org.cyberarm.engine.V2;
import com.qualcomm.robotcore.hardware.Gamepad;
import java.lang.reflect.Field;
import java.util.HashMap;
public class GamepadChecker {
private final CyberarmEngine engine;
private final Gamepad gamepad;
private final HashMap<String, Boolean> buttons = new HashMap<>();
public GamepadChecker(CyberarmEngine engine, Gamepad gamepad) {
this.engine = engine;
this.gamepad = gamepad;
buttons.put("a", false);
buttons.put("b", false);
buttons.put("x", false);
buttons.put("y", false);
buttons.put("start", false);
buttons.put("guide", false);
buttons.put("back", false);
buttons.put("left_bumper", false);
buttons.put("right_bumper", false);
buttons.put("left_stick_button", false);
buttons.put("right_stick_button", false);
buttons.put("dpad_left", false);
buttons.put("dpad_right", false);
buttons.put("dpad_up", false);
buttons.put("dpad_down", false);
}
public void update() {
for (String btn : buttons.keySet()) {
try {
Field field = gamepad.getClass().getDeclaredField(btn);
if (field.getBoolean(gamepad)) {
engine.buttonDown(gamepad, btn);
buttons.put(btn, true);
} else {
if (buttons.get(btn)) {
engine.buttonUp(gamepad, btn);
}
buttons.put(btn, false);
}
} catch (NoSuchFieldException|IllegalAccessException e) {
e.printStackTrace();
}
}
}
}