v1.3.0: added a separate bindings window for controller

This commit is contained in:
Evan Debenham
2022-06-03 12:33:17 -04:00
parent 833237eab8
commit 8653439a4f
6 changed files with 247 additions and 33 deletions

View File

@@ -164,10 +164,11 @@ public class ControllerHandler implements ControllerListener {
if (btnCode == mapping.buttonR1) return Input.Keys.BUTTON_R1;
if (btnCode == mapping.buttonR2) return Input.Keys.BUTTON_R2;
if (btnCode == mapping.buttonDpadUp) return Input.Keys.DPAD_UP;
if (btnCode == mapping.buttonDpadLeft) return Input.Keys.DPAD_LEFT;
if (btnCode == mapping.buttonDpadDown) return Input.Keys.DPAD_DOWN;
if (btnCode == mapping.buttonDpadRight) return Input.Keys.DPAD_RIGHT;
//we add 1000 here to make these keys distinct from Keys.UP, Keys.DOWN, etc..
if (btnCode == mapping.buttonDpadUp) return Input.Keys.DPAD_UP + 1000;
if (btnCode == mapping.buttonDpadDown) return Input.Keys.DPAD_DOWN + 1000;
if (btnCode == mapping.buttonDpadLeft) return Input.Keys.DPAD_LEFT + 1000;
if (btnCode == mapping.buttonDpadRight) return Input.Keys.DPAD_RIGHT + 1000;
if (btnCode == mapping.buttonLeftStick) return Input.Keys.BUTTON_THUMBL;
if (btnCode == mapping.buttonRightStick)return Input.Keys.BUTTON_THUMBR;
@@ -180,7 +181,7 @@ public class ControllerHandler implements ControllerListener {
return true;
}
else if (keyCode >= Input.Keys.DPAD_UP && keyCode <= Input.Keys.DPAD_LEFT){
if (keyCode >= Input.Keys.DPAD_UP+1000 && keyCode <= Input.Keys.DPAD_RIGHT+1000){
return true;
}
@@ -200,6 +201,16 @@ public class ControllerHandler implements ControllerListener {
}
}
if (keyCode == Input.Keys.DPAD_UP + 1000){
return Input.Keys.toString(Input.Keys.DPAD_UP);
} else if (keyCode == Input.Keys.DPAD_DOWN + 1000){
return Input.Keys.toString(Input.Keys.DPAD_DOWN);
} else if (keyCode == Input.Keys.DPAD_LEFT + 1000){
return Input.Keys.toString(Input.Keys.DPAD_LEFT);
} else if (keyCode == Input.Keys.DPAD_RIGHT + 1000){
return Input.Keys.toString(Input.Keys.DPAD_RIGHT);
}
return null;
}
}

View File

