Skip to content

Commit

Permalink
Make gamepad buttons configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
agateau committed Jul 16, 2018
1 parent 8461a62 commit de1fe78
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 28 deletions.
4 changes: 3 additions & 1 deletion android/assets/screens/gamepadconfig.gdxui
Expand Up @@ -4,7 +4,9 @@
<Label id="mainLabel" style="title"
topCenter="root.topCenter 0 -2">Configure input</Label>

<Menu id="menu" center="root.center 0 -1" width="400"/>
<Menu id="menu" topCenter="mainLabel.bottomCenter 0 -4"
labelColumnWidth="150"
defaultItemWidth="600"/>

<ImageButton id="backButton"
bottomLeft="root.bottomLeft 1 1"
Expand Down
7 changes: 7 additions & 0 deletions core/src/com/agateau/pixelwheels/GameConfig.java
Expand Up @@ -133,6 +133,13 @@ public void setPlayerInputHandlerFactory(int idx, GameInputHandlerFactory factor
mPlayerInputFactoryIds[idx] = factory.getId();
}

public void savePlayerInputHandlerConfig(int index) {
Assert.check(index < mPlayerInputHandlers.size, "Not enough input handlers for index " + String.valueOf(index));
GameInputHandler handler = mPlayerInputHandlers.get(index);
String prefix = getInputPrefix(index);
handler.saveConfig(mPreferences, prefix);
}

