diff options
27 files changed, 5234 insertions, 0 deletions
diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..3b191e3 --- /dev/null +++ b/README.txt @@ -0,0 +1,81 @@ +Project: net.java.games.* +Purpose: Open source game libraries +Authors: + -- input API design: + Michael Martak, Sun Microsystems + Thomas Daniel, Sony Computer Entertainment + -- input API original author: + Michael Martak,Sun Microsystems + -- input API original release author: + Jeff Kesselman, Game Technology Architect, + Advanced Software Technologies Group, + Sun Microsystems. + -- this file updated on 06/06/2003 by Jeff Kesselman + + +Introduction: + +This is the source tree for the Java Game Initiative (JGI) Open Source +client game programming APIs. + +Build Requirements: + +This project has been built in the follwing environment. + -- Win32 (Win 2000 in the case of our machine) + -- Sun J2SDK 1.4 (available at java.sun.com) + -- MinGW 2.0.0 plus the following updates: (all available at www.mingw.org) + -- binutils 2.13.90 + -- w32api-2.2 + -- mingw-runtime-2.4 + -- "Peter Puck's" directx8 binding + (http://www.urebelscum.speedhost.com/download.html, file: dx8libs.zip + -- ANT 1.4.1 (available at apache.org) + + +Directory Organization: + +The root contains a master ANT build.xml and the following sub directories: + -- coreAPI: The actual API + -- plugins: Directories for bildign controlelr plugins. + (Currently the only plug in is the Win32 DX8 plugin.) + +Build instructions: + +To clean: ant clean +To build: ant all (or just ant) +To build docs: ant javadoc +To test: + First cd to coreAPI. There are currently 2 tests there. + Textest: A simple discovery test that dumps + the data about the discovered controllers to stdout + To run: ant textest + Readtest: A test that creates a window for each discovered + controller (or sub-controller) which displays the + current state of all the controller's axiis. + (Note: The windows currrently all open at the same + place on the screen so yo uwill have to move them to + see them all.) + To run: ant readtest + +Release Info: + Initial Release: This release contains an implementation of the input + API designed by Mike Martak of Sun and Thomas (?) of Sony CEA for + the WIn32 platform. All the code in src/input is cross platform. The + Win32 code is segregated to the DirectX plugin (src/DXplugin) which + depends on DirectInput from DX7 (or later). + + 05/09/2003: A number of bugs and problems with the DXPlugin are fixed in this + release. This release also brings the code up to date using the DI8 + interface. This thus is the first release that requries Peter Puck's + DX8 bindings to compile with MinGW. + + 05/09/2003 (second update): + This version adds a new standard value type to the API. + Axis.POV holds standard definitions for values for POV (hat) switches + -- Axis.POV.CENTER and Axis.POV.OFF are synonmous and are + the center position. + -- Axis.POV.UP, Axis.POV.DOWN, Axis.POV.LEFT and Axis.POV.RIGHT + should be self explainatory. + Any hat that claims to be "normalized" will return these values. (It is + recommended that all hats be normalized by the systemn specific plugins.) + diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..a934222 --- /dev/null +++ b/build.xml @@ -0,0 +1,50 @@ +<?xml version="1.0"?> + +<!-- Written to assume that classpath is rooted in the current directory. --> +<!-- So this should be OK if you make this script in the root of a filesystem. --> +<!-- If not, you may prefer to adjust the basedir, or move some directories around. --> +<!-- The idea is that both Ant and NetBeans have to know what the package root is --> +<!-- for the classes in your application. --> +<project name="Sun Games Initiative Client Technologies" basedir="." default="all"> + + <!-- Don't worry if you don't know the Ant syntax completely or need help on some tasks! --> + <!-- The standard Ant documentation is bundled. See Help | Help Sets | Ant 1.4.1 Manual. --> + + <target name="init"> + <!-- You can set up any variables you want used throughout the script here. --> + <!-- <property name="hello" value="world"/ --> + <!-- To use e.g. Jikes, uncomment this line. --> + <!-- (Or make the same change in Tools | Options | Ant Settings | Properties.) --> + <!-- <property name="build.compiler" value="jikes"/> --> + <!-- You might like to set up some overridable paths, etc.: --> + <!-- <property name="mylib" value="../lib/mylib.jar"/> --> + </target> + + <target name="compile" depends="init"> + <!-- Both srcdir and destdir should be package roots. --> + <!-- They could be different of course; in that case NetBeans can also be set --> + <!-- up to compile to a different filesystem in the same way; see Compiler Types: --> + <ant dir="coreAPI" /> + <ant dir="plugins/DX8" /> + </target> + + <target name="javadoc" depends="init"> + <!-- Both srcdir and destdir should be package roots. --> + <!-- They could be different of course; in that case NetBeans can also be set --> + <!-- up to compile to a different filesystem in the same way; see Compiler Types: --> + <ant dir="coreAPI" target="javadoc"/> + <ant dir="plugins/DX8" target="javadoc"/> + </target> + + + <target name="all" depends="init,compile" description="Build everything."> + <echo message="Application built. Hello ${hello}!"/> + </target> + + <target name="clean" depends="init" description="Clean all build products."> + <ant dir="plugins/DX8" target="clean"/> + <ant dir="coreAPI" target="clean"/> + </target> + + +</project> diff --git a/coreAPI/README.txt b/coreAPI/README.txt new file mode 100644 index 0000000..90caf93 --- /dev/null +++ b/coreAPI/README.txt @@ -0,0 +1,54 @@ +This file modified last on 06/06/2003 by Jeff Kesselman + +This is the source tree for the core input API. + +Directory Organization: + +The root contains a master ANT build.xml. +After a successful build of the project you will have the following sub directories: + -- apidocs Where the javadocs get built to + -- lib Where dependant libraries are kept. + -- bin Where the actual API is built to + -- src The source files. + -- src/test Execution directories and data for tests. + +Build instructions: + +To clean: ant clean +To build: ant all (or just ant) +To build docs: ant javadoc +To test: + Textest: A simple discovery test that dumps + the data about the discovered controllers to stdout + To run: ant textest + Readtest: A test that creates a window for each discovered + controller (or sub-controller) which displays the + current state of all the controller's axiis. + (Note: The windows currrently all open at the same + place on the screen so yo uwill have to move them to + see them all.) + To run: ant readtest + + +Release Info: + Initial Release: This release contains an implementation of the input + API designed by Mike Martak of Sun and Thomas (?) of Sony CEA for + the WIn32 platform. All the code in src/input is cross platform. The + Win32 code is segregated to the DirectX plugin (src/DXplugin) which + depends on DirectInput from DX7 (or later). + + 05/09/2003: A number of bugs and problems with the DXPlugin are fixed in this + release. This release also brings the code up to date using the DI8 + interface. This thus is the first release that requries Peter Puck's + DX8 bindings to compile with MinGW. + + 05/09/2003 (second update): + This version adds a new standard value type to the API. + Axis.POV holds standard definitions for values for POV (hat) switches + -- Axis.POV.CENTER and Axis.POV.OFF are synonmous and are + the center position. + -- Axis.POV.UP, Axis.POV.DOWN, Axis.POV.LEFT and Axis.POV.RIGHT + should be self explainatory. + Any hat that claims to be "normalized" will return these values. (It is + recommended that all hats be normalized by the systemn specific plugins.) + diff --git a/coreAPI/build.xml b/coreAPI/build.xml new file mode 100644 index 0000000..f2db003 --- /dev/null +++ b/coreAPI/build.xml @@ -0,0 +1,116 @@ +<?xml version="1.0"?> + +<!-- Written to assume that classpath is rooted in the current directory. --> +<!-- So this should be OK if you make this script in the root of a filesystem. --> +<!-- If not, you may prefer to adjust the basedir, or move some directories around. --> +<!-- The idea is that both Ant and NetBeans have to know what the package root is --> +<!-- for the classes in your application. --> +<project name="Game Input API" basedir="." default="all"> + + <!-- Don't worry if you don't know the Ant syntax completely or need help on some tasks! --> + <!-- The standard Ant documentation is bundled. See Help | Help Sets | Ant 1.4.1 Manual. --> + + <target name="init"> + <!-- You can set up any variables you want used throughout the script here. --> + <!-- property name="hello" value="world" --> + <!-- To use e.g. Jikes, uncomment this line. --> + <!-- (Or make the same change in Tools | Options | Ant Settings | Properties.) --> + <!-- <property name="build.compiler" value="jikes"/> --> + <!-- You might like to set up some overridable paths, etc.: --> + <property name="utils" value="lib/jutils.jar"/> + <mkdir dir="apidocs"/> + <mkdir dir="classes"/> + <mkdir dir="bin"/> + </target> + + <target name="compile" depends="init"> + <!-- Both srcdir and destdir should be package roots. --> + <!-- They could be different of course; in that case NetBeans can also be set --> + <!-- up to compile to a different filesystem in the same way; see Compiler Types: --> + <javac srcdir="src/java" destdir="classes" debug="true" deprecation="true" source="1.4"> + <include name="net/**"/> + <!-- To add something to the classpath: --> + <classpath> + <pathelement location="${utils}"/> + </classpath> + <!-- To exclude some files: --> + <!-- + <exclude name="com/foo/SomeFile.java"/> + <exclude name="com/foo/somepackage/"/> + --> + </javac> + </target> + + <target name="jar" depends="init,compile"> + <!-- To make a standalone app: --> + <!-- 1. Create a myapp.mf manifest somewhere. --> + <!-- 2. Put in it: --> + <!-- Manifest-Version: 1.0 --> + <!-- Main-Class: com.foo.Main --> + <!-- 3. Pass to <jar>: manifest="myapp.mf" --> + <jar jarfile="bin/controller.jar" compress="true" basedir="classes"> + <include name="net/**"/> + <exclude name="**/*.java"/> + <exclude name="**/*.form"/> + <exclude name="myapp.mf"/> + <exclude name="myapp.jar"/> + </jar> + <copy file="bin/controller.jar" todir="../plugins/DX8/lib" /> + </target> + + <target name="all" depends="init,jar" description="Build everything."> + <echo message="Application built. Hello ${hello}!"/> + </target> + + <target name="texttest" depends="init,all" description="Try running it."> + <java classname="net.java.games.input.test.ControllerTextTest" + fork="true" failonerror="true" dir="src/tests"> + <classpath> + <pathelement location="bin/controller.jar"/> + <pathelement location="${utils}"/> + </classpath> + <!-- Pass some args, perhaps: --> + <!-- <arg value="-myfile"/> --> + <!-- Will be given as an absolute path: --> + <!-- <arg file="myfile.txt"/> --> + </java> + </target> + <target name="readtest" depends="init,all" description="Try running it."> + <java classname="net.java.games.input.test.ControllerReadTest" + fork="true" failonerror="true" dir="src/tests"> + <classpath> + <pathelement location="bin/controller.jar"/> + <pathelement location="${utils}"/> + </classpath> + <!-- Pass some args, perhaps: --> + <!-- <arg value="-myfile"/> --> + <!-- Will be given as an absolute path: --> + <!-- <arg file="myfile.txt"/> --> + </java> + </target> + + <target name="javadoc" depends="init" description="Javadoc for my API."> + <javadoc packagenames="net.java.games.input.*" + destdir="apidocs" + additionalparam="-source 1.4"> + <sourcepath> + <pathelement location="src/java"/> + </sourcepath> + <classpath> + <pathelement location="${utils}"/> + </classpath> + </javadoc> + </target> + + <target name="clean" depends="init" description="Clean all build products."> + <delete> + <fileset dir="classes"> + <include name="**/*.class"/> + </fileset> + </delete> + <delete file="bin/controller.jar"/> + <delete dir="apidocs"/> + <delete file="../plugins/DX8/lib/controller.jar" /> + </target> + +</project> diff --git a/coreAPI/src/java/net/java/games/input/AbstractAxis.java b/coreAPI/src/java/net/java/games/input/AbstractAxis.java new file mode 100644 index 0000000..b0fa021 --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/AbstractAxis.java @@ -0,0 +1,153 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * Skeleton implementation of a named axis. + */ +public abstract class AbstractAxis implements Axis { + + /** + * Human-readable name for this Axis + */ + protected String name; + + /** + * Identifier for the axis + */ + protected Identifier id; + + /** + * Whether this axis is ready to receive polling data + */ + private boolean polling; + + /** + * Protected constructor + * @param name A name for the axis + */ + protected AbstractAxis(String name, Identifier id) { + this.name = name; + this.id = id; + this.polling = true; + } + + /** + * Returns the type or identifier of the axis. + */ + public Identifier getIdentifier() { + return id; + } + + /** + * Returns whether or not the axis is analog, or false if it is digital. + * @return false by default, can be overridden + */ + public boolean isAnalog() { + return false; + } + + /** + * Returns whether or not data polled from this axis is normalized + * between the values of -1.0f and 1.0f. + * @return true by default, can be overridden + */ + public boolean isNormalized() { + return true; + } + + /** + * Returns whether or not this axis is ready to receive polling data. + * By default, an abstract axis is set to receive polling data. + */ + public boolean isPolling() { + return polling; + } + + /** + * Sets whether or not the axis should receive polling data. + */ + public void setPolling(boolean polling) { + this.polling = polling; + } + + /** + * Returns the suggested dead zone for this axis. Dead zone is the + * amount polled data can vary before considered a significant change + * in value. An application can safely ignore changes less than this + * value in the positive or negative direction. + * @return 0.0f by default, can be overridden + */ + public float getDeadZone() { + return 0.0f; + } + + /** + * Returns the data from the last time the control has been polled. + * If this axis is a button, the value returned will be either 0.0f or 1.0f. + * If this axis is normalized, the value returned will be between -1.0f and + * 1.0f. + * @return 0.0f by default, can be overridden + */ + public float getPollData() { + return 0.0f; + } + + /** + * Returns a human-readable name for this axis. + */ + public String getName() { + return name; + } + + /** + * Returns a non-localized string description of this axis. + */ + public String toString() { + return name; + } + + /** + * Changes the name of this Axis. This should be done only during + * initialization of the axis so that its name remains immutable. + */ + public void setName(String name) { + this.name = name; + } +} // AbstractAxis diff --git a/coreAPI/src/java/net/java/games/input/AbstractController.java b/coreAPI/src/java/net/java/games/input/AbstractController.java new file mode 100644 index 0000000..99ee2da --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/AbstractController.java @@ -0,0 +1,194 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * An AbstractController is a skeleton implementation of a controller that + * contains a fixed number of axes, controllers, and rumblers. + */ +public abstract class AbstractController implements Controller { + + /** + * Null array representing no axes + */ + protected static final Axis[] NO_AXES = {}; + + /** + * Null array representing no child controllers + */ + protected static final Controller[] NO_CONTROLLERS = {}; + + /** + * Null array representing no rumblers + */ + protected static final Rumbler[] NO_RUMBLERS = {}; + + /** + * Human-readable name for this Controller + */ + private final String name; + + /** + * Array of axes + */ + protected Axis[] axes; + + /** + * Array of child controllers + */ + protected Controller[] children; + + /** + * Array of rumblers + */ + protected Rumbler[] rumblers; + + /** + * Protected constructor for a controller; initially contains no axes, + * child controllers, or rumblers. + * @param name The name for the controller + */ + protected AbstractController(String name) { + this(name, NO_AXES, NO_CONTROLLERS, NO_RUMBLERS); + } + + /** + * Protected constructor for a controller containing the specified + * axes, child controllers, and rumblers + * @param name name for the controller + * @param axes axes for the controller + * @param children child controllers for the controller + * @param rumblers rumblers for the controller + */ + protected AbstractController(String name, Axis[] axes, + Controller[] children, Rumbler[] rumblers) { + this.name = name; + this.axes = axes; + this.children = children; + this.rumblers = rumblers; + } + + /** + * Returns the controllers connected to make up this controller, or + * an empty array if this controller contains no child controllers. + * The objects in the array are returned in order of assignment priority + * (primary stick, secondary buttons, etc.). + */ + public Controller[] getControllers() { + return children; + } + + /** + * Returns the axes on this controller, in order of assignment priority. + * For example, the button controller on a mouse returns an array containing + * the primary or leftmost mouse button, followed by the secondary or + * rightmost mouse button (if present), followed by the middle mouse button + * (if present). + * The array returned is an empty array if this controller contains no axes + * (such as a logical grouping of child controllers). + */ + public Axis[] getAxes() { + return axes; + } + + /** + * Returns a single axis based on its identifier, or null + * if no axis with the specified type could be found. + * By default, AbstractController calls getAxes in this method so that + * subclasses may lazily initialize the array of axes, if necessary. + */ + public Axis getAxis(Axis.Identifier id) { + // Calls getAxes() so that subclasses may lazily set the array of axes. + Axis[] axes = getAxes(); + if (axes.length == 0) { + return null; + } + for (int i = 0; i < axes.length; i++) { + if (axes[i].getIdentifier() == id) { + return axes[i]; + } + } + return null; + } + + /** + * Returns the rumblers for sending feedback to this controller, or an + * empty array if there are no rumblers on this controller. + */ + public Rumbler[] getRumblers() { + return rumblers; + } + + /** + * Returns the port type for this Controller. + * @return PortType.UNKNOWN by default, can be overridden + */ + public PortType getPortType() { + return PortType.UNKNOWN; + } + + /** + * Returns the zero-based port number for this Controller. + * @return 0 by default, can be overridden + */ + public int getPortNumber() { + return 0; + } + + /** + * Returns a human-readable name for this Controller. + */ + public String getName() { + return name; + } + + /** + * Returns a non-localized string description of this controller. + */ + public String toString() { + return name; + } + + /** Returns the type of the Controller. + */ + public Type getType() { + return Type.UNKNOWN; + } + +} // class AbstractController diff --git a/coreAPI/src/java/net/java/games/input/Axis.java b/coreAPI/src/java/net/java/games/input/Axis.java new file mode 100644 index 0000000..a4abced --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/Axis.java @@ -0,0 +1,349 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * An axis is a single button, slider, or dial, which has a single range. An + * axis can hold information for motion (linear or rotational), velocity, + * force, or acceleration. + */ +public interface Axis { + + /** + * Returns the identifier of the axis. + */ + public abstract Identifier getIdentifier(); + + /** + * Returns <code>true</code> if data returned from <code>poll</code> + * is relative to the last call, or <code>false</code> if data + * is absolute. + */ + public abstract boolean isRelative(); + + /** + * Returns whether or not the axis is analog, or false if it is digital. + */ + public abstract boolean isAnalog(); + + /** + * Returns whether or not data polled from this axis is normalized + * between the values of -1.0f and 1.0f. + * @see #getPollData + */ + public abstract boolean isNormalized(); + + /** + * Returns whether or not this axis is ready to receive polling data. + * @see #getPollData + * @see Controller#poll + * @see #setPolling + */ + public abstract boolean isPolling(); + + /** + * Sets whether or not the axis should receive polling data. + * @see #getPollData + * @see Controller#poll + * @see #isPolling + */ + public abstract void setPolling(boolean polling); + + /** + * Returns the suggested dead zone for this axis. Dead zone is the + * amount polled data can vary before considered a significant change + * in value. An application can safely ignore changes less than this + * value in the positive or negative direction. + * @see #getPollData + */ + public abstract float getDeadZone(); + + /** + * Returns the data from the last time the control has been polled. + * If this axis is a button, the value returned will be either 0.0f or 1.0f. + * If this axis is normalized, the value returned will be between -1.0f and + * 1.0f. + * @see Controller#poll + */ + public abstract float getPollData(); + + /** + * Returns a human-readable name for this axis. + */ + public abstract String getName(); + + /** + * Identifiers for different Axes. + */ + public static class Identifier { + + /** + * Name of axis type + */ + private final String name; + + /** + * Protected constructor + */ + protected Identifier(String name) { + this.name = name; + } + + /** + * Returns a non-localized string description of this axis type. + */ + public String getName() { + return name; + } + + /** + * Returns a non-localized string description of this axis type. + */ + public String toString() { + return name; + } + + /** + * An axis for specifying vertical data. + */ + public static final Identifier X = new Identifier("x"); + + /** + * An axis for specifying horizontal data. + */ + public static final Identifier Y = new Identifier("y"); + + /** + * An axis for specifying third dimensional up/down + * data, or linear data in any direction that is + * neither horizontal nor vertical. + */ + public static final Identifier Z = new Identifier("z"); + + /** + * An axis for specifying left-right rotational data. + */ + public static final Identifier RX = new Identifier("rx"); + + /** + * An axis for specifying forward-back rotational data. + */ + public static final Identifier RY = new Identifier("ry"); + + /** + * An axis for specifying up-down rotational data + * (rudder control). + */ + public static final Identifier RZ = new Identifier("rz"); + + /** + * An axis for a button or key. + */ + public static final Identifier BUTTON = new Identifier("button"); + + /** + * An axis for a slider or mouse wheel. + */ + public static final Identifier SLIDER = new Identifier("slider"); + + /** + * An axis for a point-of-view control. + */ + public static final Identifier POV = new Identifier("pov"); + + /** + * An axis for specifying vertical velocity data. + */ + public static final Identifier X_VELOCITY = + new Identifier("x-velocity"); + + /** + * An axis for specifying horizontal velocity data. + */ + public static final Identifier Y_VELOCITY = + new Identifier("y-velocity"); + + /** + * An axis for specifying third dimensional up/down velocity + * data. + */ + public static final Identifier Z_VELOCITY = + new Identifier("z-velocity"); + + /** + * An axis for specifying left-right angular velocity data. + */ + public static final Identifier RX_VELOCITY = + new Identifier("rx-velocity"); + + /** + * An axis for specifying forward-back angular velocity data. + */ + public static final Identifier RY_VELOCITY = + new Identifier("ry-velocity"); + + /** + * An axis for specifying up-down angular velocity data. + */ + public static final Identifier RZ_VELOCITY = + new Identifier("rz-velocity"); + + /** + * An axis for slider or mouse wheel velocity data. + */ + public static final Identifier SLIDER_VELOCITY = + new Identifier("slider-velocity"); + + /** + * An axis for specifying vertical acceleration data. + */ + public static final Identifier X_ACCELERATION = + new Identifier("x-acceleration"); + + /** + * An axis for specifying horizontal acceleration data. + */ + public static final Identifier Y_ACCELERATION = + new Identifier("y-acceleration"); + + /** + * An axis for specifying third dimensional up/down acceleration + * data. + */ + public static final Identifier Z_ACCELERATION = + new Identifier("z-acceleration"); + + /** + * An axis for specifying left-right angular acceleration data. + */ + public static final Identifier RX_ACCELERATION = + new Identifier("rx-acceleration"); + + /** + * An axis for specifying forward-back angular acceleration data. + */ + public static final Identifier RY_ACCELERATION = + new Identifier("ry-acceleration"); + + /** + * An axis for specifying up-down angular acceleration data. + */ + public static final Identifier RZ_ACCELERATION = + new Identifier("rz-acceleration"); + + /** + * An axis for slider or mouse wheel acceleration data. + */ + public static final Identifier SLIDER_ACCELERATION = + new Identifier("slider-acceleration"); + + /** + * An axis for specifying vertical force data. + */ + public static final Identifier X_FORCE = + new Identifier("x-force"); + + /** + * An axis for specifying horizontal force data. + */ + public static final Identifier Y_FORCE = + new Identifier("y-force"); + + /** + * An axis for specifying third dimensional up/down force + * data. + */ + public static final Identifier Z_FORCE = + new Identifier("z-force"); + + /** + * An axis for specifying left-right angular force (torque) data. + */ + public static final Identifier RX_FORCE = + new Identifier("rx-force"); + + /** + * An axis for specifying forward-back angular force (torque) data. + */ + public static final Identifier RY_FORCE = + new Identifier("ry-force"); + + /** + * An axis for specifying up-down angular force (torque) data. + */ + public static final Identifier RZ_FORCE = + new Identifier("rz-force"); + + /** + * An axis for slider force data. + */ + public static final Identifier SLIDER_FORCE = + new Identifier("slider-force"); + } // class Axis.Identifier + + /** + * POV enum for different positions. + */ + public static class POV { + /** + * Standard value for center HAT position + */ + public static final float OFF = 0.0f; + /** + * Synonmous with OFF + */ + public static final float CENTER = OFF; + /** + * Standard value for up HAT position + */ + public static final float UP = 0.25f; + /** + * Standard value for right HAT position + */ + public static final float RIGHT = 0.50f; + /** + * Standard value for down HAT position + */ + public static final float DOWN = 0.75f; + /** + * Standard value for left HAT position + */ + public static final float LEFT = 1.0f; + } // class Axis.POV +} // interface Axis diff --git a/coreAPI/src/java/net/java/games/input/Controller.java b/coreAPI/src/java/net/java/games/input/Controller.java new file mode 100644 index 0000000..ebf12ee --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/Controller.java @@ -0,0 +1,253 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * A Controller represents a physical device, such as a keyboard, mouse, + * or joystick, or a logical grouping of related controls, such as a button + * pad or mouse ball. A controller can be composed of multiple controllers. + * For example, the ball of a mouse and its buttons are two separate + * controllers. + */ +public interface Controller { + + /** + * Returns the controllers connected to make up this controller, or + * an empty array if this controller contains no child controllers. + * The objects in the array are returned in order of assignment priority + * (primary stick, secondary buttons, etc.). + */ + public abstract Controller[] getControllers(); + + /** + * Returns the type of the Controller. + */ + public abstract Type getType(); + + /** + * Returns the axes on this controller, in order of assignment priority. + * For example, the button controller on a mouse returns an array containing + * the primary or leftmost mouse button, followed by the secondary or + * rightmost mouse button (if present), followed by the middle mouse button + * (if present). + * The array returned is an empty array if this controller contains no axes + * (such as a logical grouping of child controllers). + */ + public abstract Axis[] getAxes(); + + /** + * Returns a single axis based on its type, or null + * if no axis with the specified type could be found. + */ + public abstract Axis getAxis(Axis.Identifier id); + + /** + * Returns the rumblers for sending feedback to this controller, or an + * empty array if there are no rumblers on this controller. + */ + public abstract Rumbler[] getRumblers(); + + /** + * Polls axes for data. Returns false if the controller is no longer valid. + * Polling reflects the current state of the device when polled. + */ + public abstract boolean poll(); + + /** + * Returns the port type for this Controller. + */ + public abstract PortType getPortType(); + + /** + * Returns the zero-based port number for this Controller. + */ + public abstract int getPortNumber(); + + /** + * Returns a human-readable name for this Controller. + */ + public abstract String getName(); + + /** + * Types of controller objects. + */ + public static class Type { + + /** + * Name of controller type + */ + private final String name; + + /** + * Protected constructor + */ + protected Type(String name) { + this.name = name; + } + + /** + * Returns a non-localized string description of this controller type. + */ + public String toString() { + return name; + } + + /** + * Mouse controller. + */ + public static final Type UNKNOWN = new Type("unknown"); + + /** + * Mouse controller. + */ + public static final Type MOUSE = new Type("mouse"); + + /** + * A mouse ball or the ball part of a trackball controller. + * Note that a mouse wheel is considered part of a ball controller. + */ + public static final Type BALL = new Type("ball"); + + /** + * A group of buttons on a pad (mouse buttons, for + * example) or a keyboard. + */ + public static final Type BUTTONS = new Type("buttons"); + /** + * A keyboard controller (same as BUTTONS) + * @see #BUTTONS + */ + public static final Type KEYBOARD = BUTTONS; + + /** + * Fingerstick controller; note that this may be sometimes treated as a + * type of mouse or stick. + */ + public static final Type FINGERSTICK = new Type("fingerstick"); + + /** + * Gamepad controller. + */ + public static final Type GAMEPAD = new Type("gamepad"); + + /** + * Headtracker controller. + */ + public static final Type HEADTRACKER = new Type("headtracker"); + + /** + * Rudder controller. + */ + public static final Type RUDDER = new Type("rudder"); + + /** + * Stick controller, such as a joystick or flightstick. + */ + public static final Type STICK = new Type("stick"); + + /** + * A trackball controller; note that this may sometimes be treated as a + * type of mouse. + */ + public static final Type TRACKBALL = new Type("trackball"); + + /** + * A trackpad, such as a tablet, touchpad, or glidepad; + * note that this may sometimes be treated as a type of mouse. + */ + public static final Type TRACKPAD = new Type("trackpad"); + + /** + * A wheel controller, such as a steering wheel (note + * that a mouse wheel is considered part of a ball control, not a + * wheel controller). + */ + public static final Type WHEEL = new Type("wheel"); + } // class Controller.Type + + /** + * Common controller port types. + */ + public static final class PortType { + + /** + * Name of port type + */ + private final String name; + + /** + * Protected constructor + */ + protected PortType(String name) { + this.name = name; + } + + /** + * Returns a non-localized string description of this port type. + */ + public String toString() { + return name; + } + + /** + * Unknown port type + */ + public static final PortType UNKNOWN = new PortType("Unknown"); + + /** + * USB port + */ + public static final PortType USB = new PortType("USB port"); + + /** + * Standard game port + */ + public static final PortType GAME = new PortType("Game port"); + + /** + * Network port + */ + public static final PortType NETWORK = new PortType("Network port"); + + /** + * Serial port + */ + public static final PortType SERIAL = new PortType("Serial port"); + } // class Controller.PortType +} // interface Controller diff --git a/coreAPI/src/java/net/java/games/input/ControllerEnvironment.java b/coreAPI/src/java/net/java/games/input/ControllerEnvironment.java new file mode 100644 index 0000000..d58ed4e --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/ControllerEnvironment.java @@ -0,0 +1,140 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.util.ArrayList; +import java.util.Iterator; + +/** + * A ControllerEnvironment represents a collection of controllers that are + * physically or logically linked. By default, this corresponds to the + * environment for the local machine. + * <p> + * In this reference implementation, this class can also be used to register + * controllers with the default environment as "plug-ins". A plug-in is + * created by subclassing ControllerEnvironment with a class that has a public + * no-argument constructor, implements the org.java.games.util.plugins.Plugin + * interface and has a name ending in "Plugin". + * (See org.java.games.input.DirectInputEnvironmentPlugin in the DXplugin + * part of the source tree for an example.) + * + * When the DefaultControllerEnvrionment is instanced it uses the plugin library + * to look for Plugins in both [java.home]/lib/controller and + * [user.dir]/controller. This allows controller plugins to be installed either + * globally for the entire Java environment or locally for just one particular + * Java app. + * + * For more information on the organization of plugins within the controller + * root directories, see org.java.games.util.plugins.Plugins (Note the + * plural -- "Plugins" not "Plugin" which is just a marker interface.) + * + */ +public abstract class ControllerEnvironment { + + /** + * The default controller environment + */ + private static ControllerEnvironment defaultEnvironment = + new DefaultControllerEnvironment(); + + /** + * List of controller listeners + */ + protected final ArrayList controllerListeners = new ArrayList(); + + /** + * Protected constructor for subclassing. + */ + protected ControllerEnvironment() { + } + + /** + * Returns a list of all controllers available to this environment, + * or an empty array if there are no controllers in this environment. + */ + public abstract Controller[] getControllers(); + + /** + * Adds a listener for controller state change events. + */ + public void addControllerListener(ControllerListener l) { + assert l != null; + controllerListeners.add(l); + } + + /** + * Removes a listener for controller state change events. + */ + public void removeControllerListener(ControllerListener l) { + assert l != null; + controllerListeners.remove(l); + } + + /** + * Creates and sends an event to the controller listeners that a controller + * has been added. + */ + protected void fireControllerAdded(Controller c) { + ControllerEvent ev = new ControllerEvent(c); + Iterator it = controllerListeners.iterator(); + while (it.hasNext()) { + ((ControllerListener)it.next()).controllerAdded(ev); + } + } + + /** + * Creates and sends an event to the controller listeners that a controller + * has been lost. + */ + protected void fireControllerRemoved(Controller c) { + ControllerEvent ev = new ControllerEvent(c); + Iterator it = controllerListeners.iterator(); + while (it.hasNext()) { + ((ControllerListener)it.next()).controllerRemoved(ev); + } + } + + /** + * Returns the default environment for input controllers. + * This usually corresponds to the environment for the local machine. + */ + public static ControllerEnvironment getDefaultEnvironment() { + return defaultEnvironment; + } +} // ControllerEnvironment diff --git a/coreAPI/src/java/net/java/games/input/ControllerEvent.java b/coreAPI/src/java/net/java/games/input/ControllerEvent.java new file mode 100644 index 0000000..14fbbcd --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/ControllerEvent.java @@ -0,0 +1,61 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * An event that is fired when the state of a controller changes + */ +public class ControllerEvent { + + private Controller controller; + + /** + * Creates a controller event object. + */ + public ControllerEvent(Controller c) { + controller = c; + } + + /** + * Returns the controller for this event. + */ + public Controller getController() { + return controller; + } +} // class ControllerEvent diff --git a/coreAPI/src/java/net/java/games/input/ControllerListener.java b/coreAPI/src/java/net/java/games/input/ControllerListener.java new file mode 100644 index 0000000..8c58eff --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/ControllerListener.java @@ -0,0 +1,55 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * A listener for changes in the state of controllers + */ +public interface ControllerListener { + + /** + * Invoked when a controller is lost. + */ + public abstract void controllerRemoved(ControllerEvent ev); + + /** + * Invoked when a controller has been added. + */ + public abstract void controllerAdded(ControllerEvent ev); +} // interface ControllerListener diff --git a/coreAPI/src/java/net/java/games/input/DefaultControllerEnvironment.java b/coreAPI/src/java/net/java/games/input/DefaultControllerEnvironment.java new file mode 100644 index 0000000..e72aeae --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/DefaultControllerEnvironment.java @@ -0,0 +1,232 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Properties; +import net.java.games.util.plugins.*; + +/** + * The default controller environment. + * + * @version %I% %G% + * @author Michael Martak + */ +class DefaultControllerEnvironment extends ControllerEnvironment { + static final boolean DEBUG =false; + /** + * The name of the properties file to find plugins. + */ + private final static String PROPERTY_FILENAME = + "controller.properties"; + + /** + * The name of the property for identifying a plugin (used + * as the value, the key being the class name). + */ + private final static String ID_PLUGIN = + "ControllerEnvironment"; + + /** + * Location of the LIB directory. + */ + static String libPath; + + /** + * List of all controllers in this environment + */ + private ArrayList controllers; + + /** + * Plug-in properties. + */ + private Properties properties = new Properties(); + + /** + * Plug-in class loader. + */ + private PluginClassLoader pluginLoader = new PluginClassLoader(); + + /** + * Public no-arg constructor. + */ + public DefaultControllerEnvironment() { + } + + /** + * Returns a list of all controllers available to this environment, + * or an empty array if there are no controllers in this environment. + */ + public Controller[] getControllers() { + if (controllers == null) { + // Controller list has not been scanned. + controllers = new ArrayList(); + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + scanControllers(); + return DefaultControllerEnvironment.this; + } + }); + } + Controller[] ret = new Controller[controllers.size()]; + Iterator it = controllers.iterator(); + int i = 0; + while (it.hasNext()) { + ret[i] = (Controller)it.next(); + i++; + } + return ret; + } + + /** + * Scans for controllers, placing them in the controllers list. + */ + /* This is Mike's old plugin code. + private void scanControllers() { + // Load properties object. + try { + loadProperties(); + } catch (IOException e) { + // Could not find or read file, simply return. + return; + } + // Create a list of ControllerEnvironment classes. + // For each ControllerEnvironment, locate the class + // using the plugin class loader. + Iterator it = properties.keySet().iterator(); + while (it.hasNext()) { + Object key = it.next(); + assert key != null; + Object value = properties.get(key); + assert value != null; + if (value.equals(ID_PLUGIN)) { + try { + ControllerEnvironment plugin = + newPlugin(key.toString()); + addControllers(plugin.getControllers()); + } catch (Throwable t) { + System.err.println( + "Warning : could not load plugin " + + key.toString() + ", received exeption " + + t.toString()); + t.printStackTrace(System.err); + } + } + } + }*/ + + /* This is jeff's new plugin code using Jeff's Plugin manager */ + private void scanControllers() { + scanControllersAt(System.getProperty("java.home") + + File.separator + "lib"+File.separator+"controller"); + scanControllersAt(System.getProperty("user.dir")+ + File.separator+ "controller"); + } + + private void scanControllersAt(String path) { + try { + Plugins plugins = new Plugins(new File(path)); + Class[] envClasses = plugins.getExtends(ControllerEnvironment.class); + for(int i=0;i<envClasses.length;i++){ + try { + if (DEBUG) { + System.out.println("ControllerEnvironment "+ + envClasses[i].getName() + +" loaded by "+envClasses[i].getClassLoader()); + } + ControllerEnvironment ce = (ControllerEnvironment) + envClasses[i].newInstance(); + addControllers(ce.getControllers()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Retrieve the file "lib/control.properties" and + * load properties into properties object. + */ + private void loadProperties() throws IOException { + if (libPath == null) { + libPath = System.getProperty("java.home") + + File.separator + "lib"; + } + File file = new File(libPath + File.separator + + PROPERTY_FILENAME); + FileInputStream inputStream = new FileInputStream(file); + properties.load(inputStream); + inputStream.close(); + } + + /** + * Create a new plugin ControllerEnvironment object + */ + /* + private ControllerEnvironment newPlugin(String name) throws + ClassNotFoundException, InstantiationException, + IllegalAccessException { + Class pluginClass = pluginLoader.loadClass(name); + if (!ControllerEnvironment.class.isAssignableFrom(pluginClass)) { + throw new ClassCastException( + "Plugin class must be assignable from " + + ControllerEnvironment.class.getName()); + } + Object instance = pluginClass.newInstance(); + return (ControllerEnvironment)instance; + } + */ + /** + * Add the array of controllers to our list of controllers. + */ + private void addControllers(Controller[] c) { + for (int i = 0; i < c.length; i++) { + controllers.add(c[i]); + } + } +} diff --git a/coreAPI/src/java/net/java/games/input/Keyboard.java b/coreAPI/src/java/net/java/games/input/Keyboard.java new file mode 100644 index 0000000..92361af --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/Keyboard.java @@ -0,0 +1,168 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * A Keyboard is a type of controller consisting of a single controller, + * they keypad, which contains several axes (the keys). By default, all keys + * are set to receive polling data. + */ +public abstract class Keyboard extends AbstractController { + + /** + * Protected constructor. + * Subclasses should initialize the array of axes to an array of keys. + * @param name The name of the keyboard + */ + protected Keyboard(String name) { + super(name); + } + + /** + * Returns the type of the Controller. + */ + public Type getType() { + return Type.KEYBOARD; + } + + /** + * Returns the axis corresponding to a particular key on the keypad, + * or null if a key with the specified ID could not be found. + */ + public Axis getAxis(Axis.Identifier id) { + assert axes != null; + // Default implementation uses indices to lookup keys + // in the array of axes + if (id instanceof KeyID) { + KeyID kid = (KeyID)id; + int index = kid.getKeyIndex(); + assert axes.length > index; + return axes[index]; + } + return null; + } + + /** + * Returns whether or not the given key has been pressed since the last + * call to poll. This is called from a key's getPollData method. + */ + protected abstract boolean isKeyPressed(Key key); + + /** + * Axis representing a single key. By default, all keys are set to receive + * polling data. + */ + public class Key extends AbstractAxis { + + /** + * Key identifier + */ + private final KeyID keyID; + + /** + * Construct a new key object + */ + public Key(KeyID keyID) { + super(keyID.toString(), keyID); + this.keyID = keyID; + } + + /** + * Returns <code>true</code> if data returned from <code>poll</code> + * is relative to the last call, or <code>false</code> if data + * is absolute. + * @return false by default, can be overridden + */ + public final boolean isRelative() { + return false; + } + + /** + * Returns the data from the last time the control has been polled. + * The value returned will be either 0.0f or 1.0f. The result is always + * 0.0f if polling is turned off. + */ + public float getPollData() { + if (!isPolling()) { + return 0.0f; + } + return (isKeyPressed(this) ? 1.0f : 0.0f); + } + } // class Keyboard.Key + + /** + * Identifiers for physical keys. + */ + public static class KeyID extends Axis.Identifier { + + /** + * Key string + */ + private static final String NAME_KEY = "key"; + + /** + * Index in the array of axes supplied to the keyboard contructor for + * this key. + */ + protected final int keyIndex; + + /** + * Protected constructor + * @param keyIndex the index for looking up the key in the array of axes + */ + protected KeyID(int keyIndex) { + super(NAME_KEY); + this.keyIndex = keyIndex; + } + + /** + * The index for this key for looking up the in the array of axes. + */ + public int getKeyIndex() { + return keyIndex; + } + + /** + * Returns a non-localized string description of this control type. + */ + public String toString() { + return super.toString() + " " + Integer.toString(keyIndex); + } + } // class Keyboard.KeyID +} // class Keyboard diff --git a/coreAPI/src/java/net/java/games/input/Mouse.java b/coreAPI/src/java/net/java/games/input/Mouse.java new file mode 100644 index 0000000..6029834 --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/Mouse.java @@ -0,0 +1,315 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * A Mouse is a type of controller consisting of two child controllers, + * a ball and a button pad. This includes devices such as touch pads, + * trackballs, and fingersticks. + */ +public abstract class Mouse extends AbstractController { + + /** + * Mouse ball; should be initialized by subclasses + */ + protected Ball ball; + + /** + * Mouse buttons; should be initialized by subclasses + */ + protected Buttons buttons; + + /** + * Protected constructor; + * Subclasses should initialize the ball and buttons + */ + protected Mouse(String name) { + super(name); + } + + /** + * Returns the controllers connected to make up this controller, or + * an empty array if this controller contains no child controllers. + * The objects in the array are returned in order of assignment priority + * (primary stick, secondary buttons, etc.). + */ + public Controller[] getControllers() { + if (children.length == 0 && ball != null && buttons != null) { + children = new Controller[] { ball, buttons }; + } + return children; + } + + /** + * Returns the control for the ball of the mouse, never null. + */ + public Ball getBall() { + return ball; + } + + /** + * Returns the control for the buttons of the mouse, never null. + */ + public Buttons getButtons() { + return buttons; + } + + /** + * Returns the type of the Controller. + */ + public Type getType() { + return Type.MOUSE; + } + + /** + * Mouse ball controller + */ + public abstract class Ball extends AbstractController { + + /** + * X-axis; should be initialized by subclasses + */ + protected Axis x; + + /** + * Y-axis; should be initialized by subclasses + */ + protected Axis y; + + /** + * Mouse wheel; should be initialized by subclasses + */ + protected Axis wheel; + + /** + * Protected constructor + */ + protected Ball(String name) { + super(name); + } + + /** + * Returns the type of Controller. + */ + public Type getType() { + return Type.BALL; + } + + /** + * Returns the x-axis for the mouse ball, never null. + */ + public Axis getX() { + return x; + } + + /** + * Returns the y-axis for the mouse ball, never null. + */ + public Axis getY() { + return y; + } + + /** + * Returns the mouse wheel, or null if no mouse wheel is present. + */ + public Axis getWheel() { + return wheel; + } + + /** + * Returns the axes on this controller, in order of assignment priority. + * Overridden to return the x-axis, followed by the y-axes, followed by + * the wheel (if present). + * The array returned is an empty array if this controller contains no + * axes (such as a logical grouping of child controllers). + */ + public Axis[] getAxes() { + if (axes.length == 0 && x != null && y != null) { + if (wheel == null) { + axes = new Axis[] { x, y }; + } else { + axes = new Axis[] { x, y, wheel }; + } + } + return axes; + } + + /** + * Polls axes for data. Returns false if the controller is no longer + * valid. Polling reflects the current state of the device when polled. + * By default, polling a mouse ball or button polls the entire mouse + * control. + */ + public boolean poll() { + return Mouse.this.poll(); + } + } // class Mouse.Ball + + /** + * Mouse buttons controller + */ + public abstract class Buttons extends AbstractController { + + /** + * Left button; should be initialized by subclasses + */ + protected Button left; + + /** + * Right button; should be initialized by subclasses + */ + protected Button right; + + /** + * Middle button; should be initialized by subclasses + */ + protected Button middle; + + /** + * Protected constructor + */ + protected Buttons(String name) { + super(name); + } + + /** + * Returns the type or identifier of the Controller. + */ + public Type getType() { + return Type.BUTTONS; + } + + /** + * Returns the left or primary mouse button, never null. + */ + public Button getLeft() { + return left; + } + + /** + * Returns the right or secondary mouse button, null if the mouse is + * a single-button mouse. + */ + public Button getRight() { + return right; + } + + /** + * Returns the middle or tertiary mouse button, null if the mouse has + * fewer than three buttons. + */ + public Button getMiddle() { + return middle; + } + + /** + * Returns the axes on this controller, in order of assignment priority. + * Overridden to return the the primary or leftmost mouse button, + * followed by the secondary or rightmost mouse button (if present), + * followed by the middle mouse button (if present). + * The array returned is an empty array if this controller contains no + * axes (such as a logical grouping of child controllers). + */ + public Axis[] getAxes() { + if (axes.length == 0 && left != null) { + if (right == null) { + axes = new Axis[] { left }; + } else if (middle == null) { + axes = new Axis[] { left, right }; + } else { + axes = new Axis[] { left, right, middle }; + } + } + return axes; + } + + /** + * Polls axes for data. Returns false if the controller is no longer + * valid. Polling reflects the current state of the device when polled. + * By default, polling a mouse ball or button polls the entire mouse + * control. + */ + public boolean poll() { + return Mouse.this.poll(); + } + } // class Mouse.Buttons + + /** + * Mouse button axis + */ + public abstract class Button extends AbstractAxis { + + /** + * Protected constructor + */ + protected Button(String name, ButtonID id) { + super(name, id); + } + } // class Mouse.Button + + /** + * Identifier for types of mouse buttons + */ + public static class ButtonID extends Axis.Identifier { + + /** + * Protected constructor + */ + protected ButtonID(String name) { + super(name); + } + + /** + * The primary or leftmost mouse button. + */ + public static final ButtonID LEFT = new ButtonID("left"); + + /** + * The secondary or rightmost mouse button, not present if + * the mouse is a single-button mouse. + */ + public static final ButtonID RIGHT = new ButtonID("right"); + + /** + * Returns the middle mouse button, not present if the + * mouse has fewer than three buttons. + */ + public static final ButtonID MIDDLE = new ButtonID("middle"); + } // class Mouse.ButtonID +} // class Mouse diff --git a/coreAPI/src/java/net/java/games/input/PluginClassLoader.java b/coreAPI/src/java/net/java/games/input/PluginClassLoader.java new file mode 100644 index 0000000..13c580f --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/PluginClassLoader.java @@ -0,0 +1,175 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * Loads all plugins. + * + * @version %I% %G% + * @author Michael Martak + */ +class PluginClassLoader extends ClassLoader { + + /** + * Location of directory to look for plugins + */ + private static String pluginDirectory; + + /** + * File filter for JAR files + */ + private static final FileFilter JAR_FILTER = new JarFileFilter(); + + /** + * Create a new class loader for loading plugins + */ + public PluginClassLoader() { + super(Thread.currentThread().getContextClassLoader()); + } + + /** + * Overrides findClass to first look in the parent class loader, + * then try loading the class from the plugin file system. + */ + protected Class findClass(String name) + throws ClassNotFoundException { + // Try loading the class from the file system. + byte[] b = loadClassData(name); + return defineClass(name, b, 0, b.length); + } + + /** + * Load the class data from the file system + */ + private byte[] loadClassData(String name) + throws ClassNotFoundException { + if (pluginDirectory == null) { + pluginDirectory = DefaultControllerEnvironment.libPath + + File.separator + "controller"; + } + try { + return loadClassFromDirectory(name); + } catch (Exception e) { + try { + return loadClassFromJAR(name); + } catch (IOException e2) { + throw new ClassNotFoundException(name, e2); + } + } + } + + /** + * Load the class data from the file system based on parsing + * the class name (packages). + */ + private byte[] loadClassFromDirectory(String name) + throws ClassNotFoundException, IOException { + // Parse the class name into package directories. + // Look for the class in the plugin directory. + StringTokenizer tokenizer = new StringTokenizer(name, "."); + StringBuffer path = new StringBuffer(pluginDirectory); + while (tokenizer.hasMoreTokens()) { + path.append(File.separator); + path.append(tokenizer.nextToken()); + } + path.append(".class"); + File file = new File(path.toString()); + if (!file.exists()) { + throw new ClassNotFoundException(name); + } + FileInputStream fileInputStream = new FileInputStream(file); + assert file.length() <= Integer.MAX_VALUE; + int length = (int)file.length(); + byte[] bytes = new byte[length]; + int length2 = fileInputStream.read(bytes); + assert length == length2; + return bytes; + } + + /** + * Scans through the plugin directory for JAR files and + * attempts to load the class data from each JAR file. + */ + private byte[] loadClassFromJAR(String name) + throws ClassNotFoundException, IOException { + File dir = new File(pluginDirectory); + File[] jarFiles = dir.listFiles(JAR_FILTER); + if (jarFiles == null) { + throw new ClassNotFoundException("Could not find class " + name); + } + for (int i = 0; i < jarFiles.length; i++) { + JarFile jarfile = new JarFile(jarFiles[i]); + JarEntry jarentry = jarfile.getJarEntry(name + ".class"); + if (jarentry != null) { + InputStream jarInputStream = jarfile.getInputStream(jarentry); + assert jarentry.getSize() <= Integer.MAX_VALUE; + int length = (int)jarentry.getSize(); + assert length >= 0; + byte[] bytes = new byte[length]; + int length2 = jarInputStream.read(bytes); + assert length == length2; + return bytes; + } + } + throw new FileNotFoundException(name); + } + + /** + * Filters out all non-JAR files, based on whether or not they + * end in ".JAR" (case-insensitive). + */ + private static class JarFileFilter implements FileFilter { + public boolean accept(File file) { + return file.getName().toUpperCase().endsWith(".JAR"); + } + } +} + diff --git a/coreAPI/src/java/net/java/games/input/Rumbler.java b/coreAPI/src/java/net/java/games/input/Rumbler.java new file mode 100644 index 0000000..2d4c8b8 --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/Rumbler.java @@ -0,0 +1,52 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * A Rumbler is a controller's mechanism for delivering feedback + * to the user through the device. + */ +public interface Rumbler { + + /** + * Rumble with the specified intensity. + */ + public abstract void rumble(float intensity); + +} // interface Rumbler diff --git a/coreAPI/src/java/net/java/games/input/StandardKeyboard.java b/coreAPI/src/java/net/java/games/input/StandardKeyboard.java new file mode 100644 index 0000000..5dc891a --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/StandardKeyboard.java @@ -0,0 +1,261 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * Identifiers for physical keys for standard PC (LATIN-1) keyboards. + */ +public abstract class StandardKeyboard extends Keyboard { + + private Key[] standardKeys = { + new Key(KeyID.VOID ), new Key(KeyID.ESCAPE ), + new Key(KeyID._1 ), new Key(KeyID._2 ), + new Key(KeyID._3 ), new Key(KeyID._4 ), + new Key(KeyID._5 ), new Key(KeyID._6 ), + new Key(KeyID._7 ), new Key(KeyID._8 ), + new Key(KeyID._9 ), new Key(KeyID._0 ), + new Key(KeyID.MINUS ), new Key(KeyID.EQUALS ), + new Key(KeyID.BACK ), new Key(KeyID.TAB ), + new Key(KeyID.Q ), new Key(KeyID.W ), + new Key(KeyID.E ), new Key(KeyID.R ), + new Key(KeyID.T ), new Key(KeyID.Y ), + new Key(KeyID.U ), new Key(KeyID.I ), + new Key(KeyID.O ), new Key(KeyID.P ), + new Key(KeyID.LBRACKET ), new Key(KeyID.RBRACKET ), + new Key(KeyID.RETURN ), new Key(KeyID.LCONTROL ), + new Key(KeyID.A ), new Key(KeyID.S ), + new Key(KeyID.D ), new Key(KeyID.F ), + new Key(KeyID.G ), new Key(KeyID.H ), + new Key(KeyID.J ), new Key(KeyID.K ), + new Key(KeyID.L ), new Key(KeyID.SEMICOLON ), + new Key(KeyID.APOSTROPHE ), new Key(KeyID.GRAVE ), + new Key(KeyID.LSHIFT ), new Key(KeyID.BACKSLASH ), + new Key(KeyID.Z ), new Key(KeyID.X ), + new Key(KeyID.C ), new Key(KeyID.V ), + new Key(KeyID.B ), new Key(KeyID.N ), + new Key(KeyID.M ), new Key(KeyID.COMMA ), + new Key(KeyID.PERIOD ), new Key(KeyID.SLASH ), + new Key(KeyID.RSHIFT ), new Key(KeyID.MULTIPLY ), + new Key(KeyID.LALT ), new Key(KeyID.SPACE ), + new Key(KeyID.CAPITAL ), new Key(KeyID.F1 ), + new Key(KeyID.F2 ), new Key(KeyID.F3 ), + new Key(KeyID.F4 ), new Key(KeyID.F5 ), + new Key(KeyID.F6 ), new Key(KeyID.F7 ), + new Key(KeyID.F8 ), new Key(KeyID.F9 ), + new Key(KeyID.F10 ), new Key(KeyID.NUMLOCK ), + new Key(KeyID.SCROLL ), new Key(KeyID.NUMPAD7 ), + new Key(KeyID.NUMPAD8 ), new Key(KeyID.NUMPAD9 ), + new Key(KeyID.SUBTRACT ), new Key(KeyID.NUMPAD4 ), + new Key(KeyID.NUMPAD5 ), new Key(KeyID.NUMPAD6 ), + new Key(KeyID.ADD ), new Key(KeyID.NUMPAD1 ), + new Key(KeyID.NUMPAD2 ), new Key(KeyID.NUMPAD3 ), + new Key(KeyID.NUMPAD0 ), new Key(KeyID.DECIMAL ), + new Key(KeyID.F11 ), new Key(KeyID.F12 ), + new Key(KeyID.F13 ), new Key(KeyID.F14 ), + new Key(KeyID.F15 ), new Key(KeyID.KANA ), + new Key(KeyID.CONVERT ), new Key(KeyID.NOCONVERT ), + new Key(KeyID.YEN ), new Key(KeyID.NUMPADEQUAL), + new Key(KeyID.CIRCUMFLEX ), new Key(KeyID.AT ), + new Key(KeyID.COLON ), new Key(KeyID.UNDERLINE ), + new Key(KeyID.KANJI ), new Key(KeyID.STOP ), + new Key(KeyID.AX ), new Key(KeyID.UNLABELED ), + new Key(KeyID.NUMPADENTER), new Key(KeyID.RCONTROL ), + new Key(KeyID.NUMPADCOMMA), new Key(KeyID.DIVIDE ), + new Key(KeyID.SYSRQ ), new Key(KeyID.RALT ), + new Key(KeyID.PAUSE ), new Key(KeyID.HOME ), + new Key(KeyID.UP ), new Key(KeyID.PRIOR ), + new Key(KeyID.LEFT ), new Key(KeyID.RIGHT ), + new Key(KeyID.END ), new Key(KeyID.DOWN ), + new Key(KeyID.NEXT ), new Key(KeyID.INSERT ), + new Key(KeyID.DELETE ), new Key(KeyID.LWIN ), + new Key(KeyID.RWIN ), new Key(KeyID.APPS ), + new Key(KeyID.POWER ), new Key(KeyID.SLEEP ), + }; + + /** + * Creates a new standard keyboard object with the default keys + * for a standard keyboard. + */ + protected StandardKeyboard(String name) { + super(name); + axes = standardKeys; + } + + /** + * KeyIDs for standard PC (LATIN-1) keyboards + */ + public static class KeyID extends Keyboard.KeyID { + /** + * Protected constructor + */ + protected KeyID(int keyID) { + super(keyID); + } + /** + * Standard keyboard (LATIN-1) keys + * UNIX X11 keysym values are listed to the right + */ + public static final KeyID VOID = new KeyID(0); // MS 0x00 UNIX 0xFFFFFF + public static final KeyID ESCAPE = new KeyID(1); // MS 0x01 UNIX 0xFF1B + public static final KeyID _1 = new KeyID(2); // MS 0x02 UNIX 0x031 EXCLAM 0x021 + public static final KeyID _2 = new KeyID(3); // MS 0x03 UNIX 0x032 AT 0x040 + public static final KeyID _3 = new KeyID(4); // MS 0x04 UNIX 0x033 NUMBERSIGN 0x023 + public static final KeyID _4 = new KeyID(5); // MS 0x05 UNIX 0x034 DOLLAR 0x024 + public static final KeyID _5 = new KeyID(6); // MS 0x06 UNIX 0x035 PERCENT 0x025 + public static final KeyID _6 = new KeyID(7); // MS 0x07 UNIX 0x036 CIRCUMFLEX 0x05e + public static final KeyID _7 = new KeyID(8); // MS 0x08 UNIX 0x037 AMPERSAND 0x026 + public static final KeyID _8 = new KeyID(9); // MS 0x09 UNIX 0x038 ASTERISK 0x02a + public static final KeyID _9 = new KeyID(10); // MS 0x0A UNIX 0x039 PARENLEFT 0x028 + public static final KeyID _0 = new KeyID(11); // MS 0x0B UNIX 0x030 PARENRIGHT 0x029 + public static final KeyID MINUS = new KeyID(12); // MS 0x0C UNIX 0x02d UNDERSCORE 0x05f + public static final KeyID EQUALS = new KeyID(13); // MS 0x0D UNIX 0x03d PLUS 0x02b + public static final KeyID BACK = new KeyID(14); // MS 0x0E UNIX 0xFF08 + public static final KeyID TAB = new KeyID(15); // MS 0x0F UNIX 0xFF09 + public static final KeyID Q = new KeyID(16); // MS 0x10 UNIX 0x071 UPPER 0x051 + public static final KeyID W = new KeyID(17); // MS 0x11 UNIX 0x077 UPPER 0x057 + public static final KeyID E = new KeyID(18); // MS 0x12 UNIX 0x065 UPPER 0x045 + public static final KeyID R = new KeyID(19); // MS 0x13 UNIX 0x072 UPPER 0x052 + public static final KeyID T = new KeyID(20); // MS 0x14 UNIX 0x074 UPPER 0x054 + public static final KeyID Y = new KeyID(21); // MS 0x15 UNIX 0x079 UPPER 0x059 + public static final KeyID U = new KeyID(22); // MS 0x16 UNIX 0x075 UPPER 0x055 + public static final KeyID I = new KeyID(23); // MS 0x17 UNIX 0x069 UPPER 0x049 + public static final KeyID O = new KeyID(24); // MS 0x18 UNIX 0x06F UPPER 0x04F + public static final KeyID P = new KeyID(25); // MS 0x19 UNIX 0x070 UPPER 0x050 + public static final KeyID LBRACKET = new KeyID(26); // MS 0x1A UNIX 0x05b BRACE 0x07b + public static final KeyID RBRACKET = new KeyID(27); // MS 0x1B UNIX 0x05d BRACE 0x07d + public static final KeyID RETURN = new KeyID(28); // MS 0x1C UNIX 0xFF0D + public static final KeyID LCONTROL = new KeyID(29); // MS 0x1D UNIX 0xFFE3 + public static final KeyID A = new KeyID(30); // MS 0x1E UNIX 0x061 UPPER 0x041 + public static final KeyID S = new KeyID(31); // MS 0x1F UNIX 0x073 UPPER 0x053 + public static final KeyID D = new KeyID(32); // MS 0x20 UNIX 0x064 UPPER 0x044 + public static final KeyID F = new KeyID(33); // MS 0x21 UNIX 0x066 UPPER 0x046 + public static final KeyID G = new KeyID(34); // MS 0x22 UNIX 0x067 UPPER 0x047 + public static final KeyID H = new KeyID(35); // MS 0x23 UNIX 0x068 UPPER 0x048 + public static final KeyID J = new KeyID(36); // MS 0x24 UNIX 0x06A UPPER 0x04A + public static final KeyID K = new KeyID(37); // MS 0x25 UNIX 0x06B UPPER 0x04B + public static final KeyID L = new KeyID(38); // MS 0x26 UNIX 0x06C UPPER 0x04C + public static final KeyID SEMICOLON = new KeyID(39); // MS 0x27 UNIX 0x03b COLON 0x03a + public static final KeyID APOSTROPHE = new KeyID(40); // MS 0x28 UNIX 0x027 QUOTEDBL 0x022 + public static final KeyID GRAVE = new KeyID(41); // MS 0x29 UNIX 0x060 TILDE 0x07e + public static final KeyID LSHIFT = new KeyID(42); // MS 0x2A UNIX 0xFFE1 + public static final KeyID BACKSLASH = new KeyID(43); // MS 0x2B UNIX 0x05c BAR 0x07c + public static final KeyID Z = new KeyID(44); // MS 0x2C UNIX 0x07A UPPER 0x05A + public static final KeyID X = new KeyID(45); // MS 0x2D UNIX 0x078 UPPER 0x058 + public static final KeyID C = new KeyID(46); // MS 0x2E UNIX 0x063 UPPER 0x043 + public static final KeyID V = new KeyID(47); // MS 0x2F UNIX 0x076 UPPER 0x056 + public static final KeyID B = new KeyID(48); // MS 0x30 UNIX 0x062 UPPER 0x042 + public static final KeyID N = new KeyID(49); // MS 0x31 UNIX 0x06E UPPER 0x04E + public static final KeyID M = new KeyID(50); // MS 0x32 UNIX 0x06D UPPER 0x04D + public static final KeyID COMMA = new KeyID(51); // MS 0x33 UNIX 0x02c LESS 0x03c + public static final KeyID PERIOD = new KeyID(52); // MS 0x34 UNIX 0x02e GREATER 0x03e + public static final KeyID SLASH = new KeyID(53); // MS 0x35 UNIX 0x02f QUESTION 0x03f + public static final KeyID RSHIFT = new KeyID(54); // MS 0x36 UNIX 0xFFE2 + public static final KeyID MULTIPLY = new KeyID(55); // MS 0x37 UNIX 0xFFAA + public static final KeyID LALT = new KeyID(56); // MS 0x38 UNIX 0xFFE9 + public static final KeyID SPACE = new KeyID(57); // MS 0x39 UNIX 0x020 + public static final KeyID CAPITAL = new KeyID(58); // MS 0x3A UNIX 0xFFE5 SHIFTLOCK 0xFFE6 + public static final KeyID F1 = new KeyID(59); // MS 0x3B UNIX 0xFFBE + public static final KeyID F2 = new KeyID(60); // MS 0x3C UNIX 0xFFBF + public static final KeyID F3 = new KeyID(61); // MS 0x3D UNIX 0xFFC0 + public static final KeyID F4 = new KeyID(62); // MS 0x3E UNIX 0xFFC1 + public static final KeyID F5 = new KeyID(63); // MS 0x3F UNIX 0xFFC2 + public static final KeyID F6 = new KeyID(64); // MS 0x40 UNIX 0xFFC3 + public static final KeyID F7 = new KeyID(65); // MS 0x41 UNIX 0xFFC4 + public static final KeyID F8 = new KeyID(66); // MS 0x42 UNIX 0xFFC5 + public static final KeyID F9 = new KeyID(67); // MS 0x43 UNIX 0xFFC6 + public static final KeyID F10 = new KeyID(68); // MS 0x44 UNIX 0xFFC7 + public static final KeyID NUMLOCK = new KeyID(69); // MS 0x45 UNIX 0xFF7F + public static final KeyID SCROLL = new KeyID(70); // MS 0x46 UNIX 0xFF14 + public static final KeyID NUMPAD7 = new KeyID(71); // MS 0x47 UNIX 0xFFB7 HOME 0xFF95 + public static final KeyID NUMPAD8 = new KeyID(72); // MS 0x48 UNIX 0xFFB8 UP 0xFF97 + public static final KeyID NUMPAD9 = new KeyID(73); // MS 0x49 UNIX 0xFFB9 PRIOR 0xFF9A + public static final KeyID SUBTRACT = new KeyID(74); // MS 0x4A UNIX 0xFFAD + public static final KeyID NUMPAD4 = new KeyID(75); // MS 0x4B UNIX 0xFFB4 LEFT 0xFF96 + public static final KeyID NUMPAD5 = new KeyID(76); // MS 0x4C UNIX 0xFFB5 + public static final KeyID NUMPAD6 = new KeyID(77); // MS 0x4D UNIX 0xFFB6 RIGHT 0xFF98 + public static final KeyID ADD = new KeyID(78); // MS 0x4E UNIX 0xFFAB + public static final KeyID NUMPAD1 = new KeyID(79); // MS 0x4F UNIX 0xFFB1 END 0xFF9C + public static final KeyID NUMPAD2 = new KeyID(80); // MS 0x50 UNIX 0xFFB2 DOWN 0xFF99 + public static final KeyID NUMPAD3 = new KeyID(81); // MS 0x51 UNIX 0xFFB3 NEXT 0xFF9B + public static final KeyID NUMPAD0 = new KeyID(82); // MS 0x52 UNIX 0xFFB0 INSERT 0xFF9E + public static final KeyID DECIMAL = new KeyID(83); // MS 0x53 UNIX 0xFFAE DELETE 0xFF9F + public static final KeyID F11 = new KeyID(84); // MS 0x57 UNIX 0xFFC8 + public static final KeyID F12 = new KeyID(85); // MS 0x58 UNIX 0xFFC9 + public static final KeyID F13 = new KeyID(86); // MS 0x64 UNIX 0xFFCA + public static final KeyID F14 = new KeyID(87); // MS 0x65 UNIX 0xFFCB + public static final KeyID F15 = new KeyID(88); // MS 0x66 UNIX 0xFFCC + public static final KeyID KANA = new KeyID(89); // MS 0x70 UNIX 0xFF2D + public static final KeyID CONVERT = new KeyID(90); // MS 0x79 Japanese keyboard + public static final KeyID NOCONVERT = new KeyID(91); // MS 0x7B Japanese keyboard + public static final KeyID YEN = new KeyID(92); // MS 0x7D UNIX 0x0a5 + public static final KeyID NUMPADEQUAL = new KeyID(93); // MS 0x8D UNIX 0xFFBD + public static final KeyID CIRCUMFLEX = new KeyID(94); // MS 0x90 Japanese keyboard + public static final KeyID AT = new KeyID(95); // MS 0x91 UNIX 0x040 + public static final KeyID COLON = new KeyID(96); // MS 0x92 UNIX 0x03a + public static final KeyID UNDERLINE = new KeyID(97); // MS 0x93 NEC PC98 + public static final KeyID KANJI = new KeyID(98); // MS 0x94 UNIX 0xFF21 + public static final KeyID STOP = new KeyID(99); // MS 0x95 UNIX 0xFF69 + public static final KeyID AX = new KeyID(100); // MS 0x96 Japan AX + public static final KeyID UNLABELED = new KeyID(101); // MS 0x97 J3100 + public static final KeyID NUMPADENTER = new KeyID(102); // MS 0x9C UNIX 0xFF8D + public static final KeyID RCONTROL = new KeyID(103); // MS 0x9D UNIX 0xFFE4 + public static final KeyID NUMPADCOMMA = new KeyID(104); // MS 0xB3 UNIX 0xFFAC + public static final KeyID DIVIDE = new KeyID(105); // MS 0xB5 UNIX 0xFFAF + public static final KeyID SYSRQ = new KeyID(106); // MS 0xB7 UNIX 0xFF15 PRINT 0xFF61 + public static final KeyID RALT = new KeyID(107); // MS 0xB8 UNIX 0xFFEA + public static final KeyID PAUSE = new KeyID(108); // MS 0xC5 UNIX 0xFF13 BREAK 0xFF6B + public static final KeyID HOME = new KeyID(109); // MS 0xC7 UNIX 0xFF50 + public static final KeyID UP = new KeyID(110); // MS 0xC8 UNIX 0xFF52 + public static final KeyID PRIOR = new KeyID(111); // MS 0xC9 UNIX 0xFF55 + public static final KeyID LEFT = new KeyID(112); // MS 0xCB UNIX 0xFF51 + public static final KeyID RIGHT = new KeyID(113); // MS 0xCD UNIX 0xFF53 + public static final KeyID END = new KeyID(114); // MS 0xCF UNIX 0xFF57 + public static final KeyID DOWN = new KeyID(115); // MS 0xD0 UNIX 0xFF54 + public static final KeyID NEXT = new KeyID(116); // MS 0xD1 UNIX 0xFF56 + public static final KeyID INSERT = new KeyID(117); // MS 0xD2 UNIX 0xFF63 + public static final KeyID DELETE = new KeyID(118); // MS 0xD3 UNIX 0xFFFF + public static final KeyID LWIN = new KeyID(119); // MS 0xDB UNIX META 0xFFE7 SUPER 0xFFEB HYPER 0xFFED + public static final KeyID RWIN = new KeyID(120); // MS 0xDC UNIX META 0xFFE8 SUPER 0xFFEC HYPER 0xFFEE + public static final KeyID APPS = new KeyID(121); // MS 0xDD UNIX 0xFF67 + public static final KeyID POWER = new KeyID(122); // MS 0xDE Sun 0x1005FF76 SHIFT 0x1005FF7D + public static final KeyID SLEEP = new KeyID(123); // MS 0xDF No UNIX keysym + protected static final KeyID FIRST = VOID; + protected static final KeyID LAST = SLEEP; + } // class StandardKeyboard.KeyID +} // class StandardKeyboard diff --git a/coreAPI/src/java/net/java/games/input/test/ControllerReadTest.java b/coreAPI/src/java/net/java/games/input/test/ControllerReadTest.java new file mode 100644 index 0000000..15668bf --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/test/ControllerReadTest.java @@ -0,0 +1,279 @@ +/* + * ConrtollerReadTest.java + * + * Created on May 5, 2003, 3:15 PM + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input.test; + +/** + * + * @author administrator + */ + +import net.java.games.input.*; +import javax.swing.*; +import java.util.*; +import java.util.List; +import java.awt.*; + +abstract class AxisPanel extends JPanel{ + Axis axis; + float data; + + public AxisPanel(Axis ax){ + axis = ax; + setLayout(new BorderLayout()); + add(new JLabel(ax.getName()+"("+ax.getIdentifier()+")"), + BorderLayout.NORTH); + } + + public void poll(){ + data = axis.getPollData(); + renderData(); + } + + protected abstract void renderData(); +} + +class DigitalAxisPanel extends AxisPanel { + JLabel digitalState = new JLabel("<unread>"); + + public DigitalAxisPanel(Axis ax) { + super(ax); + add(digitalState,BorderLayout.CENTER); + } + + protected void renderData(){ + if (data == 0.0f){ + digitalState.setBackground(getBackground()); + digitalState.setText("OFF"); + } else if ( data == 1.0f) { + digitalState.setBackground(Color.green); + digitalState.setText("ON"); + }else { // shoudl never happen + digitalState.setBackground(Color.red); + digitalState.setText("ERR:"+data); + } + digitalState.repaint(); + } +} + +class DigitalHatPanel extends AxisPanel { + JLabel digitalState = new JLabel("<unread>"); + + public DigitalHatPanel(Axis ax) { + super(ax); + add(digitalState,BorderLayout.CENTER); + } + + protected void renderData(){ + if (data == Axis.POV.OFF){ + digitalState.setBackground(getBackground()); + digitalState.setText("OFF"); + } else if ( data == Axis.POV.UP) { + digitalState.setBackground(Color.green); + digitalState.setText("UP"); + } else if ( data == Axis.POV.RIGHT) { + digitalState.setBackground(Color.green); + digitalState.setText("RIGHT"); + } else if ( data == Axis.POV.DOWN) { + digitalState.setBackground(Color.green); + digitalState.setText("DOWN"); + } else if ( data == Axis.POV.LEFT) { + digitalState.setBackground(Color.green); + digitalState.setText("LEFT"); + }else { // shoudl never happen + digitalState.setBackground(Color.red); + digitalState.setText("ERR:"+data); + } + digitalState.repaint(); + } +} +class AnalogAxisPanel extends AxisPanel { + JLabel analogState = new JLabel("<unread>"); + + public AnalogAxisPanel(Axis ax) { + super(ax); + add(analogState,BorderLayout.CENTER); + } + + protected void renderData(){ + analogState.setText(""+data); + analogState.repaint(); + } +} + + + +class ControllerWindow extends JFrame { + Controller ca; + List axisList = new ArrayList(); + boolean disabled = false; + + public ControllerWindow(JFrame frame,Controller ca){ + super(ca.getName()); + this.setName(ca.getName()); + this.ca = ca; + Container c = this.getContentPane(); + c.setLayout(new BorderLayout()); + Axis[] axis = ca.getAxes(); + System.out.println("Axis count = "+axis.length); + if (axis.length>0) { + int width = (int)Math.ceil(Math.sqrt(axis.length)); + JPanel p = new JPanel(); + p.setLayout(new GridLayout(width,0)); + for(int j=0;j<axis.length;j++){ + addAxis(p,axis[j]); + } + c.add(new JScrollPane(p),BorderLayout.CENTER); + } + setSize(400,400); + setLocation(50,50); + setVisible(true); + } + + public boolean disabled() { + return disabled; + } + + private void setDisabled(boolean b){ + disabled = b; + if (!disabled){ + this.setTitle(ca.getName()); + System.out.println(ca.getName()+" enabled"); + } else { + this.setTitle(ca.getName()+" DISABLED!"); + System.out.println(ca.getName()+" disabled"); + } + repaint(); + } + + private void addAxis(JPanel p, Axis ax){ + JPanel p2; + if (ax.isAnalog()) { + p2 = new AnalogAxisPanel(ax); + } else { + if (ax.getIdentifier() == Axis.Identifier.POV) { + p2 = new DigitalHatPanel(ax); + } else { + p2 = new DigitalAxisPanel(ax); + } + } + p.add(p2); + axisList.add(p2); + ax.setPolling(true); + } + + public void poll(){ + if (!ca.poll()) { + if (!disabled()){ + setDisabled(true); + } + return; + } + if (disabled()){ + setDisabled(false); + } + //System.out.println("Polled "+ca.getName()); + for(Iterator i =axisList.iterator();i.hasNext();){ + try { + ((AxisPanel)i.next()).poll(); + }catch (Exception e) { + e.printStackTrace(); + } + } + } +} + +public class ControllerReadTest extends JFrame{ + static final long HEARTBEATMS =100; // 10th of a second + List controllers = new ArrayList(); + /** Creates a new instance of ConrtollerReadTest */ + public ControllerReadTest() { + super("Controller Read Test"); + ControllerEnvironment ce = ControllerEnvironment.getDefaultEnvironment(); + Controller[] ca = ce.getControllers(); + for(int i =0;i<ca.length;i++){ + makeController(ca[i]); + } + + new Thread(new Runnable() { + public void run(){ + try { + while(true){ + for(Iterator i=controllers.iterator();i.hasNext();){ + try { + ControllerWindow cw = (ControllerWindow)i.next(); + cw.poll(); + } catch (Exception e) { + e.printStackTrace(); + } + } + Thread.sleep(HEARTBEATMS); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }).start(); + pack(); + setSize(400,400); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setVisible(true); + } + + private void makeController(Controller c) { + Controller[] subControllers = c.getControllers(); + if (subControllers.length == 0 ) { + createControllerWindow(c); + } else { + for(int i=0;i<subControllers.length;i++){ + makeController(subControllers[i]); + } + } + } + + private void createControllerWindow(Controller c){ + controllers.add(new ControllerWindow(this,c)); + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + new ControllerReadTest().setVisible(true); + } + +} diff --git a/coreAPI/src/java/net/java/games/input/test/ControllerTextTest.java b/coreAPI/src/java/net/java/games/input/test/ControllerTextTest.java new file mode 100644 index 0000000..8b59c8f --- /dev/null +++ b/coreAPI/src/java/net/java/games/input/test/ControllerTextTest.java @@ -0,0 +1,89 @@ +/* + * ControllerScanner.java + * + * Created on April 14, 2003, 3:45 PM + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input.test; + +/** + * + * @author administrator + */ +import net.java.games.input.*; + +public class ControllerTextTest { + ControllerEnvironment ce; + /** Creates a new instance of ControllerScanner */ + public ControllerTextTest() { + ce = ControllerEnvironment.getDefaultEnvironment(); + System.out.println("Controller Env = "+ce.toString()); + + + Controller[] ca = ce.getControllers(); + for(int i =0;i<ca.length;i++){ + System.out.println(ca[i].getName()); + System.out.println("Type: "+ca[i].getType().toString()); + Axis[] axis = ca[i].getAxes(); + System.out.println("Axis Count: "+axis.length); + for(int j=0;j<axis.length;j++){ + System.out.println("Axis "+j+": "+axis[j].getName()); + System.out.println(" Identifier: "+ + axis[j].getIdentifier().getName()); + System.out.print(" AxisType: "); + if (axis[j].isRelative()) { + System.out.print("Relative"); + } else { + System.out.print("Absolute"); + } + if (axis[j].isAnalog()) { + System.out.print(" Analog"); + } else { + System.out.print(" Digital"); + } + System.out.println(); + } + System.out.println("---------------------------------"); + } + + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + new ControllerTextTest(); + } + +} diff --git a/plugins/DX8/README.txt b/plugins/DX8/README.txt new file mode 100644 index 0000000..12cd468 --- /dev/null +++ b/plugins/DX8/README.txt @@ -0,0 +1,46 @@ +This file modified last on 06/06/2003 by Jeff Kesselman + +This is the source tree for the core input API. + +Directory Organization: + +The root contains a master ANT build.xml. +After a successful build you will have the following sub directories: + -- apidocs Where the javadocs get built to + -- lib Where dependant libraries are kept. + -- bin Where the plugin dll and jar files ar built to. + -- src The source files. + + +Build instructions: + +To clean: ant clean +To build: ant all (or just ant) +To build docs: ant javadoc +To test: + This build will install the plug-in into the coreAPI's test + directories. + Use the tests in the coreAPI build.xml to test. + +Release Info: + Initial Release: This release contains an implementation of the input + API designed by Mike Martak of Sun and Thomas (?) of Sony CEA for + the WIn32 platform. All the code in src/input is cross platform. The + Win32 code is segregated to the DirectX plugin (src/DXplugin) which + depends on DirectInput from DX7 (or later). + + 05/09/2003: A number of bugs and problems with the DXPlugin are fixed in this + release. This release also brings the code up to date using the DI8 + interface. This thus is the first release that requries Peter Puck's + DX8 bindings to compile with MinGW. + + 05/09/2003 (second update): + This version adds a new standard value type to the API. + Axis.POV holds standard definitions for values for POV (hat) switches + -- Axis.POV.CENTER and Axis.POV.OFF are synonmous and are + the center position. + -- Axis.POV.UP, Axis.POV.DOWN, Axis.POV.LEFT and Axis.POV.RIGHT + should be self explainatory. + Any hat that claims to be "normalized" will return these values. (It is + recommended that all hats be normalized by the systemn specific plugins.) + diff --git a/plugins/DX8/build.xml b/plugins/DX8/build.xml new file mode 100644 index 0000000..32001e1 --- /dev/null +++ b/plugins/DX8/build.xml @@ -0,0 +1,103 @@ +<?xml version="1.0"?> + +<!-- Written to assume that classpath is rooted in the current directory. --> +<!-- So this should be OK if you make this script in the root of a filesystem. --> +<!-- If not, you may prefer to adjust the basedir, or move some directories around. --> +<!-- The idea is that both Ant and NetBeans have to know what the package root is --> +<!-- for the classes in your application. --> +<project name="Direct Input Plugin" basedir="." default="all"> + + <!-- Don't worry if you don't know the Ant syntax completely or need help on some tasks! --> + <!-- The standard Ant documentation is bundled. See Help | Help Sets | Ant 1.4.1 Manual. --> + + <target name="init"> + <!-- You can set up any variables you want used throughout the script here. --> + <property name="hello" value="world"/> + <mkdir dir="classes"/> + <mkdir dir="bin"/> + <!-- To use e.g. Jikes, uncomment this line. --> + <!-- (Or make the same change in Tools | Options | Ant Settings | Properties.) --> + <!-- <property name="build.compiler" value="jikes"/> --> + <!-- You might like to set up some overridable paths, etc.: --> + <!-- <property name="mylib" value="../lib/mylib.jar"/> --> + </target> + + <target name="compile" depends="init"> + <!-- Both srcdir and destdir should be package roots. --> + <!-- They could be different of course; in that case NetBeans can also be set --> + <!-- up to compile to a different filesystem in the same way; see Compiler Types: --> + <javac srcdir="src/java" destdir="classes" debug="true" deprecation="true" source="1.4"> + <!-- To add something to the classpath: --> + <classpath> + <pathelement location="lib/controller.jar"/> + <pathelement location="lib/jutils.jar"/> + </classpath> + <!-- To exclude some files: --> + <!-- + <exclude name="com/foo/SomeFile.java"/> + <exclude name="com/foo/somepackage/"/> + --> + </javac> + <exec dir="." executable="gcc" os="Windows 2000"> + <arg line=" -D_STRICT_ANSI -D_JNI_IMPLEMENTATION_"/> + <arg line=" -I'${java.home}/../include' -I'${java.home}/../include/win32' -Ic:/dx9/include"/> + <arg line=" -o bin/dxinput.dll src/native/input.cpp -Wl,--export-all-symbols"/> + <arg line=" -shared -Wl,--kill-at -ldxguid -ldinput -ldinput8"/> + </exec> + <copy file="bin/dxinput.dll" todir="../../coreAPI/src/tests/controller" /> + </target> + + <target name="jar" depends="init,compile"> + <!-- To make a standalone app: --> + <!-- 1. Create a myapp.mf manifest somewhere. --> + <!-- 2. Put in it: --> + <!-- Manifest-Version: 1.0 --> + <!-- Main-Class: com.foo.Main --> + <!-- 3. Pass to <jar>: manifest="myapp.mf" --> + <jar jarfile="bin/dxinput.jar" compress="true" basedir="classes"> + <exclude name="**/*.java"/> + <exclude name="**/*.form"/> + <exclude name="dxinput.mf"/> + <exclude name="dxinput.jar"/> + <exclude name="apidoc"/> + </jar> + <copy file="bin/dxinput.jar" todir="../../coreAPI/src/tests/controller" /> + </target> + + <target name="all" depends="compile,jar" description="Build everything."> + <echo message="Application built. Hello ${hello}!"/> + </target> + + <target name="test" depends="init,all" description="Try running it."> + <echo message="Test by running test on the build.xml for input"/> + </target> + + <target name="javadoc" depends="init" description="Javadoc for my API."> + <mkdir dir="apidocs"/> + <javadoc packagenames="net.*" + destdir="apidocs" + additionalparam="-source 1.4"> + <sourcepath> + <pathelement location="src/java"/> + </sourcepath> + <classpath> + <pathelement location="lib/controller.jar"/> + <pathelement location="lib/jutils.jar"/> + </classpath> + </javadoc> + </target> + + <target name="clean" depends="init" description="Clean all build products."> + <delete> + <fileset dir="classes"> + <include name="**/*.class"/> + </fileset> + </delete> + <delete file="bin/dxinput.jar" failonerror="no"/> + <delete file="bin/dxinput.dll" failonerror="no"/> + <delete file="../../coreAPI/src/tests/controller/dxinput.jar" failonerror="no" /> + <delete file="../../coreAPI/src/test/controller/dxinput.dll" failonerror="no"/> + <delete dir="../../docs/input/win32/apidoc" failonerror="no"/> + </target> + +</project> diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputAxis.java b/plugins/DX8/src/java/net/java/games/input/DirectInputAxis.java new file mode 100644 index 0000000..58df37d --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputAxis.java @@ -0,0 +1,211 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import net.java.games.input.AbstractAxis; +import net.java.games.input.Axis; + +/** + * + * @author martak + * @version + */ +class DirectInputAxis extends AbstractAxis { + + /** + * DIDFT_ constants and macros defined in dinput.h + */ + private static final int DIDFT_ALL = 0x00000000; + private static final int DIDFT_RELAXIS = 0x00000001; + private static final int DIDFT_ABSAXIS = 0x00000002; + private static final int DIDFT_AXIS = 0x00000003; + private static final int DIDFT_PSHBUTTON = 0x00000004; + private static final int DIDFT_TGLBUTTON = 0x00000008; + private static final int DIDFT_BUTTON = 0x0000000C; + private static final int DIDFT_POV = 0x00000010; + private static final int DIDFT_COLLECTION = 0x00000040; + private static final int DIDFT_NODATA = 0x00000080; + private static final int DIDFT_ANYINSTANCE = 0x00FFFF00; + private static final int DIDFT_INSTANCEMASK = DIDFT_ANYINSTANCE; + private static final int DIDFT_FFACTUATOR = 0x01000000; + private static final int DIDFT_FFEFFECTTRIGGER = 0x02000000; + private static final int DIDFT_OUTPUT = 0x10000000; + private static final int DIDFT_NOCOLLECTION = 0x00FFFF00; + private static int DIDFT_MAKEINSTANCE(int n) { + return ((n&0xffff) << 8); + } + private static int DIDFT_GETTYPE(int n) { + return (n&0xFF); + } + private static int DIDFT_GETINSTANCE(int n) { + return ((n >> 8)&0xffff); + } + private static int DIDFT_ENUMCOLLECTION(int n) { + return ((n&0xFFFF) << 8); + } + + private DirectInputDevice device; + /** + * DIJOYSTATE structure defined in dinput.h: + * + * <pre> + * typedef struct DIJOYSTATE { + * LONG lX; + * LONG lY; + * LONG lZ; + * LONG lRx; + * LONG lRy; + * LONG lRz; + * LONG rglSlider[2]; + * DWORD rgdwPOV[4]; + * BYTE rgbButtons[32]; + * } DIJOYSTATE, *LPDIJOYSTATE; + * + * 80 bytes total + * </pre> + */ + private int offset; + private int type; + private int instance; + private int bitmask = 0xffffffff; + private int bitshift = 0; + + private DirectInputAxis(DirectInputDevice device, Axis.Identifier id, + int didft, String name) { + super(name, id); + this.device = device; + this.type = DIDFT_GETTYPE(didft); + this.instance = DIDFT_GETINSTANCE(didft); + if (id == Axis.Identifier.X) { + offset = 0; + } else if (id == Axis.Identifier.Y) { + offset = 1; + } else if (id == Axis.Identifier.Z) { + offset = 2; + } else if (id == Axis.Identifier.RX) { + offset = 3; + } else if (id == Axis.Identifier.RY) { + offset = 4; + } else if (id == Axis.Identifier.RZ) { + offset = 5; + } else if (id == Axis.Identifier.SLIDER) { + //System.out.println("Slider on "+name+" instance = "+instance); + offset = 6 + (instance>>2); + } else if (id == Axis.Identifier.POV) { + //System.out.println("POV on "+name+" instance = "+instance); + offset = 8 + instance; + } else if (id == Axis.Identifier.BUTTON) { + //System.out.println("Button on "+name+" instance = "+instance); + offset = 12 + (instance/4); + bitshift = (instance%4)*8; + bitmask=0xff; + } + } + + /** Returns the data from the last time the control has been polled. + * If this axis is a button, the value returned will be either 0.0f or 1.0f. + * If this axis is normalized, the value returned will be between -1.0f and + * 1.0f. + * @return A float between -1.0 and 1.0 + */ + public float getPollData() { + int data = ((device.data[offset] >> bitshift)&bitmask); + if ((type&DIDFT_BUTTON) != 0 ) { + return (float)((data&0x80)>>7); + } else if ((type&DIDFT_AXIS)!=0){ // all axes are set for -32768 to 32738 + return ((float)data)/32768; + } else if ((type&DIDFT_POV)!=0) { + if (data == -1) { + return Axis.POV.OFF; + } else if (data == 0.0) { + return Axis.POV.UP; + } else if (data == 9000) { + return Axis.POV.RIGHT; + } else if (data == 18000) { + return Axis.POV.DOWN; + } else if (data == 27000) { + return Axis.POV.LEFT; + } else { + System.err.print("Unexpected value for DX8 HAT: "+data); + return Axis.POV.OFF; + } + } else { // return raw value + return (float)data; + } + + } + + /** Returns <code>true</code> if data returned from <code>poll</code> + * is relative to the last call, or <code>false</code> if data + * is absolute. + * @return true if data has chnaged since last poll, else false + */ + public boolean isRelative() { + return (type & DIDFT_RELAXIS) != 0; + } + + /** Returns whether or not the axis is analog, or false if it is digital. + * @return true if analog, false if digital + */ + public boolean isAnalog() { + return (type & DIDFT_AXIS) != 0; + } + + /** Returns whether or not data polled from this axis is normalized + * between the values of -1.0f and 1.0f. + * @return true if data is normalized, false if not. + */ + public boolean isNormalized() { + return (type & (DIDFT_BUTTON|DIDFT_AXIS|DIDFT_POV)) != 0; + } + + /** Creates a new DirectInputAxis (factory method). + * This is a function used internally during set up + * @return The new DirectInputAxis object. + * @param device The device to attach this axis to. + * + * @param didft The identifier for the axis as provided by DX8. + * @param name A name to give the new axis. + * @param id The identifier for the device + */ + public static DirectInputAxis createAxis(DirectInputDevice device, + Axis.Identifier id, int didft, String name) { + return new DirectInputAxis(device, id, didft, name); + } +} diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputDevice.java b/plugins/DX8/src/java/net/java/games/input/DirectInputDevice.java new file mode 100644 index 0000000..f31c66e --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputDevice.java @@ -0,0 +1,207 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import net.java.games.input.AbstractController; +import net.java.games.input.Axis; +import net.java.games.input.Controller; +import java.util.ArrayList; +import java.util.Iterator; + +/** + * + * @author martak + * @version + */ +class DirectInputDevice extends AbstractController { + + /** + * DIDEVTYPE_ constants from dinput.h header file + ** JPK NOTE: This changed in DI8. In general this + * is fragile anda way shoudl be found to tie these mroe directly + * to the header files. + */ + /* Mike's <=DX7 types + private static final int DIDEVTYPEJOYSTICK_UNKNOWN = 1; + private static final int DIDEVTYPEJOYSTICK_TRADITIONAL = 2; + private static final int DIDEVTYPEJOYSTICK_FLIGHTSTICK = 3; + private static final int DIDEVTYPEJOYSTICK_GAMEPAD = 4; + private static final int DIDEVTYPEJOYSTICK_RUDDER = 5; + private static final int DIDEVTYPEJOYSTICK_WHEEL = 6; + private static final int DIDEVTYPEJOYSTICK_HEADTRACKER = 7; + */ + + /** + * Pointer to the IDirectInputDevice for this device + */ + private long lpDevice; + + /** + * Type of device + */ + private Type type; + + /** + * Do we need to poll data? + */ + private boolean polled = true; + /** + * Data when polling, as per the DIJOYSTATE structure in dinput.h; + * @see DirectInputAxis for a breakdown of this structure + */ + int[] data = new int[32]; + + /** + * Private constructor + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of device, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the device + * @param instanceName The name of the device + */ + private DirectInputDevice(long lpDevice, int subtype, String productName, + String instanceName,boolean polled) { + super(productName + " " + instanceName); + this.lpDevice = lpDevice; + this.polled = polled; + System.out.println("Creating "+productName+" polling = "+polled); + switch(subtype) { + /* + case DIDEVTYPEJOYSTICK_GAMEPAD: + type = Type.GAMEPAD; break; + case DIDEVTYPEJOYSTICK_RUDDER: + type = Type.RUDDER; break; + case DIDEVTYPEJOYSTICK_WHEEL: + type = Type.WHEEL; break; + case DIDEVTYPEJOYSTICK_HEADTRACKER: + type = Type.HEADTRACKER; break; + case DIDEVTYPEJOYSTICK_TRADITIONAL: // fall through + case DIDEVTYPEJOYSTICK_FLIGHTSTICK: // fall through + */ + default: + type = Type.STICK; break; + } + axes = initDirectInputAxes(); + } + + /** + * Used instead of overriding initAxes because it needs the + * pointer to the IDirectInputDevice + */ + private Axis[] initDirectInputAxes() { + ArrayList list = new ArrayList(); + enumObjects(lpDevice, list); + Axis[] ret = new Axis[list.size()]; + Iterator it = list.iterator(); + int i = 0; + while (it.hasNext()) { + ret[i] = (Axis)it.next(); + i++; + } + return ret; + } + + /** + * Callback called by enumObjects to add a new axis into the list + * @param list This in which to add the new axis + * @param id The identifier for the axis, based on GUID + * @param didft The combination of DIDFT_ flags that make up the type and + * instance number of the axis. + * @param name The name to call the axis. + */ + private void addAxis(ArrayList list, Axis.Identifier id, int didft, + String name) { + list.add(DirectInputAxis.createAxis(this, id, didft, name)); + } + + /** Polls axes for data. Returns false if the controller is no longer valid. + * Polling reflects the current state of the device when polled, and is + * unbuffered. + * @return False if the co troller is no longer valid, else true. + */ + public boolean poll() { + return pollNative(lpDevice, data, polled); + } + + /** Returns the type of Controller. + * @return The type of the controller. + */ + public Type getType() { + return type; + } + + /** Returns the zero-based port number for this Controller. + * @return The port number. + */ + public int getPortNumber() { + // REMIND : We may be able to parse this from the name string + return 0; + } + + /** + * Polls the device; native method. The data from the poll is stored in + * the data array. + */ + private native boolean pollNative(long lpDevice, int[] data, + boolean polled); + + /** + * Enumerates the axes on the device + */ + private native boolean enumObjects(long lpDevice, ArrayList list); + + /** Creates a new DirectInputDevice (factory method) + * This is a function used internally during set up + * @param polled Whether this device's driver should actually be + * polled during a call to Poll or whether it is an + * interrupt driven device that should ignore poll + * requests. + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of device, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the device + * @param instanceName The name of the device + * @return The new DirectInputDevice object + */ + public static DirectInputDevice createDevice(long lpDevice, int subtype, + String productName, String instanceName, boolean polled) { + return new DirectInputDevice(lpDevice, subtype, productName, + instanceName,polled); + } +} // class DirectInputDevice diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java b/plugins/DX8/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java new file mode 100644 index 0000000..a406b09 --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java @@ -0,0 +1,183 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.security.AccessController; +import java.util.ArrayList; +import java.util.Iterator; +import net.java.games.input.Controller; +import net.java.games.input.ControllerEnvironment; +//import sun.security.action.LoadLibraryAction; +import net.java.games.util.plugins.Plugin; + +/** DirectInput implementation of controller environment + * @author martak + * @version 1.0 + */ +public class DirectInputEnvironmentPlugin extends ControllerEnvironment + implements Plugin +{ + + static { + /** Mikes old code, causes it to be laoded by wrong loader + java.security.AccessController.doPrivileged( + new LoadLibraryAction("jinput")); + */ + System.loadLibrary("dxinput"); + } + + /** + * DIDEVTYPE_ constants from dinput.h header file + * JPK NOTE: changed in DX8 so had to be changed. This is + * fragile, we should find a way to set them from + * the C side sowe can stay up to date with header + */ + /** DX7 and earlier + private static final int DIDEVTYPE_DEVICE = 1; + private static final int DIDEVTYPE_MOUSE = 2; + private static final int DIDEVTYPE_KEYBOARD = 3; + private static final int DIDEVTYPE_JOYSTICK = 4; + private static final int DIDEVTYPE_HID = 0x00010000; + private static int GET_DIDEVICE_TYPE(int dwDevType) { + return (int)((byte)dwDevType); + } + private static int GET_DIDEVICE_SUBTYPE(int dwDevType) { + return (int)((byte)((((short)dwDevType) >> 8) & 0xFF)); + } + **/ + /* DX8 and 9 */ + private static final int DI8DEVTYPE_DEVICE = 0x11; + private static final int DI8DEVTYPE_MOUSE = 0x12; + private static final int DI8DEVTYPE_KEYBOARD = 0x13; + private static final int DI8DEVTYPE_JOYSTICK = 0x14; + private static final int DI8DEVTYPE_GAMEPAD = 0x15; + private static final int DI8DEVTYPE_DRIVING = 0x16; + private static final int DI8DEVTYPE_FLIGHT = 0x17; + private static final int DI8DEVTYPE_1STPERSON = 0x18; + private static final int DI8DEVTYPE_DEVICECTRL = 0x19; + private static final int DI8DEVTYPE_SCREENPOINTER = 0x1A; + private static final int DI8DEVTYPE_REMOTE = 0x1B; + private static final int DI8DEVTYPE_SUPPLEMENTAL = 0x1C; + + private static int GET_DIDEVICE_TYPE(int dwDevType) { + return (dwDevType&0xFF); + } + private static int GET_DIDEVICE_SUBTYPE(int dwDevType) { + return (int)((byte)((((short)dwDevType) >> 8) & 0xFF)); + } + + // Pointer to DirectInput instance + private long lpDirectInput; + // Permanent array of controllers + private Controller[] controllers; + + /** Creates new DirectInputEnvironment */ + public DirectInputEnvironmentPlugin() { + lpDirectInput = directInputCreate(); + enumControllers(); + } + + /** Returns a list of all controllers available to this environment, + * or an empty array if there are no controllers in this environment. + * @return An array of controllers that may be empty. + */ + public Controller[] getControllers() { + return controllers; + } + + private void enumControllers() { + // If direct input fails, create an empty array + if (lpDirectInput == 0) { + controllers = new Controller[] {}; + return; + } + // Create temporary controller array + ArrayList tempDevices = new ArrayList(); + // Eumerate devices + enumDevices(lpDirectInput, tempDevices); + // Set up permanent controller array + controllers = new Controller[tempDevices.size()]; + Iterator it = tempDevices.iterator(); + int i = 0; + while (it.hasNext()) { + controllers[i] = (Controller)it.next(); + i++; + } + } + + /** + * Creates a new device, adding it to the list supplied. + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param type The type of device to create, as defined by the constants + * in dinput.h (see DI8DEVTYPE constants above). + * @param productName The product name for the device + * @param instanceName The name of the device + */ + private void addDevice(ArrayList list, long lpDevice, + int type, String productName, String instanceName, boolean polled) { + Controller c; + int category = GET_DIDEVICE_TYPE(type); + int subtype = GET_DIDEVICE_SUBTYPE(type); + //System.out.println("Category = "+category); + if (category == DI8DEVTYPE_MOUSE) { + c = DirectInputMouse.createMouse(lpDevice, subtype, productName, + instanceName); + } else if (category == DI8DEVTYPE_KEYBOARD) { + c = DirectInputKeyboard.createKeyboard(lpDevice, subtype, + productName, instanceName); + } else { + assert category == DI8DEVTYPE_JOYSTICK; + c = DirectInputDevice.createDevice(lpDevice, subtype, productName, + instanceName,polled); + } + if (c != null) { + list.add(c); + } + } + + /** + * Returns the direct input instance, or 0 if failed to initialize + */ + private native long directInputCreate(); + + /** + * Enumerates all devices, calling createDevice for each one + */ + private native boolean enumDevices(long lpDirectInput, ArrayList list); +} // class DirectInputEnvironment diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputKeyboard.java b/plugins/DX8/src/java/net/java/games/input/DirectInputKeyboard.java new file mode 100644 index 0000000..6faf163 --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputKeyboard.java @@ -0,0 +1,208 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import net.java.games.input.AbstractAxis; +import net.java.games.input.Axis; +import net.java.games.input.StandardKeyboard; + +/** + * DirectInput keyboard implementation. + * @author martak + * @version + */ +class DirectInputKeyboard extends StandardKeyboard { + + /** + * DIDEVTYPE_ constants from dinput.h header file + */ + private static final int DIDEVTYPEKEYBOARD_UNKNOWN = 0; + private static final int DIDEVTYPEKEYBOARD_PCXT = 1; + private static final int DIDEVTYPEKEYBOARD_OLIVETTI = 2; + private static final int DIDEVTYPEKEYBOARD_PCAT = 3; + private static final int DIDEVTYPEKEYBOARD_PCENH = 4; + private static final int DIDEVTYPEKEYBOARD_NOKIA1050 = 5; + private static final int DIDEVTYPEKEYBOARD_NOKIA9140 = 6; + private static final int DIDEVTYPEKEYBOARD_NEC98 = 7; + private static final int DIDEVTYPEKEYBOARD_NEC98LAPTOP = 8; + private static final int DIDEVTYPEKEYBOARD_NEC98106 = 9; + private static final int DIDEVTYPEKEYBOARD_JAPAN106 = 10; + private static final int DIDEVTYPEKEYBOARD_JAPANAX = 11; + private static final int DIDEVTYPEKEYBOARD_J3100 = 12; + + /** + * Key index crosstable; maps indices into the data array to virtual keys + * in the key array in StandardKeyboard. + * For example, the key F11 is at index 84 in the array of keys in + * StandardKeyboard, yet it is data element 87 (0x57) in our data array. + * <p> + * To access the data element of a particular key (F11), we use the + * crosstable as follows: + * <p><code> + * KeyID f11 = StandardKey.KeyID.F11; + * int keyIndex = f11.getKeyIndex(); // returns 84 + * int crossIndex = CROSSTABLE[keyIndex]; // returns 0x57 (87) + * </code> + * To find a key given the data element index (87), we do a simple search + * through the crosstable starting at that index (index 87/0x57 = 0x65) and + * looking backwards until we find our key itself, or a lower number + * (meaning the key was not found). We can only take advantage of this + * algorithm only because on Windows, our crosstable is in increasing order. + */ + private final static int[] CROSSTABLE = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, // _9 + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, // Y + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // D + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, // BACKSLASH + 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, // RSHIFT + 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, // F7 + 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, // NUMPAD5 + 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x57, 0x58, 0x64, 0x65, // F14 + 0x66, 0x70, 0x79, 0x7B, 0x7D, 0x8D, 0x90, 0x91, 0x92, 0x93, 0x94, // KANJI + 0x95, 0x96, 0x97, 0x9C, 0x9D, 0xB3, 0xB5, 0xB7, 0xB8, 0xC5, 0xC7, // HOME + 0xC8, 0xC9, 0xCB, 0xCD, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xDB, 0xDC, // RWIN + 0xDD, 0xDE, 0xDF // SLEEP + }; + + /** + * Pointer to the IDirectInputDevice for this device + */ + private long lpDevice; + + /** + * Subtype of keyboard, defined by DIDEVTYPE constants + */ + private int subtype; + + /** + * Polling key data + */ + private byte[] keyData = new byte[256]; + + /** + * Private constructor + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of keyboard, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the device + * @param instanceName The name of the device + */ + private DirectInputKeyboard(long lpDevice, int subtype, String productName, + String instanceName) { + super(productName + " (" + instanceName + ")"); + this.lpDevice = lpDevice; + this.subtype = subtype; + } + + /** + * Callback to rename a given key by index, name + * @param index the index in the data array + * @param name the name of the key + */ + private void renameKey(int index, String name) { + int keyIndex = index; + if (keyIndex > CROSSTABLE.length) { + keyIndex = CROSSTABLE.length - 1; + } + for (; CROSSTABLE[keyIndex] > index; keyIndex--) + ; + if (CROSSTABLE[keyIndex] == index) { + Axis[] axes = getAxes(); + AbstractAxis key = (AbstractAxis)axes[index]; + if (name != null && name.length() > 0) { + //System.out.println("Renaming key " + key.getName() + + // " to " + name + " index=" + + // index + " keyIndex=" + keyIndex + " CROSSTAB=" + + // CROSSTABLE[keyIndex]); + key.setName(name); + } + } else { + //System.out.println("Key not found " + name + " index=" + index + + // " keyIndex=" + keyIndex + " CROSSTAB=" + + // CROSSTABLE[keyIndex]); + } + } + + /** Polls axes for data. Returns false if the controller is no longer valid. + * Polling reflects the current state of the device when polled. + * @return False if the KB is no longer valid, true otherwise. + */ + public boolean poll() { + return pollNative(lpDevice, keyData); + } + + /** Returns whether or not the given key has been pressed since the last + * call to poll. + * @param key The key whose state to check. + * @return true if this key has changed state since last read of its state, false otherwise. + */ + protected boolean isKeyPressed(Key key) { + KeyID id = (KeyID)key.getIdentifier(); + int keyIndex = id.getKeyIndex(); + int crossIndex = CROSSTABLE[keyIndex]; + return ((keyData[crossIndex] & 0x80) != 0); + } + + /** + * Polls the device; native method + */ + private native boolean pollNative(long lpDevice, byte[] keyData); + + /** + * Renames the keys with the name provided by DirectInput + */ + private native boolean renameKeys(long lpDevice); + + /** Creates a new DirectInputKeyboard (factory method) + * This is a function used internally during set up. + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of keyboard, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the keyboard + * @param instanceName The name of the keyboard + * @return The new DirectInputKeyboard object. + */ + public static DirectInputKeyboard createKeyboard(long lpDevice, + int subtype, String productName, String instanceName) { + DirectInputKeyboard ret = new DirectInputKeyboard(lpDevice, subtype, + productName, instanceName); + ret.renameKeys(lpDevice); + return ret; + } +} // class DirectInputKeyboard diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputMouse.java b/plugins/DX8/src/java/net/java/games/input/DirectInputMouse.java new file mode 100644 index 0000000..f706250 --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputMouse.java @@ -0,0 +1,311 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import net.java.games.input.AbstractAxis; +import net.java.games.input.Axis; +import net.java.games.input.Mouse; + +/** + * DirectInput mouse implementation. + * @author martak + * @version + */ +class DirectInputMouse extends Mouse { + + /** + * DIDEVTYPE_ constants from dinput.h header file + */ + private static final int DIDEVTYPEMOUSE_UNKNOWN = 1; + private static final int DIDEVTYPEMOUSE_TRADITIONAL = 2; + private static final int DIDEVTYPEMOUSE_FINGERSTICK = 3; + private static final int DIDEVTYPEMOUSE_TOUCHPAD = 4; + private static final int DIDEVTYPEMOUSE_TRACKBALL = 5; + + /** + * Pointer to the IDirectInputDevice for this device + */ + private long lpDevice; + + /** + * Type of mouse + */ + private Type type; + + /** + * Mouse data + */ + private byte[] mouseData = new byte[16]; + + /** + * Private constructor + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of mouse, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the device + * @param instanceName The name of the device + */ + private DirectInputMouse(long lpDevice, int subtype, String productName, + String instanceName) { + super(productName + " " + instanceName); + buttons = new ButtonsImpl(); + ball = new BallImpl(); + this.lpDevice = lpDevice; + switch(subtype) { + case DIDEVTYPEMOUSE_FINGERSTICK: + type = Type.FINGERSTICK; break; + case DIDEVTYPEMOUSE_TOUCHPAD: + type = Type.TRACKPAD; break; + case DIDEVTYPEMOUSE_TRACKBALL: + type = Type.TRACKBALL; break; + case DIDEVTYPEMOUSE_TRADITIONAL: // fall through + case DIDEVTYPEMOUSE_UNKNOWN: // fall through + default: + type = Type.MOUSE; break; + } + renameAxes(lpDevice); + } + + /** + * Callback to rename a given axis by type, name + */ + private void renameAxis(Axis.Identifier id, String name) { + AbstractAxis axis; + if (id instanceof ButtonID) { + axis = (AbstractAxis)getButtons().getAxis(id); + } else { + axis = (AbstractAxis)getBall().getAxis(id); + } + axis.setName(name); + //System.out.println("Renaming " + name); + } + + /** Polls axes for data. Returns false if the controller is no longer valid. + * Polling reflects the current state of the device when polled. + * @return false if the mosue is no lonegr valid, true otherwise. + */ + public boolean poll() { + return pollNative(lpDevice, mouseData); + } + + /** Returns the type of the Controller. + * @return The device type of the controller (logically this + * shoudl be some form of "mouse" .) + */ + public Type getType() { + return type; + } + + /** Creates a new DirectInputMouse (factory method) + * This is a function used internally during set up. + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of mouse, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the keyboard + * @param instanceName The name of the keyboard + * @return The new DirectInputMouse object. + */ + public static DirectInputMouse createMouse(long lpDevice, int subtype, + String productName, String instanceName) { + return new DirectInputMouse(lpDevice, subtype, productName, + instanceName); + } + + /** + * Implementation class representing the mouse ball + */ + class BallImpl extends Ball { + + /** + * Public constructor + */ + public BallImpl() { + super(DirectInputMouse.this.getName() + " ball"); + x = new BallAxis(Axis.Identifier.X); + y = new BallAxis(Axis.Identifier.Y); + wheel = new BallAxis(Axis.Identifier.SLIDER); + } + } // class DirectInputMouse.BallImpl + + /** + * Implementation class representing the mouse buttons + */ + class ButtonsImpl extends Buttons { + + /** + * Public constructor + */ + public ButtonsImpl() { + super(DirectInputMouse.this.getName() + " buttons"); + left = new ButtonImpl(ButtonID.LEFT); + right = new ButtonImpl(ButtonID.RIGHT); + middle = new ButtonImpl(ButtonID.MIDDLE); + } + } // class DirectInputMouse.ButtonsImpl + + /** + * Polls the device; native method + */ + private native boolean pollNative(long lpDevice, byte[] mouseData); + + /** + * Renames the axes with the name provided by DirectInput + */ + private native boolean renameAxes(long lpDevice); + + /** + * Mouse button axis implementation + */ + class ButtonImpl extends Button { + + /** + * Index into the mouseData array + */ + private final int index; + + /** Public constructor + * @param id An ID of a button to create an obejct to represent. + * + */ + public ButtonImpl(ButtonID id) { + super(id.getName(), id); + if (id == ButtonID.LEFT) { + index = 12; + } else if (id == ButtonID.RIGHT) { + index = 13; + } else if (id == ButtonID.MIDDLE) { + index = 14; + } else { + throw new RuntimeException("Unknown button"); + } + } + + /** Returns the data from the last time the control has been polled. + * If this axis is a button, the value returned will be either 0.0f or 1.0f. + * If this axis is normalized, the value returned will be between -1.0f and + * 1.0f. + * @return state of controller. (Note: DX8 mice actually + * queue state so what is returned is the next state, + * not necessarily the most current one.) + */ + public float getPollData() { + // Mouse button + byte data = mouseData[index]; + if ((data & 0x80) != 0) { + return 1.0f; + } else { + return 0.0f; + } + } + + /** Returns <code>true</code> if data returned from <code>poll</code> + * is relative to the last call, or <code>false</code> if data + * is absolute. + * @return true if data is relative, otherwise false. + */ + public boolean isRelative() { + return false; + } + } // class DirectInputMouse.ButtonImpl + + /** + * Mouse ball axis implementation + */ + class BallAxis extends AbstractAxis { + + /** + * Starting index into the mouseData array + */ + private final int index; + + /** Public constructor + * @param id An ID for a mouse axis to create an object to represent. + */ + public BallAxis(Identifier id) { + super(id.getName(), id); + if (id == Identifier.X) { + index = 0; + } else if (id == Identifier.Y) { + index = 4; + } else if (id == Identifier.SLIDER) { + index = 8; + } else { + throw new RuntimeException("Unknown mouse axis"); + } + } + + /** Returns the data from the last time the control has been polled. + * If this axis is a button, the value returned will be either 0.0f or 1.0f. + * If this axis is normalized, the value returned will be between -1.0f and + * 1.0f. + * @return data. (Note that mice queue state in DX8 so what + * is returned is the next stae in the queue, not + * necessarily the most current one.) + */ + public float getPollData() { + int data = ((int)mouseData[index] << 12) | + ((int)mouseData[index + 1] << 8) | + ((int)mouseData[index + 2] << 4) | + ((int)mouseData[index + 3]); + if (data == -1) { + return -1.0f; + } else if (data >= 1) { + return 1.0f; + } else { + return 0.0f; + } + } + + /** Returns <code>true</code> if data returned from <code>poll</code> + * is relative to the last call, or <code>false</code> if data + * is absolute. + * @return true if relative, otherwise false. + */ + public boolean isRelative() { + return true; + } + + /** Returns whether or not the axis is analog, or false if it is digital. + * @return true if analog, false if digital + */ + public boolean isAnalog() { + return true; + } + } // class DirectInputMouse.MouseBallAxis +} // class DirectInputMouse diff --git a/plugins/DX8/src/native/input.cpp b/plugins/DX8/src/native/input.cpp new file mode 100644 index 0000000..ccfda2f --- /dev/null +++ b/plugins/DX8/src/native/input.cpp @@ -0,0 +1,888 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#ifndef WIN32 + #error This is a Windows-only file +#endif + +// hard define as DX7 +//#define DIRECTINPUT_VERSION 0x0800 +#include <windows.h> +#include <jni.h> +#include <dinput.h> + + +/* + ****************************************************************************** + * Global variables + ****************************************************************************** + */ +jclass CLASS_AxisIdentifier = NULL; +jclass CLASS_ButtonIdentifier = NULL; +jclass CLASS_DirectInputEnvironmentPlugin = NULL; +jclass CLASS_DirectInputDevice = NULL; +jclass CLASS_DirectInputKeyboard = NULL; +jclass CLASS_DirectInputMouse = NULL; +jmethodID MID_AddDevice = NULL; +jmethodID MID_AddAxis = NULL; +jmethodID MID_RenameKey = NULL; +jmethodID MID_RenameAxis = NULL; +jfieldID FID_X = NULL; +jfieldID FID_Y = NULL; +jfieldID FID_Z = NULL; +jfieldID FID_RX = NULL; +jfieldID FID_RY = NULL; +jfieldID FID_RZ = NULL; +jfieldID FID_Slider = NULL; +jfieldID FID_Button = NULL; +jfieldID FID_POV = NULL; +jfieldID FID_Left = NULL; +jfieldID FID_Right = NULL; +jfieldID FID_Middle = NULL; + +const char* FD_AxisIdentifier = "Lnet/java/games/input/Axis$Identifier;"; +const char* FD_ButtonIdentifier = "Lnet/java/games/input/Mouse$ButtonID;"; +// Dummy input window. This is needed because DirectX evidently needs a window +// to do anything, such as setting the cooperative level for a device. +const TCHAR* DUMMY_WINDOW_NAME = "InputControllerWindow"; +HWND hwndDummy = NULL; +// Buffer size +const DWORD BUFFER_SIZE = 16; + +// Class for handing device data to the callback for EnumDevices +class DeviceParamData { +public: + DeviceParamData(LPDIRECTINPUT8 lpdi, JNIEnv* e, jobject o, jobject l) : + lpDirectInput(lpdi), env(e), obj(o), list(l) + { + } + LPDIRECTINPUT8 lpDirectInput; + JNIEnv* env; + jobject obj; + jobject list; +}; + +// Class for handing device data to the callback for EnumObjects +class ObjectParamData { +public: + ObjectParamData(LPDIRECTINPUTDEVICE8 lpDev, JNIEnv* e, jobject o, + jobject l) : + lpDevice(lpDev), env(e), obj(o), list(l) + { + } + LPDIRECTINPUTDEVICE8 lpDevice; + JNIEnv* env; + jobject obj; + jobject list; +}; + +void PrintOutput(TCHAR* tszMessage) { + printf("%s\n", tszMessage); +} + +void PrintDIError(TCHAR* tszOutput, HRESULT res) { + TCHAR tszMessage[256]; +#define CHECK_RESULT(r) case r: \ +sprintf(tszMessage, "%s : %s", tszOutput, #r); \ +break; + switch (res) { + CHECK_RESULT(DI_OK) + CHECK_RESULT(DI_NOTATTACHED) + CHECK_RESULT(DI_POLLEDDEVICE) + CHECK_RESULT(DI_DOWNLOADSKIPPED) + CHECK_RESULT(DI_EFFECTRESTARTED) + CHECK_RESULT(DI_TRUNCATED) + CHECK_RESULT(DI_TRUNCATEDANDRESTARTED) + CHECK_RESULT(DIERR_OLDDIRECTINPUTVERSION) + CHECK_RESULT(DIERR_BETADIRECTINPUTVERSION) + CHECK_RESULT(DIERR_BADDRIVERVER) + CHECK_RESULT(DIERR_DEVICENOTREG) + CHECK_RESULT(DIERR_NOTFOUND) + //CHECK_RESULT(DIERR_OBJECTNOTFOUND) + CHECK_RESULT(DIERR_INVALIDPARAM) + CHECK_RESULT(DIERR_NOINTERFACE) + CHECK_RESULT(DIERR_GENERIC) + CHECK_RESULT(DIERR_OUTOFMEMORY) + CHECK_RESULT(DIERR_UNSUPPORTED) + CHECK_RESULT(DIERR_NOTINITIALIZED) + CHECK_RESULT(DIERR_ALREADYINITIALIZED) + CHECK_RESULT(DIERR_NOAGGREGATION) + CHECK_RESULT(DIERR_OTHERAPPHASPRIO) + CHECK_RESULT(DIERR_INPUTLOST) + CHECK_RESULT(DIERR_ACQUIRED) + CHECK_RESULT(DIERR_NOTACQUIRED) + //CHECK_RESULT(DIERR_READONLY) + //CHECK_RESULT(DIERR_HANDLEEXISTS) + CHECK_RESULT(DIERR_INSUFFICIENTPRIVS) + CHECK_RESULT(DIERR_DEVICEFULL) + CHECK_RESULT(DIERR_MOREDATA) + CHECK_RESULT(DIERR_NOTDOWNLOADED) + CHECK_RESULT(DIERR_HASEFFECTS) + CHECK_RESULT(DIERR_NOTEXCLUSIVEACQUIRED) + CHECK_RESULT(DIERR_INCOMPLETEEFFECT) + CHECK_RESULT(DIERR_NOTBUFFERED) + CHECK_RESULT(DIERR_EFFECTPLAYING) + CHECK_RESULT(DIERR_UNPLUGGED) + CHECK_RESULT(DIERR_REPORTFULL) + default: sprintf(tszMessage, "Unknown"); break; + } + PrintOutput(tszMessage); +} + +/* + ****************************************************************************** + * DirectInputEnvironmentPlugin + ****************************************************************************** + */ + +/* + * Initialize all class, method, and field IDs + */ +BOOL InitIDs(JNIEnv* env) { + CLASS_AxisIdentifier = + env->FindClass("net/java/games/input/Axis$Identifier"); + if (CLASS_AxisIdentifier == NULL) { + return FALSE; + } + FID_X = env->GetStaticFieldID(CLASS_AxisIdentifier, "X", + FD_AxisIdentifier); + if (FID_X == NULL) { + return FALSE; + } + FID_Y = env->GetStaticFieldID(CLASS_AxisIdentifier, "Y", + FD_AxisIdentifier); + if (FID_Y == NULL) { + return FALSE; + } + FID_Z = env->GetStaticFieldID(CLASS_AxisIdentifier, "Z", + FD_AxisIdentifier); + if (FID_Z == NULL) { + return FALSE; + } + FID_RX = env->GetStaticFieldID(CLASS_AxisIdentifier, "RX", + FD_AxisIdentifier); + if (FID_RX == NULL) { + return FALSE; + } + FID_RY = env->GetStaticFieldID(CLASS_AxisIdentifier, "RY", + FD_AxisIdentifier); + if (FID_RY == NULL) { + return FALSE; + } + FID_RZ = env->GetStaticFieldID(CLASS_AxisIdentifier, "RZ", + FD_AxisIdentifier); + if (FID_RZ == NULL) { + return FALSE; + } + FID_Slider = env->GetStaticFieldID(CLASS_AxisIdentifier, "SLIDER", + FD_AxisIdentifier); + if (FID_Slider == NULL) { + return FALSE; + } + FID_Button = env->GetStaticFieldID(CLASS_AxisIdentifier, "BUTTON", + FD_AxisIdentifier); + if (FID_Button == NULL) { + return FALSE; + } + FID_POV = env->GetStaticFieldID(CLASS_AxisIdentifier, "POV", + FD_AxisIdentifier); + if (FID_POV == NULL) { + return FALSE; + } + CLASS_ButtonIdentifier = + env->FindClass("net/java/games/input/Mouse$ButtonID"); + if (CLASS_ButtonIdentifier == NULL) { + return FALSE; + } + FID_Left = env->GetStaticFieldID(CLASS_ButtonIdentifier, "LEFT", + FD_ButtonIdentifier); + if (FID_Left == NULL) { + return FALSE; + } + FID_Right = env->GetStaticFieldID(CLASS_ButtonIdentifier, "RIGHT", + FD_ButtonIdentifier); + if (FID_Right == NULL) { + return FALSE; + } + FID_Middle = env->GetStaticFieldID(CLASS_ButtonIdentifier, "MIDDLE", + FD_ButtonIdentifier); + if (FID_Middle == NULL) { + return FALSE; + } + CLASS_DirectInputEnvironmentPlugin = + env->FindClass("net/java/games/input/DirectInputEnvironmentPlugin"); + if (CLASS_DirectInputEnvironmentPlugin == NULL) { + return FALSE; + } + MID_AddDevice = env->GetMethodID(CLASS_DirectInputEnvironmentPlugin, "addDevice", + "(Ljava/util/ArrayList;JILjava/lang/String;Ljava/lang/String;Z)V"); + if (MID_AddDevice == NULL) { + return FALSE; + } + CLASS_DirectInputDevice = + env->FindClass("net/java/games/input/DirectInputDevice"); + if (CLASS_DirectInputDevice == NULL) { + return FALSE; + } + MID_AddAxis = env->GetMethodID(CLASS_DirectInputDevice, "addAxis", + "(Ljava/util/ArrayList;Lnet/java/games/input/Axis$Identifier;ILjava/lang/String;)V"); + if (MID_AddAxis == NULL) { + return FALSE; + } + CLASS_DirectInputKeyboard = + env->FindClass("net/java/games/input/DirectInputKeyboard"); + if (CLASS_DirectInputKeyboard == NULL) { + return FALSE; + } + MID_RenameKey = env->GetMethodID(CLASS_DirectInputKeyboard, "renameKey", + "(ILjava/lang/String;)V"); + if (MID_RenameKey == NULL) { + return FALSE; + } + CLASS_DirectInputMouse = + env->FindClass("net/java/games/input/DirectInputMouse"); + if (CLASS_DirectInputMouse == NULL) { + return FALSE; + } + MID_RenameAxis = env->GetMethodID(CLASS_DirectInputMouse, "renameAxis", + "(Lnet/java/games/input/Axis$Identifier;Ljava/lang/String;)V"); + if (MID_RenameAxis == NULL) { + return FALSE; + } + return TRUE; +} + +/* + * WndProc for our dummy input window + */ +LRESULT CALLBACK DummyWndProc( + HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc(hWnd, message, wParam, lParam); +} + +/* + * Register the dummy input window class + */ +BOOL RegisterDummyWindow(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)DummyWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = NULL; + wcex.hCursor = NULL; + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = (LPCSTR)NULL; + wcex.lpszClassName = DUMMY_WINDOW_NAME; + wcex.hIconSm = NULL; + return RegisterClassEx(&wcex); +} + +/* + * Class: org_java_games_input_DirectInputEnvironmentPlugin + * Method: directInputCreate + * Signature: ()J + */ +extern "C" JNIEXPORT jlong JNICALL +Java_net_java_games_input_DirectInputEnvironmentPlugin_directInputCreate + (JNIEnv* env, jobject obj) +{ + // Get our module handle + HINSTANCE hInst = GetModuleHandle(NULL); + + // Register the dummy input window + if (!RegisterDummyWindow(hInst)) { + return (jlong)0; + } + + // Create the dummy input window + hwndDummy = CreateWindow(DUMMY_WINDOW_NAME, NULL, + WS_POPUP | WS_ICONIC, + 0, 0, 0, 0, NULL, NULL, hInst, NULL); + if (hwndDummy == NULL) + { + return (jlong)0; + } + + // Create the IDirectInput object + DWORD dwVersion = DIRECTINPUT_VERSION; + LPDIRECTINPUT8 lpDirectInput = NULL; + HRESULT res; + if (FAILED(res = DirectInput8Create(hInst, DIRECTINPUT_VERSION, + IID_IDirectInput8,(VOID **)&lpDirectInput, NULL))){ + PrintDIError("DirectInputCreate", res); + return (jlong)0; + } + + // Initialize method, class, and field IDs + if (!InitIDs(env)) { + lpDirectInput->Release(); + return (jlong)0; + } + + return (jlong)(long)lpDirectInput; +} + +/* + * Enumeration callback for devices + * + * returns DIENUM_CONTINUE or DIENUM_STOP + */ + +/** mikes old enum callback +BOOL CALLBACK EnumDeviceCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) +{ + DeviceParamData* pData = (DeviceParamData*)pvRef; + LPDIRECTINPUT8 lpDirectInput = pData->lpDirectInput; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jobject list = pData->list; + LPDIRECTINPUTDEVICE8 lpDevice = NULL; + LPUNKNOWN pUnknown = NULL; + + // Create the device object + HRESULT res = lpDirectInput->CreateDevice(lpddi->guidInstance, &lpDevice, + pUnknown); + if (res != DI_OK) { + PrintDIError("CreateDevice", res); + return DIENUM_STOP; + } + + LPDIRECTINPUTDEVICE8 lpDevice2 = NULL; + // Get the IDirectDrawDevice8 interface from the object + res = lpDevice->QueryInterface(IID_IDirectInputDevice8, + (void**)&lpDevice2); + if (res != DI_OK) { + PrintDIError("QueryInterface DID2", res); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Set the data format + DWORD category = GET_DIDEVICE_TYPE(lpddi->dwDevType); + LPCDIDATAFORMAT lpDataFormat = &c_dfDIJoystick; + if (category == DI8DEVTYPE_MOUSE) { + lpDataFormat = &c_dfDIMouse; + } else if (category == DI8DEVTYPE_KEYBOARD) { + lpDataFormat = &c_dfDIKeyboard; + } + res = lpDevice2->SetDataFormat(lpDataFormat); + if (res != DI_OK) { + PrintDIError("SetDataFormat", res); + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + + // If we are the mouse, we have to buffer the data + if (category == DI8DEVTYPE_MOUSE) { + DIPROPDWORD dipropdw; + dipropdw.diph.dwSize = sizeof(DIPROPDWORD); + dipropdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipropdw.diph.dwObj = 0; + dipropdw.diph.dwHow = DIPH_DEVICE; + dipropdw.dwData = BUFFER_SIZE; + res = lpDevice2->SetProperty(DIPROP_BUFFERSIZE, &dipropdw.diph); + if (res != DI_OK) { + PrintDIError("SetProperty", res); + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + } + + // Set the cooperative level + res = lpDevice2->SetCooperativeLevel(hwndDummy, + DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + if (res != DI_OK) { + PrintDIError("SetCooperativeLevel", res); + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Acquire the device + res = lpDevice2->Acquire(); + if (res != DI_OK && res != S_FALSE) { + PrintDIError("Acquire", res); + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Set the variables for the Java callback + jint type = (jint)lpddi->dwDevType; + jstring productName = env->NewStringUTF(lpddi->tszProductName); + if (productName == NULL) { + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + jstring instanceName = env->NewStringUTF(lpddi->tszInstanceName); + if (instanceName == NULL) { + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Add the device into the list + env->CallVoidMethod(obj, MID_AddDevice, list, (jlong)(long)lpDevice2, type, + productName, instanceName); + return DIENUM_CONTINUE; +} +*/ +/** jeff's new enum callback */ +BOOL CALLBACK EnumDeviceCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) +{ + DeviceParamData* pData = (DeviceParamData*)pvRef; + LPDIRECTINPUT8 lpDirectInput = pData->lpDirectInput; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jobject list = pData->list; + LPDIRECTINPUTDEVICE8 lpDevice = NULL; + LPUNKNOWN pUnknown = NULL; + HRESULT res; + + // Create the device object + if (FAILED(res = lpDirectInput->CreateDevice(lpddi->guidInstance, &lpDevice, + pUnknown))){ + PrintDIError("CreateDevice", res); + return DIENUM_STOP; + } + + /* + LPDIRECTINPUTDEVICE8 lpDevice2 = NULL; + // Get the IDirectDrawDevice8 interface from the object + res = lpDevice->QueryInterface(IID_IDirectInputDevice8, + (void**)&lpDevice2); + if (res != DI_OK) { + PrintDIError("QueryInterface DID2", res); + lpDevice->Release(); + return DIENUM_STOP; + } + */ + + // Set the data format + LPCDIDATAFORMAT lpDataFormat; + DWORD category = GET_DIDEVICE_TYPE(lpddi->dwDevType)&0xFF; + switch (category){ + case DI8DEVTYPE_KEYBOARD: + //printf("found Keyboard\n"); + lpDataFormat = &c_dfDIKeyboard; + break; + case DI8DEVTYPE_MOUSE: + //printf("found mouse\n"); + lpDataFormat = &c_dfDIMouse; + // set up buffering + DIPROPDWORD dipropdw; + dipropdw.diph.dwSize = sizeof(DIPROPDWORD); + dipropdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipropdw.diph.dwObj = 0; + dipropdw.diph.dwHow = DIPH_DEVICE; + dipropdw.dwData = BUFFER_SIZE; + if (FAILED( + res = lpDevice->SetProperty(DIPROP_BUFFERSIZE, + &dipropdw.diph))) { + PrintDIError("SetProperty", res); + lpDevice->Release(); + return DIENUM_STOP; + } + break; + case DI8DEVTYPE_JOYSTICK: + default: + //printf("found stick\n"); + lpDataFormat = &c_dfDIJoystick; + break; + } + + if (FAILED(res = lpDevice->SetDataFormat(lpDataFormat))){ + PrintDIError("SetDataFormat", res); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Set the cooperative level + if(FAILED(res = lpDevice->SetCooperativeLevel(hwndDummy, + DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))){ + PrintDIError("SetCooperativeLevel", res); + lpDevice->Release(); + return DIENUM_STOP; + } + + // get polling + DIDEVCAPS didc; + // Allocate space for all the device's objects (axes, buttons, POVS) + ZeroMemory( &didc, sizeof(DIDEVCAPS) ); + didc.dwSize = sizeof(DIDEVCAPS); + if (FAILED(res=lpDevice->GetCapabilities(&didc))){ + PrintDIError("Get Device Capabilities", res); + lpDevice->Release(); + return DIENUM_STOP; + } + jboolean polled = JNI_FALSE; + if ((didc.dwFlags)&DIDC_POLLEDDATAFORMAT) { + polled = JNI_TRUE; + } + + // Acquire the device + if(FAILED(res = lpDevice->Acquire())){ + PrintDIError("Acquire", res); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Set the variables for the Java callback + jint type = (jint)lpddi->dwDevType&0xffff; + //printf("type == %x\n",type); + jstring productName = env->NewStringUTF(lpddi->tszProductName); + if (productName == NULL) { + lpDevice->Release(); + return DIENUM_STOP; + } + jstring instanceName = env->NewStringUTF(lpddi->tszInstanceName); + if (instanceName == NULL) { + lpDevice->Release(); + return DIENUM_STOP; + } + + // Add the device into the list + env->CallVoidMethod(obj, MID_AddDevice, list, (jlong)(long)lpDevice, type, + productName, instanceName,(jboolean)polled); + return DIENUM_CONTINUE; +} + +/* + * Class: org_java_games_input_DirectInputEnvironmentPlugin + * Method: enumDevices + * Signature: (JLjava/util/ArrayList;)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputEnvironmentPlugin_enumDevices + (JNIEnv* env, jobject obj, jlong lDirectInput, jobject list) +{ + LPDIRECTINPUT8 lpDirectInput = (LPDIRECTINPUT8)(long)lDirectInput; + DWORD dwDevType = DI8DEVCLASS_ALL; + DeviceParamData data(lpDirectInput, env, obj, list); + LPVOID pvRef = (LPVOID)&data; + DWORD dwFlags = DIEDFL_ATTACHEDONLY; + HRESULT res; + if(FAILED(res=lpDirectInput->EnumDevices(dwDevType, + EnumDeviceCallback, pvRef, dwFlags))){ + PrintDIError("EnumDevices", res); + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + ****************************************************************************** + * DirectInputDevice + ****************************************************************************** + */ + +/* + * Class: org_java_games_input_DirectInputDevice + * Method: pollNative + * Signature: (J[B)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputDevice_pollNative + (JNIEnv* env, jobject obj, jlong lDevice, jintArray baData, + jboolean pollme) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + // Reacquire the device + HRESULT res = lpDevice->Acquire(); + if (res != DI_OK && res != S_FALSE) { + PrintDIError("Acquire", res); + return JNI_FALSE; + } + // Poll the device + if (pollme == JNI_TRUE) { + res = lpDevice->Poll(); + if (res != DI_OK) { + PrintDIError("Poll", res); + return JNI_FALSE; + } + } + // Get the device state (data) + DIJOYSTATE data; + res = lpDevice->GetDeviceState(sizeof(data), &data); + if (res != DI_OK) { + PrintDIError("GetDeviceState", res); + return JNI_FALSE; + } + // Copy the data into the byte array + env->SetIntArrayRegion(baData, 0, (jsize)(sizeof(data)/4), (jint*)&data); + return JNI_TRUE; +} + +/* + * Enumeration callback for device objects + * + * returns DIENUM_CONTINUE or DIENUM_STOP + */ +BOOL CALLBACK EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, + LPVOID pvRef) +{ + ObjectParamData* pData = (ObjectParamData*)pvRef; + LPDIRECTINPUTDEVICE8 lpDevice = pData->lpDevice; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jobject list = pData->list; + jobject identifier = NULL; + HRESULT res; + if (lpddoi->guidType == GUID_XAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_X); + } else if (lpddoi->guidType == GUID_YAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_Y); + } else if (lpddoi->guidType == GUID_ZAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_Z); + } else if (lpddoi->guidType == GUID_RxAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_RX); + } else if (lpddoi->guidType == GUID_RyAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_RY); + } else if (lpddoi->guidType == GUID_RzAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_RZ); + } else if (lpddoi->guidType == GUID_Slider) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_Slider); + } else if (lpddoi->guidType == GUID_Button) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_Button); + } else if (lpddoi->guidType == GUID_POV) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_POV); + } else { + // Do not add this axis into the list, since we don't know what it is + return DIENUM_CONTINUE; + } + if (identifier == NULL) { + return DIENUM_STOP; + } + if (DIDFT_GETTYPE(lpddoi->dwType)&DIDFT_AXIS){ + // set axis range + DIPROPRANGE joy_axis_range; + joy_axis_range.lMin = -32768; + joy_axis_range.lMax = 32768; + joy_axis_range.diph.dwSize=sizeof(DIPROPRANGE); + joy_axis_range.diph.dwHeaderSize=sizeof(DIPROPHEADER); + joy_axis_range.diph.dwHow = DIPH_BYID; + joy_axis_range.diph.dwObj=lpddoi->dwType; + if (FAILED( + res=lpDevice->SetProperty(DIPROP_RANGE,&joy_axis_range.diph))){ + PrintDIError("SetProperty", res); + } + } + jint didft = (jint)lpddoi->dwType; + jstring name = env->NewStringUTF(lpddoi->tszName); + // Add the axis into our list + env->CallVoidMethod(obj, MID_AddAxis, list, identifier, didft, + name); + return DIENUM_CONTINUE; +} + +/* + * Class: org_java_games_input_DirectInputDevice + * Method: enumObjects + * Signature: (JLjava/util/ArrayList;)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputDevice_enumObjects + (JNIEnv* env, jobject obj, jlong lDevice, jobject list) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + ObjectParamData data(lpDevice, env, obj, list); + LPVOID pvRef = (LPVOID)&data; + DWORD dwFlags = DIDFT_ALL; + // Enum objects + HRESULT res = lpDevice->EnumObjects(EnumObjectsCallback, pvRef, dwFlags); + if (res != DI_OK) { + PrintDIError("EnumObjects", res); + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + ****************************************************************************** + * DirectInputKeyboard + ****************************************************************************** + */ + +/* + * Class: org_java_games_input_DirectInputKeyboard + * Method: pollNative + * Signature: (J[B)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputKeyboard_pollNative + (JNIEnv* env, jobject obj, jlong lDevice, jbyteArray baData) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + // Reacquire the device + HRESULT res = lpDevice->Acquire(); + if (res != DI_OK && res != S_FALSE) { + PrintDIError("Acquire", res); + return JNI_FALSE; + } + // Get the device state (data) + char data[256]; + res = lpDevice->GetDeviceState(sizeof(data), data); + if (res != DI_OK) { + PrintDIError("GetDeviceState", res); + return JNI_FALSE; + } + env->SetByteArrayRegion(baData, 0, (jsize)sizeof(data), (jbyte*)&data); + return JNI_TRUE; +} + +/* + * Enumeration callback to rename keyboard keys + * + * returns DIENUM_CONTINUE or DIENUM_STOP + */ +BOOL CALLBACK RenameKeysCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, + LPVOID pvRef) +{ + ObjectParamData* pData = (ObjectParamData*)pvRef; + //LPDIRECTINPUTDEVICE8 lpDevice = pData->lpDevice; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jint index = (jint)lpddoi->dwOfs; + jstring name = env->NewStringUTF(lpddoi->tszName); + env->CallVoidMethod(obj, MID_RenameKey, index, name); + return DIENUM_CONTINUE; +} + +/* + * Class: org_java_games_input_DirectInputKeyboard + * Method: renameKeys + * Signature: (J)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputKeyboard_renameKeys + (JNIEnv* env, jobject obj, jlong lDevice) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + ObjectParamData data(lpDevice, env, obj, NULL); + LPVOID pvRef = (LPVOID)&data; + DWORD dwFlags = DIDFT_ALL; + // Enum objects + HRESULT res = lpDevice->EnumObjects(RenameKeysCallback, pvRef, dwFlags); + if (res != DI_OK) { + PrintDIError("EnumObjects", res); + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + ****************************************************************************** + * DirectInputMouse + ****************************************************************************** + */ + +/* + * Class: org_java_games_input_DirectInputMouse + * Method: pollNative + * Signature: (J[B)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputMouse_pollNative + (JNIEnv* env, jobject obj, jlong lDevice, jbyteArray baData) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + // Reacquire the device + HRESULT res = lpDevice->Acquire(); + if (res != DI_OK && res != S_FALSE) { + PrintDIError("Acquire", res); + return JNI_FALSE; + } + // Get the data + DIMOUSESTATE data; + res = lpDevice->GetDeviceState(sizeof(data), &data); + if (res != DI_OK) { + PrintDIError("GetDeviceState", res); + return JNI_FALSE; + } + // Set the data in our array + env->SetByteArrayRegion(baData, 0, (jsize)sizeof(data), (jbyte*)&data); + return JNI_TRUE; +} + +/* + * Enumeration callback to rename mouse axes + * + * returns DIENUM_CONTINUE or DIENUM_STOP + */ +BOOL CALLBACK RenameAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, + LPVOID pvRef) +{ + ObjectParamData* pData = (ObjectParamData*)pvRef; + //LPDIRECTINPUTDEVICE8 lpDevice = pData->lpDevice; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jobject identifier; + switch (lpddoi->dwOfs) { + case DIMOFS_X: + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, + FID_X); + break; + case DIMOFS_Y: + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, + FID_Y); + break; + case DIMOFS_Z: + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, + FID_Slider); + break; + case DIMOFS_BUTTON0: + identifier = env->GetStaticObjectField(CLASS_ButtonIdentifier, + FID_Left); + break; + case DIMOFS_BUTTON1: + identifier = env->GetStaticObjectField(CLASS_ButtonIdentifier, + FID_Right); + break; + case DIMOFS_BUTTON2: + identifier = env->GetStaticObjectField(CLASS_ButtonIdentifier, + FID_Middle); + break; + case DIMOFS_BUTTON3: + default: + return DIENUM_CONTINUE; // Not an axis we know + } + jstring name = env->NewStringUTF(lpddoi->tszName); + env->CallVoidMethod(obj, MID_RenameAxis, identifier, name); + return DIENUM_CONTINUE; +} + +/* + * Class: org_java_games_input_DirectInputMouse + * Method: renameAxes + * Signature: (J)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputMouse_renameAxes + (JNIEnv* env, jobject obj, jlong lDevice) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + ObjectParamData data(lpDevice, env, obj, NULL); + LPVOID pvRef = (LPVOID)&data; + DWORD dwFlags = DIDFT_ALL; + // Enum objects + HRESULT res = lpDevice->EnumObjects(RenameAxesCallback, pvRef, dwFlags); + if (res != DI_OK) { + PrintDIError("EnumObjects", res); + return JNI_FALSE; + } + return JNI_TRUE; +} + + |