@@ -30,8 +30,12 @@ import java.util.LinkedHashMap;
// should see about doing some refactoring to clean this up
public class KeyBindings {
//for keyboard keys
private static LinkedHashMap<Integer, GameAction> bindings = new LinkedHashMap<>();
//for controller buttons
private static LinkedHashMap<Integer, GameAction> controllerBindings = new LinkedHashMap<>();
public static LinkedHashMap<Integer, GameAction> getAllBindings(){
return new LinkedHashMap<>(bindings);
}
@@ -40,6 +44,14 @@ public class KeyBindings {
bindings = new LinkedHashMap<>(newBindings);
}
public static LinkedHashMap<Integer, GameAction> getAllControllerBindings(){
return new LinkedHashMap<>(controllerBindings);
}
public static void setAllControllerBindings(LinkedHashMap<Integer, GameAction> newBindings){
controllerBindings = new LinkedHashMap<>(newBindings);
}
//these are special keybinding that are not user-configurable
private static LinkedHashMap<Integer, GameAction> hardBindings = new LinkedHashMap<>();
@@ -53,12 +65,17 @@ public class KeyBindings {
if (keyCode < 0 || (keyCode > 255 && keyCode < 1000)){
return false;
}
return bindingKey || bindings.containsKey( keyCode ) || hardBindings.containsKey( keyCode );
return bindingKey
|| bindings.containsKey( keyCode )
|| controllerBindings.containsKey( keyCode )
|| hardBindings.containsKey( keyCode );
}
public static GameAction getActionForKey(KeyEvent event){
if (bindings.containsKey( event.code )){
if (bindings.containsKey( event.code )) {
return bindings.get( event.code );
} else if (controllerBindings.containsKey( event.code )){
return controllerBindings.get( event.code );
} else if (hardBindings.containsKey( event.code )) {
return hardBindings.get( event.code );
}
@@ -67,11 +84,36 @@ public class KeyBindings {
public static ArrayList<Integer> getBoundKeysForAction(GameAction action){
ArrayList<Integer> result = new ArrayList<>();
for( int i : bindings.keySet()){
for( int i : bindings.keySet() ){
if (bindings.get(i) == action){
result.add(i);
}
}
for( int i : controllerBindings.keySet() ){
if (controllerBindings.get(i) == action){
result.add(i);
}
}
return result;
}
public static ArrayList<Integer> getKeyboardKeysForAction(GameAction action){
ArrayList<Integer> result = new ArrayList<>();
for( int i : bindings.keySet() ){
if (bindings.get(i) == action){
result.add(i);
}
}
return result;
}
public static ArrayList<Integer> getControllerKeysForAction(GameAction action){
ArrayList<Integer> result = new ArrayList<>();
for( int i : controllerBindings.keySet() ){
if (controllerBindings.get(i) == action){
result.add(i);
}
}
return result;
}

View File

@@ -88,7 +88,7 @@ public class Bundle {
}
public boolean contains( String key ) {
return !data.isNull( key );
return !isNull() && !data.isNull( key );
}
public boolean remove( String key ){

View File

@@ -22,6 +22,7 @@
package com.shatteredpixel.shatteredpixeldungeon;
import com.badlogic.gdx.Input;
import com.watabou.input.ControllerHandler;
import com.watabou.input.GameAction;
import com.watabou.input.KeyBindings;
import com.watabou.utils.Bundle;
@@ -88,12 +89,6 @@ public class SPDAction extends GameAction {
static {
defaultBindings.put( Input.Keys.ESCAPE, SPDAction.BACK );
defaultBindings.put( Input.Keys.BACKSPACE, SPDAction.BACK );
defaultBindings.put( Input.Keys.BUTTON_START, SPDAction.BACK );
defaultBindings.put( Input.Keys.BUTTON_R2, SPDAction.LEFT_CLICK );
defaultBindings.put( Input.Keys.BUTTON_THUMBR, SPDAction.LEFT_CLICK );
defaultBindings.put( Input.Keys.BUTTON_L2, SPDAction.RIGHT_CLICK );
defaultBindings.put( Input.Keys.BUTTON_SELECT, SPDAction.MIDDLE_CLICK );
defaultBindings.put( Input.Keys.W, SPDAction.N );
defaultBindings.put( Input.Keys.A, SPDAction.W );
@@ -116,19 +111,12 @@ public class SPDAction extends GameAction {
defaultBindings.put( Input.Keys.NUMPAD_3, SPDAction.SE );
defaultBindings.put( Input.Keys.NUMPAD_5, SPDAction.WAIT );
defaultBindings.put( Input.Keys.BUTTON_THUMBL, SPDAction.WAIT );
defaultBindings.put( Input.Keys.F, SPDAction.INVENTORY );
defaultBindings.put( Input.Keys.I, SPDAction.INVENTORY );
defaultBindings.put( Input.Keys.BUTTON_R1, SPDAction.INVENTORY );
defaultBindings.put( Input.Keys.NUM_1, SPDAction.QUICKSLOT_1 );
defaultBindings.put( Input.Keys.BUTTON_Y, SPDAction.QUICKSLOT_1 );
defaultBindings.put( Input.Keys.NUM_2, SPDAction.QUICKSLOT_2 );
defaultBindings.put( Input.Keys.BUTTON_B, SPDAction.QUICKSLOT_2 );
defaultBindings.put( Input.Keys.NUM_3, SPDAction.QUICKSLOT_3 );
defaultBindings.put( Input.Keys.BUTTON_X, SPDAction.QUICKSLOT_3 );
defaultBindings.put( Input.Keys.NUM_4, SPDAction.QUICKSLOT_4 );
defaultBindings.put( Input.Keys.BUTTON_A, SPDAction.QUICKSLOT_4 );
defaultBindings.put( Input.Keys.NUM_5, SPDAction.QUICKSLOT_5 );
defaultBindings.put( Input.Keys.NUM_6, SPDAction.QUICKSLOT_6 );
@@ -139,7 +127,6 @@ public class SPDAction extends GameAction {
defaultBindings.put( Input.Keys.F5, SPDAction.BAG_5 );
defaultBindings.put( Input.Keys.E, SPDAction.EXAMINE );
defaultBindings.put( Input.Keys.BUTTON_L1, SPDAction.EXAMINE );
defaultBindings.put( Input.Keys.Z, SPDAction.REST );
defaultBindings.put( Input.Keys.Q, SPDAction.TAG_ATTACK );
@@ -161,6 +148,38 @@ public class SPDAction extends GameAction {
return new LinkedHashMap<>(defaultBindings);
}
private static final LinkedHashMap<Integer, GameAction> defaultControllerBindings = new LinkedHashMap<>();
static {
defaultControllerBindings.put( Input.Keys.BUTTON_START, SPDAction.BACK );
defaultControllerBindings.put( Input.Keys.BUTTON_R2, SPDAction.LEFT_CLICK );
defaultControllerBindings.put( Input.Keys.BUTTON_THUMBR, SPDAction.LEFT_CLICK );
defaultControllerBindings.put( Input.Keys.BUTTON_L2, SPDAction.RIGHT_CLICK );
defaultControllerBindings.put( Input.Keys.BUTTON_SELECT, SPDAction.MIDDLE_CLICK );
defaultControllerBindings.put( Input.Keys.DPAD_UP+1000, SPDAction.N );
defaultControllerBindings.put( Input.Keys.DPAD_LEFT+1000, SPDAction.W );
defaultControllerBindings.put( Input.Keys.DPAD_DOWN+1000, SPDAction.S );
defaultControllerBindings.put( Input.Keys.DPAD_RIGHT+1000, SPDAction.E );
defaultControllerBindings.put( Input.Keys.BUTTON_THUMBL, SPDAction.WAIT );
defaultControllerBindings.put( Input.Keys.BUTTON_R1, SPDAction.INVENTORY );
defaultControllerBindings.put( Input.Keys.BUTTON_L1, SPDAction.EXAMINE );
//plan for new buttons: quickslots, quick inventory,
//Probably want to repurpose dpad too: attack, loot(or combine this?), special action, resume
defaultControllerBindings.put( Input.Keys.BUTTON_Y, SPDAction.QUICKSLOT_1 );
defaultControllerBindings.put( Input.Keys.BUTTON_B, SPDAction.QUICKSLOT_2 );
defaultControllerBindings.put( Input.Keys.BUTTON_X, SPDAction.QUICKSLOT_3 );
defaultControllerBindings.put( Input.Keys.BUTTON_A, SPDAction.QUICKSLOT_4 );
}
public static LinkedHashMap<Integer, GameAction> getControllerDefaults() {
return new LinkedHashMap<>(defaultControllerBindings);
}
//hard bindings for android devices
static {
KeyBindings.addHardBinding( Input.Keys.BACK, SPDAction.BACK );
@@ -187,7 +206,7 @@ public class SPDAction extends GameAction {
LinkedHashMap<Integer, GameAction> merged = new LinkedHashMap<>();
for (GameAction a : allActions()) {
if (firstKeys.contains(a.name())) {
if (firstKeys.contains(a.name()) && !ControllerHandler.icControllerKey(firstKeys.getInt(a.name()))) {
if (firstKeys.getInt(a.name()) == 0){
continue; //we have no keys assigned to this action, move to the next one
} else {
@@ -204,7 +223,7 @@ public class SPDAction extends GameAction {
}
}
if (secondKeys.contains(a.name())) {
if (secondKeys.contains(a.name()) && !ControllerHandler.icControllerKey(secondKeys.getInt(a.name()))) {
if (secondKeys.getInt(a.name()) == 0){
continue; //we have no more keys assigned to this action, move to the next one
} else {
@@ -221,7 +240,7 @@ public class SPDAction extends GameAction {
}
}
if (thirdKeys.contains(a.name())) {
if (thirdKeys.contains(a.name()) && !ControllerHandler.icControllerKey(thirdKeys.getInt(a.name()))) {
if (thirdKeys.getInt(a.name()) == 0){
continue; //we have no more keys assigned to this action, move to the next one
} else {
@@ -242,8 +261,72 @@ public class SPDAction extends GameAction {
KeyBindings.setAllBindings(merged);
defaults = getControllerDefaults();
merged.clear();
Bundle firstButtons = b.getBundle("first_keys_controller");
Bundle secondButtons = b.getBundle("second_keys_controller");
Bundle thirdButtons = b.getBundle("third_keys_controller");
for (GameAction a : allActions()) {
if (firstButtons.contains(a.name()) && ControllerHandler.icControllerKey(firstButtons.getInt(a.name()))) {
if (firstButtons.getInt(a.name()) == 0){
continue; //we have no keys assigned to this action, move to the next one
} else {
merged.put(firstButtons.getInt(a.name()), a);
defaults.remove(firstButtons.getInt(a.name())); //prevent duplicates in other actions
}
} else {
//if we have no custom key here, find the first one from defaults and merge it
for (int i : defaults.keySet()){
if (defaults.get(i) == a){
merged.put(i, defaults.remove(i));
break;
}
}
}
if (secondButtons.contains(a.name()) && ControllerHandler.icControllerKey(secondButtons.getInt(a.name()))) {
if (secondButtons.getInt(a.name()) == 0){
continue; //we have no more keys assigned to this action, move to the next one
} else {
merged.put(secondButtons.getInt(a.name()), a);
defaults.remove(secondButtons.getInt(a.name()));
}
} else {
//if we have no custom key here, find the next one from defaults and merge it
for (int i : defaults.keySet()){
if (defaults.get(i) == a){
merged.put(i, defaults.remove(i));
break;
}
}
}
if (thirdButtons.contains(a.name()) && ControllerHandler.icControllerKey(thirdButtons.getInt(a.name()))) {
if (thirdButtons.getInt(a.name()) == 0){
continue; //we have no more keys assigned to this action, move to the next one
} else {
merged.put(thirdButtons.getInt(a.name()), a);
defaults.remove(thirdButtons.getInt(a.name()));
}
} else {
//if we have no custom key here, find the next one from defaults and merge it
for (int i : defaults.keySet()){
if (defaults.get(i) == a){
merged.put(i, defaults.remove(i));
break;
}
}
}
}
KeyBindings.setAllControllerBindings(merged);
} catch (Exception e){
KeyBindings.setAllBindings(getDefaults());
KeyBindings.setAllControllerBindings(getControllerDefaults());
}
}
@@ -305,6 +388,59 @@ public class SPDAction extends GameAction {
b.put("second_keys", secondKeys);
b.put("third_keys", thirdKeys);
Bundle firstButtons = new Bundle();
Bundle secondButtons = new Bundle();
Bundle thirdButtons = new Bundle();
for (GameAction a : allActions()){
int firstCur = 0;
int secondCur = 0;
int thirdCur = 0;
int firstDef = 0;
int secondDef = 0;
int thirdDef = 0;
for (int i : defaultControllerBindings.keySet()){
if (defaultControllerBindings.get(i) == a){
if (firstDef == 0) {
firstDef = i;
} else if (secondDef == 0) {
secondDef = i;
} else {
thirdDef = i;
}
}
}
LinkedHashMap<Integer, GameAction> curBindings = KeyBindings.getAllControllerBindings();
for (int i : curBindings.keySet()){
if (curBindings.get(i) == a){
if (firstCur == 0) {
firstCur = i;
} else if (secondCur == 0) {
secondCur = i;
} else {
thirdCur = i;
}
}
}
if (firstCur != firstDef){
firstButtons.put(a.name(), firstCur);
}
if (secondCur != secondDef){
secondButtons.put(a.name(), secondCur);
}
if (thirdCur != thirdDef){
thirdButtons.put(a.name(), thirdCur);
}
}
b.put("first_keys_controller", firstButtons);
b.put("second_keys_controller", secondButtons);
b.put("third_keys_controller", thirdButtons);
try {
FileUtils.bundleToFile(BINDINGS_FILE, b);
} catch (IOException e) {

View File

@@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.ScrollPane;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.watabou.input.ControllerHandler;
import com.watabou.input.GameAction;
import com.watabou.input.KeyBindings;
import com.watabou.input.KeyEvent;
@@ -57,9 +58,13 @@ public class WndKeyBindings extends Window {
private LinkedHashMap<Integer, GameAction> changedBindings;
public WndKeyBindings() {
private static boolean controller = false;
changedBindings = KeyBindings.getAllBindings();
public WndKeyBindings(Boolean controller) {
this.controller = controller;
changedBindings = controller ? KeyBindings.getAllControllerBindings() : KeyBindings.getAllBindings();
RenderedTextBlock ttlAction = PixelScene.renderTextBlock(Messages.get(this, "ttl_action"), 9);
ttlAction.setPos( COL1_CENTER - ttlAction.width()/2, (BTN_HEIGHT - ttlAction.height())/2);
@@ -119,6 +124,15 @@ public class WndKeyBindings extends Window {
//start at 1. No bindings for NONE
if (action.code() < 1) continue;
//mouse bindings are only available to controllers
if ((action == GameAction.LEFT_CLICK
|| action == GameAction.RIGHT_CLICK
|| action == GameAction.MIDDLE_CLICK) && !controller){
continue;
}
//TODO probably exclude some binding for controllers, and adjust default mappings
BindingItem item = new BindingItem(action);
item.setRect(0, y, WIDTH, BindingItem.HEIGHT);
bindingsList.addToBack(item);
@@ -132,7 +146,7 @@ public class WndKeyBindings extends Window {
RedButton btnDefaults = new RedButton(Messages.get(this, "default"), 9){
@Override
protected void onClick() {
changedBindings = SPDAction.getDefaults();
changedBindings = controller ? SPDAction.getControllerDefaults() : SPDAction.getDefaults();
for (BindingItem i : listItems){
int key1 = 0;
int key2 = 0;
@@ -154,7 +168,8 @@ public class WndKeyBindings extends Window {
RedButton btnConfirm = new RedButton(Messages.get(this, "confirm"), 9){
@Override
protected void onClick() {
KeyBindings.setAllBindings(changedBindings);
if (controller) KeyBindings.setAllControllerBindings(changedBindings);
else KeyBindings.setAllBindings(changedBindings);
SPDAction.saveBindings();
hide();
}
@@ -221,7 +236,12 @@ public class WndKeyBindings extends Window {
actionName.setHightlighting(false);
add(actionName);
ArrayList<Integer> keys = KeyBindings.getBoundKeysForAction(action);
ArrayList<Integer> keys;
if (controller){
keys = KeyBindings.getControllerKeysForAction(action);
} else {
keys = KeyBindings.getKeyboardKeysForAction(action);
}
origKey1 = key1 = keys.isEmpty() ? 0 : keys.remove(0);
origKey2 = key2 = keys.isEmpty() ? 0 : keys.remove(0);
origKey3 = key3 = keys.isEmpty() ? 0 : keys.remove(0);
@@ -465,6 +485,11 @@ public class WndKeyBindings extends Window {
if (btnCancel.inside(hoverPos.x, hoverPos.y)) return true;
}
//ignore controller buttons on key bindings, and vice-versa
if (ControllerHandler.icControllerKey(event.code) != controller){
return true;
}
if (event.pressed){
changedKey.text(Messages.get(this, "changed_bind", KeyBindings.getKeyName(event.code)));
changedKey.setPos((WIDTH - changedKey.width())/2, changedKey.top());

View File

@@ -689,7 +689,7 @@ public class WndSettings extends WndTabbed {
@Override
protected void onClick() {
super.onClick();
ShatteredPixelDungeon.scene().addToFront(new WndKeyBindings());
ShatteredPixelDungeon.scene().addToFront(new WndKeyBindings(false));
}
};
@@ -701,7 +701,7 @@ public class WndSettings extends WndTabbed {
@Override
protected void onClick() {
super.onClick();
//TODO Controller bindings menu
ShatteredPixelDungeon.scene().addToFront(new WndKeyBindings(true));
}
};