private String getInputPrefix(int idx) {
// Include the factory id to ensure there are no configuration clashes when switching
// between input handlers
Expand Down
87 changes: 84 additions & 3 deletions core/src/com/agateau/pixelwheels/screens/GamepadConfigScreen.java
Expand Up @@ -18,26 +18,82 @@
*/
package com.agateau.pixelwheels.screens;

import com.agateau.pixelwheels.GameConfig;
import com.agateau.pixelwheels.PwGame;
import com.agateau.pixelwheels.gameinput.GamepadInputHandler;
import com.agateau.ui.GamepadInputMapper;
import com.agateau.ui.RefreshHelper;
import com.agateau.ui.UiBuilder;
import com.agateau.ui.anchor.AnchorGroup;
import com.agateau.ui.menu.ButtonMenuItem;
import com.agateau.ui.menu.Menu;
import com.agateau.ui.menu.MenuItemListener;
import com.agateau.utils.FileUtils;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Array;

import java.util.Locale;

/**
* Configure an input device
*/
public class GamepadConfigScreen extends PwStageScreen {
private final PwGame mGame;
private final int mPlayerIdx;
private final GamepadInputMapper mInputMapper;
private final Array<GamepadButtonItemController> mButtonControllers = new Array<GamepadButtonItemController>();

private GamepadButtonItemController mEditingController;

private class GamepadButtonItemController implements GamepadInputMapper.Listener {
private final ButtonMenuItem mMenuItem;
private final GamepadInputMapper.GamepadButton mButtonId;
private boolean mEditing = false;

GamepadButtonItemController(ButtonMenuItem menuItem, GamepadInputMapper.GamepadButton buttonId) {
mMenuItem = menuItem;
mButtonId = buttonId;
mMenuItem.addListener(new MenuItemListener() {
@Override
public void triggered() {
onEditButton(GamepadButtonItemController.this);
}
});
updateText();
}

void setEditing(boolean editing) {
mEditing = editing;
if (editing) {
mInputMapper.setListener(this);
}
updateText();
}

private void updateText() {
String text;
if (mEditing) {
text = "Press the gamepad key...";
} else {
text = String.format(Locale.US, "%d", mInputMapper.getButtonCode(mButtonId));
}
mMenuItem.setText(text);
}

@Override
public void onButtonPressed(int buttonCode, boolean pressed) {
mInputMapper.setButtonCode(mButtonId, buttonCode);
onEditButton(null);
}
}

public GamepadConfigScreen(PwGame game, int playerIdx) {
GamepadConfigScreen(PwGame game, int playerIdx) {
super(game.getAssets().ui);
mGame = game;
mPlayerIdx = playerIdx;
GamepadInputHandler handler = (GamepadInputHandler) mGame.getConfig().getPlayerInputHandler(mPlayerIdx);
mInputMapper = (GamepadInputMapper) handler.getInputMapper();
new RefreshHelper(getStage()) {
@Override
protected void refresh() {
Expand All @@ -56,6 +112,9 @@ private void setupUi() {

Menu menu = builder.getActor("menu");

createButton(menu, "Trigger:", GamepadInputMapper.GamepadButton.TRIGGER);
createButton(menu, "Back:", GamepadInputMapper.GamepadButton.BACK);

builder.getActor("backButton").addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Expand All @@ -64,10 +123,32 @@ public void clicked(InputEvent event, float x, float y) {
});
}

private void createButton(Menu menu, String label, GamepadInputMapper.GamepadButton buttonId) {
ButtonMenuItem buttonItem = new ButtonMenuItem(menu, "");
menu.addItemWithLabel(label, buttonItem);
GamepadButtonItemController controller = new GamepadButtonItemController(buttonItem, buttonId);
mButtonControllers.add(controller);
}

private void onEditButton(GamepadButtonItemController controller) {
if (mEditingController != null) {
mEditingController.setEditing(false);
}
mEditingController = controller;
if (mEditingController != null) {
mEditingController.setEditing(true);
}
}

@Override
public void onBackPressed() {
mGame.getDebugIntrospector().save();
mGame.getGamePlayIntrospector().save();
saveConfig();
mGame.popScreen();
}

private void saveConfig() {
GameConfig config = mGame.getConfig();
config.savePlayerInputHandlerConfig(mPlayerIdx);

}
}
61 changes: 37 additions & 24 deletions core/src/com/agateau/ui/GamepadInputMapper.java
Expand Up @@ -25,6 +25,7 @@
import com.badlogic.gdx.controllers.PovDirection;
import com.badlogic.gdx.utils.Array;

import java.lang.ref.WeakReference;
import java.util.HashMap;

/**
Expand All @@ -48,15 +49,25 @@ private enum KeyState {
JUST_PRESSED
}

public enum GamepadButton {
TRIGGER,
BACK
}

private boolean mActive;

private final HashMap<VirtualKey, KeyState> mPressedKeys = new HashMap<VirtualKey, KeyState>();

private int mTriggerButtonCode = 1;
private int mBackButtonCode = 2;
private final HashMap<GamepadButton,Integer> mButtonCodes = new HashMap<GamepadButton, Integer>();

private static final GamepadInputMapper[] sInstances = new GamepadInputMapper[MAX_GAMEPAD_COUNT];

private WeakReference<Listener> mListenerRef;

public interface Listener {
void onButtonPressed(int buttonCode, boolean pressed);
}

public static GamepadInputMapper[] getInstances() {
if (sInstances[0] == null) {
createInstances();
Expand All @@ -68,22 +79,6 @@ public static GamepadInputMapper getInstance(int idx) {
return getInstances()[idx];
}

public int getTriggerButtonCode() {
return mTriggerButtonCode;
}

public void setTriggerButtonCode(int triggerButtonCode) {
mTriggerButtonCode = triggerButtonCode;
}

public int getBackButtonCode() {
return mBackButtonCode;
}

public void setBackButtonCode(int backButtonCode) {
mBackButtonCode = backButtonCode;
}

private static void createInstances() {
for (int idx = 0; idx < sInstances.length; ++idx) {
sInstances[idx] = new GamepadInputMapper(idx);
Expand All @@ -92,6 +87,8 @@ private static void createInstances() {

private GamepadInputMapper(int idx) {
Array<Controller> controllers = Controllers.getControllers();
mButtonCodes.put(GamepadButton.TRIGGER, 1);
mButtonCodes.put(GamepadButton.BACK, 2);
if (idx < controllers.size) {
controllers.get(idx).addListener(this);
mActive = true;
Expand All @@ -100,10 +97,22 @@ private GamepadInputMapper(int idx) {
}
}

public int getButtonCode(GamepadButton button) {
return mButtonCodes.get(button);
}

public void setButtonCode(GamepadButton button, int code) {
mButtonCodes.put(button, code);
}

public boolean isActive() {
return mActive;
}

public void setListener(Listener listener) {
mListenerRef = new WeakReference<Listener>(listener);
}

@Override
public boolean isKeyPressed(VirtualKey key) {
KeyState state = mPressedKeys.get(key);
Expand All @@ -123,14 +132,14 @@ public boolean isKeyJustPressed(VirtualKey key) {

@Override
public void loadConfig(Preferences preferences, String prefix) {
mTriggerButtonCode = preferences.getInteger(prefix + TRIGGER_BUTTON_PREF, 1);
mBackButtonCode = preferences.getInteger(prefix + BACK_BUTTON_PREF, 2);
mButtonCodes.put(GamepadButton.TRIGGER, preferences.getInteger(prefix + TRIGGER_BUTTON_PREF, 1));
mButtonCodes.put(GamepadButton.BACK, preferences.getInteger(prefix + BACK_BUTTON_PREF, 2));
}

@Override
public void saveConfig(Preferences preferences, String prefix) {
preferences.putInteger(prefix + TRIGGER_BUTTON_PREF, mTriggerButtonCode);
preferences.putInteger(prefix + BACK_BUTTON_PREF, mBackButtonCode);
preferences.putInteger(prefix + TRIGGER_BUTTON_PREF, mButtonCodes.get(GamepadButton.TRIGGER));
preferences.putInteger(prefix + BACK_BUTTON_PREF, mButtonCodes.get(GamepadButton.BACK));
}

@Override
Expand Down Expand Up @@ -218,10 +227,14 @@ private static AxisValue normalizeAxisValue(float value) {
}

private void onButtonPressed(int buttonCode, boolean pressed) {
if (buttonCode == mTriggerButtonCode) {
if (buttonCode == mButtonCodes.get(GamepadButton.TRIGGER)) {
setKeyJustPressed(VirtualKey.TRIGGER, pressed);
} else if (buttonCode == mBackButtonCode) {
} else if (buttonCode == mButtonCodes.get(GamepadButton.BACK)) {
setKeyJustPressed(VirtualKey.BACK, pressed);
}
Listener listener = mListenerRef != null ? mListenerRef.get() : null;
if (listener != null) {
listener.onButtonPressed(buttonCode, pressed);
}
}
}

0 comments on commit de1fe78

Please sign in to comment.