/* * Copyright (c) 2002-2008 LWJGL Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'LWJGL' nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.lwjgl.input; import java.util.ArrayList; import net.java.games.input.Component; import net.java.games.input.Component.Identifier.Axis; import net.java.games.input.Component.Identifier.Button; import net.java.games.input.Event; import net.java.games.input.EventQueue; import net.java.games.input.Rumbler; /** * A wrapper round a JInput controller that attempts to make the interface * more useable. * * @author Kevin Glass */ class JInputController implements Controller { /** The JInput controller this class is wrapping */ private net.java.games.input.Controller target; /** The index that has been assigned to this controller */ private int index; /** The Buttons that have been detected on the JInput controller */ private ArrayList<Component> buttons = new ArrayList<Component>(); /** The Axes that have been detected on the JInput controller */ private ArrayList<Component> axes = new ArrayList<Component>(); /** The POVs that have been detected on the JInput controller */ private ArrayList<Component> pov = new ArrayList<Component>(); /** The rumblers exposed by the controller */ private Rumbler[] rumblers; /** The state of the buttons last check */ private boolean[] buttonState; /** The values that were read from the pov last check */ private float[] povValues; /** The values that were read from the axes last check */ private float[] axesValue; /** The maximum values read for each axis */ private float[] axesMax; /** The dead zones for each axis */ private float[] deadZones; /** The index of the X axis or -1 if no X axis is defined */ private int xaxis = -1; /** The index of the Y axis or -1 if no Y axis is defined */ private int yaxis = -1; /** The index of the X axis or -1 if no Z axis is defined */ private int zaxis = -1; /** The index of the RX axis or -1 if no RX axis is defined */ private int rxaxis = -1; /** The index of the RY axis or -1 if no RY axis is defined */ private int ryaxis = -1; /** The index of the RZ axis or -1 if no RZ axis is defined */ private int rzaxis = -1; /** * Create a new controller that wraps round a JInput controller and hopefully * makes it easier to use. * * @param index The index this controller has been assigned to * @param target The target JInput controller this class is wrapping */ JInputController(int index, net.java.games.input.Controller target) { this.target = target; this.index = index; Component[] sourceAxes = target.getComponents(); for ( Component sourceAxis : sourceAxes ) { if ( sourceAxis.getIdentifier() instanceof Button ) { buttons.add(sourceAxis); } else if ( sourceAxis.getIdentifier().equals(Axis.POV) ) { pov.add(sourceAxis); } else { axes.add(sourceAxis); } } buttonState = new boolean[buttons.size()]; povValues = new float[pov.size()]; axesValue = new float[axes.size()]; int buttonsCount = 0; int axesCount = 0; // initialise the state for ( Component sourceAxis : sourceAxes ) { if ( sourceAxis.getIdentifier() instanceof Button ) { buttonState[buttonsCount] = sourceAxis.getPollData() != 0; buttonsCount++; } else if ( sourceAxis.getIdentifier().equals(Axis.POV) ) { // no account for POV yet // pov.add(sourceAxes[i]); } else { axesValue[axesCount] = sourceAxis.getPollData(); if ( sourceAxis.getIdentifier().equals(Axis.X) ) { xaxis = axesCount; } if ( sourceAxis.getIdentifier().equals(Axis.Y) ) { yaxis = axesCount; } if ( sourceAxis.getIdentifier().equals(Axis.Z) ) { zaxis = axesCount; } if ( sourceAxis.getIdentifier().equals(Axis.RX) ) { rxaxis = axesCount; } if ( sourceAxis.getIdentifier().equals(Axis.RY) ) { ryaxis = axesCount; } if ( sourceAxis.getIdentifier().equals(Axis.RZ) ) { rzaxis = axesCount; } axesCount++; } } axesMax = new float[axes.size()]; deadZones = new float[axes.size()]; for (int i=0;i<axesMax.length;i++) { axesMax[i] = 1.0f; deadZones[i] = 0.05f; } rumblers = target.getRumblers(); } /* * @see org.lwjgl.input.Controller#getName() */ public String getName() { String name = target.getName(); return name; } /* * @see org.lwjgl.input.Controller#getIndex() */ public int getIndex() { return index; } /* * @see org.lwjgl.input.Controller#getButtonCount() */ public int getButtonCount() { return buttons.size(); } /* * @see org.lwjgl.input.Controller#getButtonName(int) */ public String getButtonName(int index) { return buttons.get(index).getName(); } /* * @see org.lwjgl.input.Controller#isButtonPressed(int) */ public boolean isButtonPressed(int index) { return buttonState[index]; } /* * @see org.lwjgl.input.Controller#poll() */ public void poll() { target.poll(); Event event = new Event(); EventQueue queue = target.getEventQueue(); while (queue.getNextEvent(event)) { // handle button event if (buttons.contains(event.getComponent())) { Component button = event.getComponent(); int buttonIndex = buttons.indexOf(button); buttonState[buttonIndex] = event.getValue() != 0; // fire button pressed event Controllers.addEvent(new ControllerEvent(this,event.getNanos(),ControllerEvent.BUTTON,buttonIndex, buttonState[buttonIndex],false,false,0,0)); } // handle pov events if (pov.contains(event.getComponent())) { Component povComponent = event.getComponent(); int povIndex = pov.indexOf(povComponent); float prevX = getPovX(); float prevY = getPovY(); povValues[povIndex] = event.getValue(); if (prevX != getPovX()) { Controllers.addEvent(new ControllerEvent(this,event.getNanos(),ControllerEvent.POVX,0,false,false)); } if (prevY != getPovY()) { Controllers.addEvent(new ControllerEvent(this,event.getNanos(),ControllerEvent.POVY,0,false,false)); } } // handle axis updates if (axes.contains(event.getComponent())) { Component axis = event.getComponent(); int axisIndex = axes.indexOf(axis); float value = axis.getPollData(); float xaxisValue = 0; float yaxisValue = 0; // fixed dead zone since most axis don't report it :( if (Math.abs(value) < deadZones[axisIndex]) { value = 0; } if (Math.abs(value) < axis.getDeadZone()) { value = 0; } if (Math.abs(value) > axesMax[axisIndex]) { axesMax[axisIndex] = Math.abs(value); } // normalize the value based on maximum value read in the past value /= axesMax[axisIndex]; if (axisIndex == xaxis) { xaxisValue = value; } if (axisIndex == yaxis) { yaxisValue = value; } // fire event Controllers.addEvent(new ControllerEvent(this,event.getNanos(),ControllerEvent.AXIS,axisIndex,false, axisIndex == xaxis,axisIndex == yaxis,xaxisValue,yaxisValue)); axesValue[axisIndex] = value; } } } /* * @see org.lwjgl.input.Controller#getAxisCount() */ public int getAxisCount() { return axes.size(); } /* * @see org.lwjgl.input.Controller#getAxisName(int) */ public String getAxisName(int index) { return axes.get(index).getName(); } /* * @see org.lwjgl.input.Controller#getAxisValue(int) */ public float getAxisValue(int index) { return axesValue[index]; } /* * @see org.lwjgl.input.Controller#getXAxisValue() */ public float getXAxisValue() { if (xaxis == -1) { return 0; } return getAxisValue(xaxis); } /* * @see org.lwjgl.input.Controller#getYAxisValue() */ public float getYAxisValue() { if (yaxis == -1) { return 0; } return getAxisValue(yaxis); } /* * @see org.lwjgl.input.Controller#getXAxisDeadZone() */ public float getXAxisDeadZone() { if (xaxis == -1) { return 0; } return getDeadZone(xaxis); } /* * @see org.lwjgl.input.Controller#getYAxisDeadZone() */ public float getYAxisDeadZone() { if (yaxis == -1) { return 0; } return getDeadZone(yaxis); } /* * @see org.lwjgl.input.Controller#setXAxisDeadZone(float) */ public void setXAxisDeadZone(float zone) { setDeadZone(xaxis,zone); } /* * @see org.lwjgl.input.Controller#setYAxisDeadZone(float) */ public void setYAxisDeadZone(float zone) { setDeadZone(yaxis,zone); } /* * @see org.lwjgl.input.Controller#getDeadZone(int) */ public float getDeadZone(int index) { return deadZones[index]; } /* * @see org.lwjgl.input.Controller#setDeadZone(int, float) */ public void setDeadZone(int index, float zone) { deadZones[index] = zone; } /* * @see org.lwjgl.input.Controller#getZAxisValue() */ public float getZAxisValue() { if (zaxis == -1) { return 0; } return getAxisValue(zaxis); } /* * @see org.lwjgl.input.Controller#getZAxisDeadZone() */ public float getZAxisDeadZone() { if (zaxis == -1) { return 0; } return getDeadZone(zaxis); } /* * @see org.lwjgl.input.Controller#setZAxisDeadZone(float) */ public void setZAxisDeadZone(float zone) { setDeadZone(zaxis,zone); } /* * @see org.lwjgl.input.Controller#getRXAxisValue() */ public float getRXAxisValue() { if (rxaxis == -1) { return 0; } return getAxisValue(rxaxis); } /* * @see org.lwjgl.input.Controller#getRXAxisDeadZone() */ public float getRXAxisDeadZone() { if (rxaxis == -1) { return 0; } return getDeadZone(rxaxis); } /* * @see org.lwjgl.input.Controller#setRXAxisDeadZone(float) */ public void setRXAxisDeadZone(float zone) { setDeadZone(rxaxis,zone); } /* * @see org.lwjgl.input.Controller#getRYAxisValue() */ public float getRYAxisValue() { if (ryaxis == -1) { return 0; } return getAxisValue(ryaxis); } /* * @see org.lwjgl.input.Controller#getRYAxisDeadZone() */ public float getRYAxisDeadZone() { if (ryaxis == -1) { return 0; } return getDeadZone(ryaxis); } /* * @see org.lwjgl.input.Controller#setRYAxisDeadZone(float) */ public void setRYAxisDeadZone(float zone) { setDeadZone(ryaxis,zone); } /* * @see org.lwjgl.input.Controller#getRZAxisValue() */ public float getRZAxisValue() { if (rzaxis == -1) { return 0; } return getAxisValue(rzaxis); } /* * @see org.lwjgl.input.Controller#getRZAxisDeadZone() */ public float getRZAxisDeadZone() { if (rzaxis == -1) { return 0; } return getDeadZone(rzaxis); } /* * @see org.lwjgl.input.Controller#setRZAxisDeadZone(float) */ public void setRZAxisDeadZone(float zone) { setDeadZone(rzaxis,zone); } /* * @see org.lwjgl.input.Controller#getPovX() */ public float getPovX() { if (pov.size() == 0) { return 0; } float value = povValues[0]; if ((value == Component.POV.DOWN_LEFT) || (value == Component.POV.UP_LEFT) || (value == Component.POV.LEFT)) { return -1; } if ((value == Component.POV.DOWN_RIGHT) || (value == Component.POV.UP_RIGHT) || (value == Component.POV.RIGHT)) { return 1; } return 0; } /* * @see org.lwjgl.input.Controller#getPovY() */ public float getPovY() { if (pov.size() == 0) { return 0; } float value = povValues[0]; if ((value == Component.POV.DOWN_LEFT) || (value == Component.POV.DOWN_RIGHT) || (value == Component.POV.DOWN)) { return 1; } if ((value == Component.POV.UP_LEFT) || (value == Component.POV.UP_RIGHT) || (value == Component.POV.UP)) { return -1; } return 0; } public int getRumblerCount() { return rumblers.length; } public String getRumblerName(int index) { return rumblers[index].getAxisName(); } public void setRumblerStrength(int index, float strength) { rumblers[index].rumble(strength); } }