commit f45b3ebaf8008da2fe43dfd59f99e0459e566e71 Author: Rik Veenboer Date: Sat Oct 18 17:43:25 2014 +0100 Import from http://drts.cvs.sourceforge.net/viewvc/drts/projects/jxinput/ tarball diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..21df587 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,5 @@ +classes +tmp +build +archiv + diff --git a/etc/build.xml b/etc/build.xml new file mode 100644 index 0000000..509822e --- /dev/null +++ b/etc/build.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etc/nb5/.cvsignore b/etc/nb5/.cvsignore new file mode 100644 index 0000000..9d0b71a --- /dev/null +++ b/etc/nb5/.cvsignore @@ -0,0 +1,2 @@ +build +dist diff --git a/etc/nb5/build.xml b/etc/nb5/build.xml new file mode 100644 index 0000000..80ab72e --- /dev/null +++ b/etc/nb5/build.xml @@ -0,0 +1,69 @@ + + + + + + Builds, tests, and runs the project jxinput. + + + diff --git a/etc/nb5/manifest.mf b/etc/nb5/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/etc/nb5/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/etc/nb5/nbproject/.cvsignore b/etc/nb5/nbproject/.cvsignore new file mode 100644 index 0000000..3e18ebf --- /dev/null +++ b/etc/nb5/nbproject/.cvsignore @@ -0,0 +1 @@ +private diff --git a/etc/nb5/nbproject/build-impl.xml b/etc/nb5/nbproject/build-impl.xml new file mode 100644 index 0000000..08b7cd7 --- /dev/null +++ b/etc/nb5/nbproject/build-impl.xml @@ -0,0 +1,532 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + diff --git a/etc/nb5/nbproject/genfiles.properties b/etc/nb5/nbproject/genfiles.properties new file mode 100644 index 0000000..a6c84f7 --- /dev/null +++ b/etc/nb5/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=3ba4020f +build.xml.script.CRC32=654a06bb +build.xml.stylesheet.CRC32=d5b6853a +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=3ba4020f +nbproject/build-impl.xml.script.CRC32=00e7e9f7 +nbproject/build-impl.xml.stylesheet.CRC32=99b91518 diff --git a/etc/nb5/nbproject/project.properties b/etc/nb5/nbproject/project.properties new file mode 100644 index 0000000..a0f0bc5 --- /dev/null +++ b/etc/nb5/nbproject/project.properties @@ -0,0 +1,57 @@ +application.args= +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/jxinput.jar +dist.javadoc.dir=${dist.dir}/javadoc +file.reference.jxinput-java=../../java +jar.compress=false +javac.classpath=\ + ${libs.Java3D.classpath} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=de.hardcode.jxinput.test.JXInputTestDialog +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +src.dir=${file.reference.jxinput-java} diff --git a/etc/nb5/nbproject/project.xml b/etc/nb5/nbproject/project.xml new file mode 100644 index 0000000..9f941d5 --- /dev/null +++ b/etc/nb5/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.java.j2seproject + + + jxinput + 1.6.5 + + + + + + + diff --git a/java/de/hardcode/jxinput/Axis.java b/java/de/hardcode/jxinput/Axis.java new file mode 100644 index 0000000..9f1d710 --- /dev/null +++ b/java/de/hardcode/jxinput/Axis.java @@ -0,0 +1,72 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 19. Dezember 2001, 21:58 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * The Axis interface describes the most common feature of a joystick or other input devices. + * + * @author Herkules + */ +public interface Axis extends Feature +{ + // Enumeration of axes. + final static int ID_X = 0; + final static int ID_Y = 1; + final static int ID_Z = 2; + final static int ID_ROTX = 3; + final static int ID_ROTY = 4; + final static int ID_ROTZ = 5; + final static int ID_SLIDER0 = 6; + final static int ID_SLIDER1 = 7; + final static int NUMBER_OF_ID = 8; + + // Enumeration of axis types + final static int TRANSLATION = 0; + final static int ROTATION = 1; + final static int SLIDER = 2; + + /** + * Retrieve the type of the axis. + * The type is describes the meaning and the range of values of the axis. + *

+ * TRANSLATION typed axes denote a translational deviation from a center + * position. This can be e.g. the common, basic joystick axes. + * The range of getValue() is [-1.0,1.0]. + *

+ * ROTATION typed axes denote a rotational deviation from a center + * position. Something on the stick is turned or twisted. + * The range of getValue() is [-1.0,1.0]. + *

+ * SLIDER typed axes denote a shifting device without a center position. + * A good sample is a throttle control. + * The range of getValue() is [0.0,1.0]. + * + * @return [ TRANSLATION | ROTATION | SLIDER ] + */ + int getType(); + + /** + * Returns the current value of the axis. + * The range of the result depends on the axis type. + * + * @return value [-1.0,1.0] or [0.0,1.0] + */ + double getValue(); + + + /** + * Inform about the resolution of the axis. + * + * @return resolution, e.g. 2^-16 + */ + double getResolution(); + +} + + diff --git a/java/de/hardcode/jxinput/Button.java b/java/de/hardcode/jxinput/Button.java new file mode 100644 index 0000000..418e2b6 --- /dev/null +++ b/java/de/hardcode/jxinput/Button.java @@ -0,0 +1,35 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 19. Dezember 2001, 21:58 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * + * @author Herkules + */ +public interface Button extends Feature +{ + // Enumeration of button types + final static int PUSHBUTTON = 0; + final static int TOGGLEBUTTON = 1; + + /** + * Retrieve the type of the button. + * Pushbutton will deliver true==getState() as long as they are pressed down. + * Togglebuttons will change their state once they are pressed and keep that state + * until they are pressed again. + * @return [ PUSHBUTTON | TOGGLEBUTTON ] + */ + int getType(); + + /** + * Tells the state of the button at last update. + */ + boolean getState(); +} + diff --git a/java/de/hardcode/jxinput/Directional.java b/java/de/hardcode/jxinput/Directional.java new file mode 100644 index 0000000..ccd27c1 --- /dev/null +++ b/java/de/hardcode/jxinput/Directional.java @@ -0,0 +1,45 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 23:33 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * + * @author Herkules + */ +public interface Directional extends Feature +{ + /** + * If the Directional has a center position where it points to no direction, this + * flag is true when this position is reached. + */ + boolean isCentered(); + + /** + * Retrieve the direction pointed to. + * Value is given in 1/100 degree, [0,36000] + */ + int getDirection(); + + /** + * Retrieve the analog value pointing to the angle described by + * getDirection(). + * For coolie hats this will be either 1,0 for any direction or 0.0 + * when isCentered()==true. + */ + double getValue(); + + /** + * Inform about the resolution of the value returned by getValue(). + * + * @return resolution, e.g. 1.0 for coolie hats + */ + double getResolution(); + +} + diff --git a/java/de/hardcode/jxinput/Feature.java b/java/de/hardcode/jxinput/Feature.java new file mode 100644 index 0000000..20c396f --- /dev/null +++ b/java/de/hardcode/jxinput/Feature.java @@ -0,0 +1,38 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 00:19 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * An input device offers a set of features (otherwise it would be pretty useless). + * Features in this sense can be axes, buttons and a feature callede directional here. + * Coolie hats are typical directionals because they control a direction (to look at e.g.). + *

+ * There are no concrete classes directly derived from Feature - it only + * provides a basis for other interfaces. + * + * @see Axis + * @see Button + * @see Directional + * + * @author Herkules + */ +public abstract interface Feature +{ + /** + * Features may have a name provided e.g. by the driver. + */ + String getName(); + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + boolean hasChanged(); +} + diff --git a/java/de/hardcode/jxinput/JXInputDevice.java b/java/de/hardcode/jxinput/JXInputDevice.java new file mode 100644 index 0000000..d8a8bc8 --- /dev/null +++ b/java/de/hardcode/jxinput/JXInputDevice.java @@ -0,0 +1,71 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 19. Dezember 2001, 21:47 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * The JXInputDevise is the main entrypoint to the jxinput package. + *

+ * A JXInputDevice represents one physical device like a joystick, a gamepad or + * even some emulation (e.g. using keyboard) that implements the interface. + *

+ * The basis task of a JXInputDevise is to maintain a consistent state of all its features. + *
+ * It is save to distribute the Feature objects into application without worrying + * about someone else performing an update method and thereby destructing the consistent state. + *

+ * An additional task is to provide basic device features information like number of axes, buttons + * and directional features. + * + * @see Feature + * @see JXInputManager + * + * @author Herkules + * @version 0.2beta + */ +public interface JXInputDevice +{ + /** + * @directed + */ + /*#Features lnkFeatures;*/ + + /** + *@link aggregationByValue + */ + /*#Feature lnkFeature;*/ + + /** + * Devices may have a name. + * This name might be provided by a system dependant driver. + */ + String getName(); + + /** Actual number of available axes. */ + int getNumberOfAxes(); + + /** Actual number of available buttons. */ + int getNumberOfButtons(); + + /** Actual number of available directional features. */ + int getNumberOfDirectionals(); + + /** Maximum number of axes as an upper bound for index values. */ + int getMaxNumberOfAxes(); + + /** Maximum number of buttons as an upper bound for index values. */ + int getMaxNumberOfButtons(); + + /** Maximum number of directional features as an upper bound for index values. */ + int getMaxNumberOfDirectionals(); + + Axis getAxis( int idx ); + Button getButton( int idx ); + Directional getDirectional( int idx ); +} + diff --git a/java/de/hardcode/jxinput/JXInputManager.java b/java/de/hardcode/jxinput/JXInputManager.java new file mode 100644 index 0000000..8c3e050 --- /dev/null +++ b/java/de/hardcode/jxinput/JXInputManager.java @@ -0,0 +1,233 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 29. Dezember 2001, 02:17 +//********************************************************************************************** +package de.hardcode.jxinput; + +// +// Import driver stuff +// +import de.hardcode.jxinput.directinput.DirectInputDevice; +import de.hardcode.jxinput.event.JXInputEventManager; +import de.hardcode.jxinput.keyboard.JXKeyboardInputDevice; +import de.hardcode.jxinput.virtual.JXVirtualInputDevice; + + +import java.util.ArrayList; +import java.util.Iterator; +import java.awt.Component; + + +/** + * Manages the available instances of JXInputDevice. + * It holds the one central update method which synchronizes with the physical device. + * @author Herkules + */ +public class JXInputManager +{ + + /** Remember when the last update took place. */ + private static long mTimeOfLastUpdate; + + /** Maintain a list of devices. */ + private final static ArrayList mDevices = new ArrayList(); + + /** Maintain a list of direct input devices. */ + private final static ArrayList mDIDevices = new ArrayList(); + + /** Maintain a list of virtual devices. */ + private final static ArrayList mVirtualDevices = new ArrayList(); + + /** Maintain a list of keyboard devices. */ + private final static ArrayList mKBDevices = new ArrayList(); + + /** + * Statically retrieve all DirectInputDevices available. + */ + static + { + reset(); + } + + + /** + * @directed + */ + /*#JXInputDevice lnkJXInputDevice;*/ + + /** + * Creates a new instance of JXInputManager. + * This is prohibited - it only has static members. + */ + private JXInputManager() + { + } + + + /** + * Retrieve the number of available input devices. + */ + public static int getNumberOfDevices() + { + return mDevices.size(); + } + + /** + * Delivers the JXInputDevice with the desired index. + *

+ * Take care that idx < getNumberOfDevices()! + */ + public static JXInputDevice getJXInputDevice( int idx ) + { + // + // Be well-behaved even if idx is out of range. + // + if ( idx >= mDevices.size() ) + return null; + return (JXInputDevice)mDevices.get( idx ); + } + + + /** + * Master reset for all devices and events. + * After calling reset(), better forget all devices created or retrieved. + * They are no longer valid. + * Event listeners will no longer be called and should be discarded. + */ + synchronized public static void reset() + { + JXInputEventManager.reset(); + + mDevices.clear(); + + mVirtualDevices.clear(); + mDIDevices.clear(); + + DirectInputDevice.reset(); + + for ( int i = 0; i < DirectInputDevice.getNumberOfDevices(); ++i ) + { + DirectInputDevice dev = new DirectInputDevice( i ); + mDevices.add( dev ); + mDIDevices.add( dev ); + } + + // I have to call updateFeatures one time here during initialization + // bc. I experienced difficulties otherwise while running with the + // J3D sensoring stuff! +// updateFeatures(); + DirectInputDevice.update(); + + int n = mKBDevices.size(); + for ( int i = 0; i < n; ++i ) + ((JXKeyboardInputDevice)mKBDevices.get( i )).shutdown(); + mKBDevices.clear(); + } + + + /** + * Update the (shared) state of all features in one step. + * This method asks the actual device for a consistant state. + * After calling this method, all features may have new values. + * updateFeatures() is meant to be called e.g. once per frame in a gaming environment. + */ + public static void updateFeatures() + { + // Get timing + long now = System.currentTimeMillis(); + long deltaT = now - mTimeOfLastUpdate; + + // Update available driver + DirectInputDevice.update(); + + // + // Update the virtual devices. + // + Iterator vdevices = mVirtualDevices.iterator(); + while ( vdevices.hasNext() ) + { + ((JXVirtualInputDevice)vdevices.next()).update( deltaT ); + } + + // Remember time + mTimeOfLastUpdate = now; + + // Fire all events. + JXInputEventManager.trigger(); + } + + + + /** + * Get time when last update occurred. + * @return tickervalue in milliseconds + */ + public static long getLastUpdateTime() + { + return mTimeOfLastUpdate; + } + + + /** + * Create a new pseudo-device. + */ + public static JXKeyboardInputDevice createKeyboardDevice() + { + JXKeyboardInputDevice d = new JXKeyboardInputDevice(); + mDevices.add( d ); + mKBDevices.add( d ); + return d; + } + + + /** + * Create a new pseudo-device listening to a Swing component. + * Make sure that the component also has the keyboard focus!! + */ + public static JXKeyboardInputDevice createKeyboardDevice( Component comp ) + { + JXKeyboardInputDevice d = new JXKeyboardInputDevice( comp ); + mDevices.add( d ); + mKBDevices.add( d ); + return d; + } + + + /** + * Delete a keyboard device again e.g. when the corresponding + * JComponent gets deleted. + */ + public static void deleteKeyboardDevice( JXKeyboardInputDevice dev ) + { + mDevices.remove( dev ); + mKBDevices.remove( dev ); + ((JXKeyboardInputDevice)dev).shutdown(); + } + + + /** + * Create a new pseudo-device. + */ + public static JXVirtualInputDevice createVirtualDevice() + { + JXVirtualInputDevice d = new JXVirtualInputDevice(); + mDevices.add( d ); + mVirtualDevices.add( d ); + return d; + } + + + /** + * Delete a virtual device again. + */ + public static void deleteVirtualDevice( JXVirtualInputDevice dev ) + { + mDevices.remove( dev ); + mVirtualDevices.remove( dev ); + } + +} diff --git a/java/de/hardcode/jxinput/directinput/DIAxis.java b/java/de/hardcode/jxinput/directinput/DIAxis.java new file mode 100644 index 0000000..a6d0eac --- /dev/null +++ b/java/de/hardcode/jxinput/directinput/DIAxis.java @@ -0,0 +1,70 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 00:14 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import de.hardcode.jxinput.Axis; + +/** + * + * @author Herkules + */ +class DIAxis implements Axis +{ + private final int mDeviceIdx; + private final int mIdx; + + /** + * Creates a new instance of DIAxis. + */ + DIAxis( int devidx, int idx ) + { + mDeviceIdx = devidx; + mIdx = idx; + } + + public String getName() + { + return DirectInputDriver.getAxisName( mDeviceIdx, mIdx ); + } + + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + + public double getValue() + { + return DirectInputDriver.getAxisValue( mDeviceIdx, mIdx ); + } + + public int getType() + { + return DirectInputDriver.getAxisType( mDeviceIdx, mIdx ); + } + + /** + * Inform about the resolution of the axis. + * + * @return resolution, e.g. 2^-16 + */ + public double getResolution() + { + // extend the driver here!! + // Here I assume typical 16 bit resolution + return ( getType() == Axis.SLIDER ? 1.0/65536.0 : 2.0/65536.0 ) ; + } + +} + + diff --git a/java/de/hardcode/jxinput/directinput/DIButton.java b/java/de/hardcode/jxinput/directinput/DIButton.java new file mode 100644 index 0000000..5419550 --- /dev/null +++ b/java/de/hardcode/jxinput/directinput/DIButton.java @@ -0,0 +1,55 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 00:14 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import de.hardcode.jxinput.Button; + + +/** + * + * @author Herkules + */ +class DIButton implements Button +{ + private final int mDeviceIdx; + private final int mIdx; + + /** + * Creates a new instance of DIButton. + */ + DIButton( int devidx, int idx ) + { + mDeviceIdx = devidx; + mIdx = idx; + } + + public String getName() + { + return DirectInputDriver.getButtonName( mDeviceIdx, mIdx ); + } + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + + public int getType() + { + return DirectInputDriver.getButtonType( mDeviceIdx, mIdx ); + } + + public boolean getState() + { + return DirectInputDriver.getButtonState( mDeviceIdx, mIdx ); + } +} \ No newline at end of file diff --git a/java/de/hardcode/jxinput/directinput/DIDirectional.java b/java/de/hardcode/jxinput/directinput/DIDirectional.java new file mode 100644 index 0000000..9da2d3d --- /dev/null +++ b/java/de/hardcode/jxinput/directinput/DIDirectional.java @@ -0,0 +1,78 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 23:40 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import de.hardcode.jxinput.Directional; + +/** + * + * @author Herkules + */ +class DIDirectional implements Directional +{ + private final int mDeviceIdx; + private final int mIdx; + + /** + * Creates a new instance of DIDirectional. + */ + DIDirectional( int devidx, int idx ) + { + mDeviceIdx = devidx; + mIdx = idx; + } + + /** Features may have a name provided e.g. by the driver. */ + public String getName() + { + return DirectInputDriver.getDirectionalName( mDeviceIdx, mIdx ); + } + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + + + public boolean isCentered() + { + return ( 0xffff == (DirectInputDriver.getDirection( mDeviceIdx, mIdx ) & 0xffff) ); + } + + public int getDirection() + { + return isCentered() ? 0 : DirectInputDriver.getDirection( mDeviceIdx, mIdx ); + } + + public double getValue() + { + if ( isCentered() ) + return 0.0; + return 1.0; + } + + /** + * Inform about the resolution of the value returned by getValue(). + * + * @return resolution, e.g. 1.0 for coolie hats + */ + public double getResolution() + { + // DI POV always return 0.0 or 1.0, so the resolution is 1.0. + return 1.0; + } + + +} + + diff --git a/java/de/hardcode/jxinput/directinput/DirectInputDevice.java b/java/de/hardcode/jxinput/directinput/DirectInputDevice.java new file mode 100644 index 0000000..a20eab3 --- /dev/null +++ b/java/de/hardcode/jxinput/directinput/DirectInputDevice.java @@ -0,0 +1,170 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 26. Dezember 2001, 00:40 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Axis; +import de.hardcode.jxinput.Directional; +import de.hardcode.jxinput.Button; + +/** + * + * @author Herkules + */ +public class DirectInputDevice implements JXInputDevice +{ + int mDeviceIdx; + + private DIAxis[] mAxes; + private DIButton[] mButtons; + private DIDirectional[] mDirectionals; + + /** + * The number of DirectInput devices available with the driver. + */ + public static int getNumberOfDevices() + { + if ( DirectInputDriver.isAvailable() ) + return DirectInputDriver.getNumberOfDevices(); + return 0; + } + + + /** + * Update the state of all devices. + */ + public static void update() + { + if ( DirectInputDriver.isAvailable() ) + DirectInputDriver.nativeupdate(); + } + + + + + /** + * Creates a new instance of DirectInputDevice. + */ + public DirectInputDevice( int devidx ) + { + mDeviceIdx = devidx; + + init(); + } + + /** + * Reset the DirectInput connection. + */ + public static void reset() + { + if ( DirectInputDriver.isAvailable() ) + DirectInputDriver.reset(); + } + + + /** + * Initialisation of fields. + */ + private final void init() + { + // + // Allocate arrays for max. number of features + // + mAxes = new DIAxis [ getMaxNumberOfAxes() ]; + mButtons = new DIButton [ getMaxNumberOfButtons() ]; + mDirectionals = new DIDirectional [ getMaxNumberOfDirectionals() ]; + + // + // Fill arrays due to the state of the driver. + // + for ( int i = 0; i < mAxes.length; ++i ) + { + if ( DirectInputDriver.isAxisAvailable( mDeviceIdx, i ) ) + mAxes[ i ] = new DIAxis( mDeviceIdx, i ); + } + + for ( int i = 0; i < mButtons.length; ++i ) + { + if ( DirectInputDriver.isButtonAvailable( mDeviceIdx, i ) ) + mButtons[ i ] = new DIButton( mDeviceIdx, i ); + } + + for ( int i = 0; i < mDirectionals.length; ++i ) + { + if ( DirectInputDriver.isDirectionalAvailable( mDeviceIdx, i ) ) + mDirectionals[ i ] = new DIDirectional( mDeviceIdx, i ); + } + } + + /** Devices may have a name. */ + public String getName() + { + String name = DirectInputDriver.getName( mDeviceIdx ); + if ( null == name ) + return "Win32 DirectInput Joystick"; + return name; + } + + + /** Actual number of available buttons. */ + public int getNumberOfButtons() + { + return DirectInputDriver.getNumberOfButtons( mDeviceIdx ); + } + + /** Actual number of available axes. */ + public int getNumberOfAxes() + { + return DirectInputDriver.getNumberOfAxes( mDeviceIdx ); + } + + /** Actual number of available directional features. */ + public int getNumberOfDirectionals() + { + return DirectInputDriver.getNumberOfDirectionals( mDeviceIdx ); + } + + /** Maximum number of buttons as an upper bound for index values. */ + public int getMaxNumberOfButtons() + { + return DirectInputDriver.getMaxNumberOfButtons(); + } + + /** Maximum number of axes as an upper bound for index values. */ + public int getMaxNumberOfAxes() + { + return DirectInputDriver.getMaxNumberOfAxes(); + } + + /** Maximum number of available directional features. */ + public int getMaxNumberOfDirectionals() + { + return DirectInputDriver.getMaxNumberOfDirectionals(); + } + + + public Axis getAxis(int idx) + { + return mAxes[ idx ]; + } + + public Button getButton(int idx) + { + return mButtons[ idx ]; + } + + public Directional getDirectional(int idx) + { + return mDirectionals[ idx ]; + } + +} + + + diff --git a/java/de/hardcode/jxinput/directinput/DirectInputDriver.java b/java/de/hardcode/jxinput/directinput/DirectInputDriver.java new file mode 100644 index 0000000..558f7d8 --- /dev/null +++ b/java/de/hardcode/jxinput/directinput/DirectInputDriver.java @@ -0,0 +1,184 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 19. Dezember 2001, 22:44 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import java.lang.reflect.Array; + +/** + * DirectInputDriver: the connection to the Win32 joystick. + * There is only one allowed, so the layout of this class is merely static. + * + * History: + * + * Changes since 0.1beta: + * - support of multiple devices addressed by the dev index + * + * + * @author Herkules + * @version 0.2beta + */ +class DirectInputDriver +{ + private final static String NATIVE_LIB_NAME = "jxinput"; + + /** Remember wether nativeinit() succeeded. */ + static boolean sIsOperational = false; + + // + // Static arrays to hold the values. + // + private static double [][] sAxisValues; + private static boolean [][] sButtonStates; + private static int [][] sDirectionalValues; + + /** + * Perform the static initialization. + */ + static + { + try + { + // Load the native lib. + System.loadLibrary( NATIVE_LIB_NAME ); + + init(); + } + catch( SecurityException e ) + { + Log.logger.warning("Native library jxinput not loaded due to a SecurityException."); + } + catch( UnsatisfiedLinkError e ) + { + Log.logger.info("Native library jxinput not loaded due to an UnsatisfiedLinkError."); + } + } + + + private final static void init() + { + sIsOperational = false; + // + // Initialize it. + // + if ( nativeinit() ) + { + int devs = getNumberOfDevices(); + sAxisValues = new double [ devs ][ DirectInputDriver.getMaxNumberOfAxes() ]; + sButtonStates = new boolean [ devs ][ DirectInputDriver.getMaxNumberOfButtons() ]; + sDirectionalValues = new int [ devs ][ DirectInputDriver.getMaxNumberOfDirectionals() ]; + + // Bind the native lib to my variables. + bind(); + + // Remember I am fine. + sIsOperational = true; + } + + } + + + /** + * Static ctor of DirectInputDriver. + * No object will be created due to the static layout. + */ + private DirectInputDriver() + { + } + + // Administration + private static native boolean nativeinit(); + private static native void nativeexit(); + private static native void bind(); + + static native int getNumberOfDevices(); + + // Configuration + static native String getName( int dev ); + static native int getNumberOfAxes( int dev ); + static native int getNumberOfButtons( int dev ); + static native int getNumberOfDirectionals( int dev ); + static native int getMaxNumberOfAxes(); + static native int getMaxNumberOfButtons(); + static native int getMaxNumberOfDirectionals(); + + static native boolean isAxisAvailable( int dev, int idx ); + static native String getAxisName( int dev, int idx ); + static native int getAxisType( int dev, int idx ); + + static native boolean isButtonAvailable( int dev, int idx ); + static native String getButtonName( int dev, int idx ); + static native int getButtonType( int dev, int idx ); + + static native boolean isDirectionalAvailable( int dev, int idx ); + static native String getDirectionalName( int dev, int idx ); + + // Operation + static native void nativeupdate(); + + + public static boolean isAvailable() + { + return sIsOperational; + } + + + /** + * Shutdown the device and free all Win32 resources. + * It is not a good idea to access any joystick features after + * shutdown(). + */ + static void shutdown() + { + nativeexit(); + sAxisValues = null; + sButtonStates = null; + sDirectionalValues = null; + } + + + /** + * Reset the device and free all Win32 resources. + */ + static void reset() + { + shutdown(); + init(); + } + + static double getAxisValue( int dev, int idx ) + { + return sAxisValues[ dev ][ idx ]; + } + + static boolean getButtonState( int dev, int idx ) + { + return sButtonStates[ dev ][ idx ]; + } + + static int getDirection( int dev, int idx ) + { + return sDirectionalValues[ dev ][ idx ]; + } + + /** + * @param args the command line arguments + */ + public static void main (String args[]) + { + + if ( ! sIsOperational ) + return; + + for( int i = 0; i < 5000; ++i ) + nativeupdate(); + + shutdown(); + } + +} diff --git a/java/de/hardcode/jxinput/directinput/Log.java b/java/de/hardcode/jxinput/directinput/Log.java new file mode 100644 index 0000000..95e586c --- /dev/null +++ b/java/de/hardcode/jxinput/directinput/Log.java @@ -0,0 +1,34 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 29. Oktober 2002, 22:57 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Herkules + */ +public class Log +{ + public final static Logger logger = Logger.getLogger( Log.class.getPackage().getName() ); + +// static +// { +// logger.setLevel( Level.ALL ); +// } + + /** + * Creates a new instance of Log. + */ + private Log() + { + } + +} diff --git a/java/de/hardcode/jxinput/event/JXInputAxisEvent.java b/java/de/hardcode/jxinput/event/JXInputAxisEvent.java new file mode 100644 index 0000000..c353b5e --- /dev/null +++ b/java/de/hardcode/jxinput/event/JXInputAxisEvent.java @@ -0,0 +1,48 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:33 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Axis; + +/** + * Represents an event coming from an axis. + * @author Joerg Plewe + */ +public class JXInputAxisEvent +{ + private final Axis mAxis; + double mDelta; + + /** + * Creates a new instance of JXInputEvent. + */ + JXInputAxisEvent( Axis axis ) + { + mAxis = axis; + } + + /** + * The feature that caused the event. + */ + public final Axis getAxis() + { + return mAxis; + } + + + /** + * Return the change in value that caused the event. + */ + public double getDelta() + { + return mDelta; + } + +} diff --git a/java/de/hardcode/jxinput/event/JXInputAxisEventListener.java b/java/de/hardcode/jxinput/event/JXInputAxisEventListener.java new file mode 100644 index 0000000..d8adf46 --- /dev/null +++ b/java/de/hardcode/jxinput/event/JXInputAxisEventListener.java @@ -0,0 +1,19 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:54 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +/** + * + * @author Herkules + */ +public interface JXInputAxisEventListener +{ + void changed( JXInputAxisEvent ev ); +} + diff --git a/java/de/hardcode/jxinput/event/JXInputButtonEvent.java b/java/de/hardcode/jxinput/event/JXInputButtonEvent.java new file mode 100644 index 0000000..d82d0b9 --- /dev/null +++ b/java/de/hardcode/jxinput/event/JXInputButtonEvent.java @@ -0,0 +1,38 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:33 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Button; + +/** + * Represents event coming from a button. + * @author Joerg Plewe + */ +public class JXInputButtonEvent +{ + final Button mButton; + + /** + * Creates a new instance of JXInputEvent. + */ + JXInputButtonEvent( Button button ) + { + mButton = button; + } + + /** + * The feature that caused the event. + */ + public final Button getButton() + { + return mButton; + } + +} diff --git a/java/de/hardcode/jxinput/event/JXInputButtonEventListener.java b/java/de/hardcode/jxinput/event/JXInputButtonEventListener.java new file mode 100644 index 0000000..afdc323 --- /dev/null +++ b/java/de/hardcode/jxinput/event/JXInputButtonEventListener.java @@ -0,0 +1,19 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:54 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +/** + * + * @author Herkules + */ +public interface JXInputButtonEventListener +{ + void changed( JXInputButtonEvent ev ); +} + diff --git a/java/de/hardcode/jxinput/event/JXInputDirectionalEvent.java b/java/de/hardcode/jxinput/event/JXInputDirectionalEvent.java new file mode 100644 index 0000000..70e6bcd --- /dev/null +++ b/java/de/hardcode/jxinput/event/JXInputDirectionalEvent.java @@ -0,0 +1,56 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:33 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Directional; + +/** + * Represents an event coming from an axis. + * @author Joerg Plewe + */ +public class JXInputDirectionalEvent +{ + private final Directional mDirectional; + double mValueDelta; + int mDirectionDelta; + + /** + * Creates a new instance of JXInputEvent. + */ + JXInputDirectionalEvent( Directional directional ) + { + mDirectional = directional; + } + + /** + * The feature that caused the event. + */ + public final Directional getDirectional() + { + return mDirectional; + } + + /** + * Return the change in value that caused the event. + */ + public double getValueDelta() + { + return mValueDelta; + } + + /** + * Return the change in direction that caused the event. + */ + public int getDirectionDelta() + { + return mDirectionDelta; + } + +} diff --git a/java/de/hardcode/jxinput/event/JXInputDirectionalEventListener.java b/java/de/hardcode/jxinput/event/JXInputDirectionalEventListener.java new file mode 100644 index 0000000..65c7efa --- /dev/null +++ b/java/de/hardcode/jxinput/event/JXInputDirectionalEventListener.java @@ -0,0 +1,19 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:54 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +/** + * + * @author Herkules + */ +public interface JXInputDirectionalEventListener +{ + void changed( JXInputDirectionalEvent ev ); +} + diff --git a/java/de/hardcode/jxinput/event/JXInputEventManager.java b/java/de/hardcode/jxinput/event/JXInputEventManager.java new file mode 100644 index 0000000..aa196d7 --- /dev/null +++ b/java/de/hardcode/jxinput/event/JXInputEventManager.java @@ -0,0 +1,284 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:42 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +import de.hardcode.jxinput.JXInputManager; +import de.hardcode.jxinput.JXInputDevice; + +import java.util.ArrayList; +import de.hardcode.jxinput.Axis; +import java.util.Iterator; +import de.hardcode.jxinput.Button; +import de.hardcode.jxinput.Directional; + +/** + * Handles all events and listeners. + * JXInputEventManager is layed out a static singleton. + * @author Herkules + */ +public class JXInputEventManager +{ + + private final static ArrayList mAxisEventListeners = new ArrayList(); + private final static ArrayList mButtonEventListeners = new ArrayList(); + private final static ArrayList mDirectionalEventListeners = new ArrayList(); + + private static autotrigger mAutoTrigger = null; + + /** + * Inner class combining a listener with its scheduling parameters. + */ + private static class axislistener + { + final JXInputAxisEventListener mListener; + final double mTreshold; + final JXInputAxisEvent mEvent; + double mLastValueFired = 0.0; + + axislistener( JXInputAxisEventListener l, Axis axis, double treshold ) + { + mListener = l; + mTreshold = treshold; + mEvent = new JXInputAxisEvent( axis ); + } + + final void checkTrigger() + { + double curval = mEvent.getAxis().getValue(); + double delta = curval - mLastValueFired; + + if ( Math.abs( delta ) >= mTreshold ) + { + mLastValueFired = curval; + mEvent.mDelta = delta; + mListener.changed( mEvent ); + } + } + } + + /** + * Inner class combining a listener with its scheduling parameters. + */ + private static class buttonlistener + { + final JXInputButtonEventListener mListener; + final JXInputButtonEvent mEvent; + boolean mLastValueFired = false; + + buttonlistener( JXInputButtonEventListener l, Button button ) + { + mListener = l; + mEvent = new JXInputButtonEvent( button ); + } + + final void checkTrigger() + { + boolean curstate = mEvent.getButton().getState(); + if ( curstate != mLastValueFired ) + { + mLastValueFired = curstate; + mListener.changed( mEvent ); + } + } + } + + + private static class directionallistener + { + final JXInputDirectionalEventListener mListener; + final double mValueTreshold; + final JXInputDirectionalEvent mEvent; + double mLastValueFired = 0.0; + boolean mLastCenteredFired = true; + int mLastDirectionFired = 0; + + directionallistener( JXInputDirectionalEventListener l, Directional directional, double valuetreshold ) + { + mListener = l; + mValueTreshold = valuetreshold; + mEvent = new JXInputDirectionalEvent( directional ); + } + + final void checkTrigger() + { + double curval = mEvent.getDirectional().getValue(); + int curdir = mEvent.getDirectional().getDirection(); + boolean curctr = mEvent.getDirectional().isCentered(); + + double delta = curval - mLastValueFired; + int dirdelta = curdir - mLastDirectionFired; + boolean centeredchanged = mLastCenteredFired != curctr; + + if ( Math.abs( delta ) >= mValueTreshold + || Math.abs( dirdelta ) > 0 + || centeredchanged ) + { + mLastValueFired = curval; + mLastDirectionFired = curdir; + mLastCenteredFired = curctr; + + mEvent.mValueDelta = delta; + mEvent.mDirectionDelta = dirdelta; + mListener.changed( mEvent ); + } + } + } + + /** + * Creates a new instance of JXInputEventManager. + */ + private JXInputEventManager() + { + } + + + /** + * Remove all listeners at once. + */ + public static void reset() + { + mAxisEventListeners.clear(); + mButtonEventListeners.clear(); + mDirectionalEventListeners.clear(); + } + + + /** + * Query devices and fire all occuring events. + * trigger() is thought to be called by JXInputManager#updateFeatures(). + */ + public static void trigger() + { + int n = mAxisEventListeners.size(); + for ( int i = 0; i < n; i++ ) + { + axislistener l = (axislistener)mAxisEventListeners.get( i ); + l.checkTrigger(); + } + + n = mButtonEventListeners.size(); + for ( int i = 0; i < n; i++ ) + { + buttonlistener l = (buttonlistener)mButtonEventListeners.get( i ); + l.checkTrigger(); + } + + n = mDirectionalEventListeners.size(); + for ( int i = 0; i < n; i++ ) + { + directionallistener l = (directionallistener)mDirectionalEventListeners.get( i ); + l.checkTrigger(); + } + } + + + private final static class autotrigger extends Thread + { + boolean mFinish = false; + final int mDelay; + + autotrigger( int delay ) + { + mDelay = delay; + } + + public void run() + { + while ( ! mFinish ) + { + try + { + Thread.sleep( mDelay ); + JXInputManager.updateFeatures(); + } + catch ( InterruptedException ex ) + { + } + } + } + } + + + /** + * Set the intervall in ms that is used to check for new values of the features. + * Set it to <= 0 to prohibit automatic triggering. Events will then only be fired + * when somebody invokes JXInputManager#updateFeatures(). + */ + public static void setTriggerIntervall( int ms ) + { + // + // Kill current thread, if any + // + if ( null != mAutoTrigger ) + { + mAutoTrigger.mFinish = true; + try + { + mAutoTrigger.join(); + } + catch ( InterruptedException ex ) + { + } + } + + mAutoTrigger = null; + + if ( ms > 0 ) + { + mAutoTrigger = new autotrigger( ms ); + mAutoTrigger.start(); + } + + } + + + + + public static void addListener( JXInputAxisEventListener l, Axis axis, double treshold ) + { + mAxisEventListeners.add( new JXInputEventManager.axislistener( l, axis, treshold ) ); + } + + public static void addListener( JXInputAxisEventListener l, Axis axis ) + { + mAxisEventListeners.add( new JXInputEventManager.axislistener( l, axis, axis.getResolution() ) ); + } + + public static void removeListener( JXInputAxisEventListener l ) + { + mAxisEventListeners.remove( l ); + } + + + public static void addListener( JXInputButtonEventListener l, Button button ) + { + mButtonEventListeners.add( new JXInputEventManager.buttonlistener( l, button ) ); + } + + public static void removeListener( JXInputButtonEventListener l ) + { + mButtonEventListeners.remove( l ); + } + + public static void addListener( JXInputDirectionalEventListener l, Directional directional, double valuetreshold ) + { + mDirectionalEventListeners.add( new JXInputEventManager.directionallistener( l, directional, valuetreshold ) ); + } + + public static void addListener( JXInputDirectionalEventListener l, Directional directional ) + { + mDirectionalEventListeners.add( new JXInputEventManager.directionallistener( l, directional, directional.getResolution() ) ); + } + + public static void removeListener( JXInputDirectionalEventListener l ) + { + mDirectionalEventListeners.remove( l ); + } + +} diff --git a/java/de/hardcode/jxinput/j3d/DeviceConfiguration.java b/java/de/hardcode/jxinput/j3d/DeviceConfiguration.java new file mode 100644 index 0000000..8c1288a --- /dev/null +++ b/java/de/hardcode/jxinput/j3d/DeviceConfiguration.java @@ -0,0 +1,95 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 23. Februar 2002, 14:05 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +import de.hardcode.jxinput.Axis; + + +/** + * Connects JXInput with J3DInputDevice. + * + * @author Herkules + */ +public class DeviceConfiguration +{ + public final static int AXIS_X = 0; + public final static int AXIS_Y = 1; + public final static int AXIS_Z = 2; + + private final static class axisvalue + { + private final Axis mAxis; + private final IsActiveCondition mIsActive; + private final IsActiveCondition mIsIncremental; + private final double mScale; + private final double mOffset; + private double mValue; + + axisvalue( Axis axis, IsActiveCondition active, IsActiveCondition incremental, double offset, double scale ) + { + mAxis = axis; + mIsActive = active; + mIsIncremental = incremental; + mValue = mOffset = offset; + mScale = scale; + } + + double value() + { + if ( mIsActive.isActive() ) + { + double newval = mAxis.getValue() * mScale; + + if ( mIsIncremental.isActive() ) + mValue += newval; + else + mValue = newval + mOffset; + } + return mValue; + } + } + + DeviceConfiguration.axisvalue [] mAxisTrans = new DeviceConfiguration.axisvalue[ 3 ]; + DeviceConfiguration.axisvalue [] mAxisRot = new DeviceConfiguration.axisvalue[ 3 ]; + + /** + * Creates a new instance of DeviceConfiguration. + */ + public DeviceConfiguration() + { + } + + + double getTranslational( int axisid ) + { + DeviceConfiguration.axisvalue val = mAxisTrans[ axisid ]; + return null == val ? 0.0 : val.value(); + } + + double getRotational( int axisid ) + { + DeviceConfiguration.axisvalue val = mAxisRot[ axisid ]; + return null == val ? 0.0 : val.value(); + } + + public void setTranslational( int axisid, Axis axis, IsActiveCondition active, IsActiveCondition incremental, double offset, double scale ) + { + if ( axisid < 0 || axisid > AXIS_Z ) + throw new IllegalArgumentException(); + mAxisTrans[ axisid ] = new DeviceConfiguration.axisvalue( axis, active, incremental, offset, scale ); + } + + public void setRotational( int axisid, Axis axis, IsActiveCondition active, IsActiveCondition incremental, double offset, double scale ) + { + if ( axisid < 0 || axisid > AXIS_Z ) + throw new IllegalArgumentException(); + mAxisRot[ axisid ] = new DeviceConfiguration.axisvalue( axis, active, incremental, offset, scale ); + } + +} diff --git a/java/de/hardcode/jxinput/j3d/IsActiveCondition.java b/java/de/hardcode/jxinput/j3d/IsActiveCondition.java new file mode 100644 index 0000000..af6ca08 --- /dev/null +++ b/java/de/hardcode/jxinput/j3d/IsActiveCondition.java @@ -0,0 +1,25 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 25. Februar 2002, 22:41 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +/** + * + * @author Herkules + */ +public interface IsActiveCondition +{ + public final static IsActiveCondition ALWAYS = IsAlwaysActiveCondition.ALWAYS; + public final static IsActiveCondition NEVER = IsAlwaysActiveCondition.NEVER; + + /** + * Tell wether a certain thing is active. + */ + boolean isActive(); +} + diff --git a/java/de/hardcode/jxinput/j3d/IsActiveOnButtonCondition.java b/java/de/hardcode/jxinput/j3d/IsActiveOnButtonCondition.java new file mode 100644 index 0000000..98da7bb --- /dev/null +++ b/java/de/hardcode/jxinput/j3d/IsActiveOnButtonCondition.java @@ -0,0 +1,39 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 25. Februar 2002, 22:43 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +import de.hardcode.jxinput.Button; + +/** + * + * @author Herkules + */ +public class IsActiveOnButtonCondition implements IsActiveCondition +{ + private final boolean mActiveState; + private final Button mButton; + + /** + * Creates a new instance of IsAlwayActiveCondition. + */ + public IsActiveOnButtonCondition( Button button, boolean activestate ) + { + mActiveState = activestate; + mButton = button; + } + + /** + * Tell wether a certain thing is active. + */ + public boolean isActive() + { + return mButton.getState() == mActiveState; + } + +} diff --git a/java/de/hardcode/jxinput/j3d/IsAlwaysActiveCondition.java b/java/de/hardcode/jxinput/j3d/IsAlwaysActiveCondition.java new file mode 100644 index 0000000..cd8b1fe --- /dev/null +++ b/java/de/hardcode/jxinput/j3d/IsAlwaysActiveCondition.java @@ -0,0 +1,38 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 25. Februar 2002, 22:43 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +/** + * + * @author Herkules + */ +final class IsAlwaysActiveCondition implements IsActiveCondition +{ + private final boolean mIsActive; + + public final static IsActiveCondition ALWAYS = new IsAlwaysActiveCondition( true ); + public final static IsActiveCondition NEVER = new IsAlwaysActiveCondition( false ); + + /** + * Creates a new instance of IsAlwayActiveCondition. + */ + private IsAlwaysActiveCondition(boolean isactive) + { + mIsActive = isactive; + } + + /** + * Tell wether a certain thing is active. + */ + public boolean isActive() + { + return mIsActive; + } + +} diff --git a/java/de/hardcode/jxinput/j3d/J3DInputDevice.java b/java/de/hardcode/jxinput/j3d/J3DInputDevice.java new file mode 100644 index 0000000..f5b08f2 --- /dev/null +++ b/java/de/hardcode/jxinput/j3d/J3DInputDevice.java @@ -0,0 +1,171 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 22. Februar 2002, 13:21 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +import javax.media.j3d.InputDevice; +import javax.media.j3d.Sensor; +import javax.media.j3d.SensorRead; +import javax.vecmath.Vector3d; +import javax.media.j3d.Transform3D; +import de.hardcode.jxinput.JXInputManager; + + +/** + * Implementation of Java3D's InputDevice + * + * @author Herkules + */ +public class J3DInputDevice + implements InputDevice +{ + private Vector3d mPosition = new Vector3d(); + private Transform3D mNewTransform = new Transform3D(); + + private Transform3D mRotTransX = new Transform3D(); + private Transform3D mRotTransY = new Transform3D(); + private Transform3D mRotTransZ = new Transform3D(); + + private Vector3d mInitPos = new Vector3d( 0.0, 0.0, 0.0 ); + + private Sensor mSensor = new Sensor( this ); + private SensorRead mSensorRead = new SensorRead(); + + private DeviceConfiguration mConfig; + + /** + * Creates a new instance of J3DInputDevice. + */ + public J3DInputDevice( DeviceConfiguration config ) + { + mConfig = config; + setNominalPositionAndOrientation(); + } + + + public void close() + { + // Intentionally empty + } + + + /** + * Retrieve processing mode. + * For this device, it always is NON_BLOCKING. + */ + public int getProcessingMode() + { + return InputDevice.NON_BLOCKING; + } + + + /** + * Don't care for the index, I only support one sensor. + * And I deliver that. + */ + public Sensor getSensor( int param ) + { + return mSensor; + } + + + /** + * Tell the world about the only one sensor I support. + */ + public int getSensorCount() + { + return 1; + } + + + /** + * Well - initialize! + * Nothing to do here. + */ + public boolean initialize() + { + return true; + } + + + /** + * The main update method. + */ + public void pollAndProcessInput() + { + JXInputManager.updateFeatures(); + + mSensorRead.setTime( JXInputManager.getLastUpdateTime() ); + + mRotTransX.rotX( mConfig.getRotational( DeviceConfiguration.AXIS_X ) ); + mRotTransY.rotY( mConfig.getRotational( DeviceConfiguration.AXIS_Y ) ); + mRotTransZ.rotZ( mConfig.getRotational( DeviceConfiguration.AXIS_Z ) ); + + mPosition.set( + mConfig.getTranslational( DeviceConfiguration.AXIS_X ), + mConfig.getTranslational( DeviceConfiguration.AXIS_Y ), + mConfig.getTranslational( DeviceConfiguration.AXIS_Z ) + ); + + mNewTransform.set( mPosition ); + + mNewTransform.mul( mRotTransX ); + mNewTransform.mul( mRotTransY ); + mNewTransform.mul( mRotTransZ ); + + mSensorRead.set( mNewTransform ); + mSensor.setNextSensorRead( mSensorRead ); + } + + + /** + * Not called by current j3d implementation. + */ + public void processStreamInput() + { + // Intentionally empty + } + + + /** + * Reset state. + */ + public void setNominalPositionAndOrientation() + { + mSensorRead.setTime( JXInputManager.getLastUpdateTime() ); + + mRotTransX.rotX( 0.0 ); + mRotTransY.rotY( 0.0 ); + mRotTransZ.rotZ( 0.0 ); + + mPosition.set( mInitPos ); + + mNewTransform.set( mPosition ); + + mNewTransform.mul( mRotTransX ); + mNewTransform.mul( mRotTransY ); + mNewTransform.mul( mRotTransZ ); + + mSensorRead.set( mNewTransform ); + mSensor.setNextSensorRead( mSensorRead ); + + } + + + /** + * Set the processing mode. + * Only NON_BLOCKING is allowed! + */ + public void setProcessingMode(int param) + { + if ( param != InputDevice.NON_BLOCKING ) + throw new IllegalArgumentException("Processing mode must be NON_BLOCKING"); + + } + +} diff --git a/java/de/hardcode/jxinput/j3d/package.html b/java/de/hardcode/jxinput/j3d/package.html new file mode 100644 index 0000000..9b92964 --- /dev/null +++ b/java/de/hardcode/jxinput/j3d/package.html @@ -0,0 +1,11 @@ + + + + + + + +Connecting JXInput to Java3D by implementing the interface +javax.media.j3d.InputDevice. + + diff --git a/java/de/hardcode/jxinput/j3d/test/HelloUniverse.java b/java/de/hardcode/jxinput/j3d/test/HelloUniverse.java new file mode 100644 index 0000000..fde34bc --- /dev/null +++ b/java/de/hardcode/jxinput/j3d/test/HelloUniverse.java @@ -0,0 +1,205 @@ + +/* + * @(#)HelloUniverse.java 1.15 02/02/07 14:48:36 + * + * Copyright (c) 1996-2002 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: + * + * - Redistributions 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 materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES + * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THE 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 OR INABILITY TO USE SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed,licensed or intended + * for use in the design, construction, operation or maintenance of + * any nuclear facility. + */ + +package de.hardcode.jxinput.j3d.test; + + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import com.sun.j3d.utils.applet.MainFrame; +import com.sun.j3d.utils.geometry.ColorCube; +import com.sun.j3d.utils.universe.*; +import javax.media.j3d.*; +import javax.vecmath.*; +import de.hardcode.jxinput.j3d.DeviceConfiguration; +import de.hardcode.jxinput.Axis; +import de.hardcode.jxinput.JXInputManager; +import de.hardcode.jxinput.j3d.IsActiveCondition; +import de.hardcode.jxinput.j3d.J3DInputDevice; +import de.hardcode.jxinput.j3d.IsActiveOnButtonCondition; + + +public class HelloUniverse extends Applet +{ + + private SimpleUniverse u = null; + TransformGroup objTrans; + + public BranchGroup createSceneGraph() + { + BranchGroup objRoot = new BranchGroup(); + objTrans = new TransformGroup(); + objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); + objRoot.addChild(objTrans); + objTrans.addChild(new ColorCube(0.4)); + +// Transform3D yAxis = new Transform3D(); +// Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, +// 0, 0, +// 4000, 0, 0, +// 0, 0, 0); +// RotationInterpolator rotator = new RotationInterpolator(rotationAlpha, objTrans, yAxis, +// 0.0f, (float) Math.PI*2.0f); +// BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); +// rotator.setSchedulingBounds(bounds); +// objTrans.addChild(rotator); + return objRoot; + } + + + public HelloUniverse() + { + + } + + public void init() + { + // These are the string arguments given to the VirtualInputDevice + // constructor. These are settable parameters. Look in the + // VirtualInputDevice constructor for a complete list. + String[] args = new String[10]; + args[0] = "printvalues"; + args[1] = "true"; + args[2] = "yscreeninitloc"; + args[3] = "50"; + args[4] = null; + + + // now create the HelloUniverse Canvas + setLayout(new BorderLayout()); + GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); + + Canvas3D c = new Canvas3D(config); + add("Center", c); + + // Create a simple scene and attach it to the virtual universe + BranchGroup scene = createSceneGraph(); + u = new SimpleUniverse(c); + + // + // Use the inputdevice + // + InputDevice device = createInputDevice(); + + // Register the VirtualInputDevice with Java 3D + u.getViewer().getPhysicalEnvironment().addInputDevice( device ); + +// TransformGroup viewTrans = u.getViewingPlatform().getViewPlatformTransform(); + + // Put the behavoir to teh object + SensorBehavior s = new SensorBehavior( objTrans, device.getSensor(0) ); + s.setSchedulingBounds( new BoundingSphere( new Point3d(0.0,0.0,0.0), Float.MAX_VALUE ) ); + objTrans.addChild( s ); + + u.getViewingPlatform().setNominalViewingTransform(); + u.addBranchGraph(scene); + } + + public void destroy() + { + u.removeAllLocales(); + } + + + /** + * Setup an input device. + */ + private InputDevice createInputDevice() + { + IsActiveCondition button1down = new IsActiveOnButtonCondition(JXInputManager.getJXInputDevice( 0 ).getButton( 0 ), true ); + IsActiveCondition button1up = new IsActiveOnButtonCondition(JXInputManager.getJXInputDevice( 0 ).getButton( 0 ), false ); + + Axis xaxis = JXInputManager.getJXInputDevice( 0 ).getAxis( Axis.ID_X ); + Axis yaxis = JXInputManager.getJXInputDevice( 0 ).getAxis( Axis.ID_Y ); + + DeviceConfiguration cnf = new DeviceConfiguration(); + + // + // Setup the configuration to use joysticks x/y for rotation is not button is pressed + // and for translation if button1 is pressed. + // + cnf.setRotational( + DeviceConfiguration.AXIS_Y, + xaxis, + button1up, + IsActiveCondition.NEVER, + 0.0, Math.PI + ); + + cnf.setRotational( + DeviceConfiguration.AXIS_X, + yaxis, + button1up, + IsActiveCondition.NEVER, + 0.0, Math.PI + ); + + cnf.setTranslational( + DeviceConfiguration.AXIS_Z, + yaxis, + button1down, + IsActiveCondition.NEVER, + -5.0, 4.0 + ); + cnf.setTranslational( + DeviceConfiguration.AXIS_X, + xaxis, + button1down, + IsActiveCondition.NEVER, + 0.0, 4.0 + ); + + // We have the config, create the device... + J3DInputDevice d = new J3DInputDevice( cnf ); + + // The InputDevice must be initialized before registering it + // with the PhysicalEnvironment object. + d.initialize(); + + return d; + } + + + public static void main(String[] args) + { + new MainFrame(new HelloUniverse(), 350, 350); + } +} diff --git a/java/de/hardcode/jxinput/j3d/test/SensorBehavior.java b/java/de/hardcode/jxinput/j3d/test/SensorBehavior.java new file mode 100644 index 0000000..6836ebb --- /dev/null +++ b/java/de/hardcode/jxinput/j3d/test/SensorBehavior.java @@ -0,0 +1,70 @@ +package de.hardcode.jxinput.j3d.test; + +/* + * @(#)SensorBehavior.java 1.8 02/02/07 14:48:34 + * + * Copyright (c) 1996-2002 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: + * + * - Redistributions 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 materials provided with the + * distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES + * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THE 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 OR INABILITY TO USE SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed,licensed or intended + * for use in the design, construction, operation or maintenance of + * any nuclear facility. + */ + +import javax.media.j3d.*; +import java.util.*; + +public class SensorBehavior extends Behavior +{ + private WakeupOnElapsedFrames conditions = new WakeupOnElapsedFrames(0); + private TransformGroup transformGroup; + private Sensor sensor; + private Transform3D transform = new Transform3D(); + + public SensorBehavior( TransformGroup tg, Sensor sensor ) + { + transformGroup = tg; + this.sensor = sensor; + } + + public void initialize() + { + wakeupOn( conditions ); + } + + public void processStimulus( Enumeration criteria ) + { + sensor.getRead( transform ); + transformGroup.setTransform( transform ); + wakeupOn( conditions ); + } + +} diff --git a/java/de/hardcode/jxinput/keyboard/InvalidKeyCodeException.java b/java/de/hardcode/jxinput/keyboard/InvalidKeyCodeException.java new file mode 100644 index 0000000..f44ee6b --- /dev/null +++ b/java/de/hardcode/jxinput/keyboard/InvalidKeyCodeException.java @@ -0,0 +1,35 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 16. April 2002, 23:31 +//********************************************************************************************** +package de.hardcode.jxinput.keyboard; + +/** + * Exeception to be thrown if keycode is not in then range [0,255]. + * + * @author Herkules + */ +public class InvalidKeyCodeException + extends IllegalArgumentException +{ + + /** + * Creates a new instance of InvalidKeyCodeException. + */ + public InvalidKeyCodeException() + { + } + + + /** + * Creates a new instance of InvalidKeyCodeException. + */ + public InvalidKeyCodeException( String s ) + { + super( s ); + } +} diff --git a/java/de/hardcode/jxinput/keyboard/JXKeyboardInputDevice.java b/java/de/hardcode/jxinput/keyboard/JXKeyboardInputDevice.java new file mode 100644 index 0000000..858bdb7 --- /dev/null +++ b/java/de/hardcode/jxinput/keyboard/JXKeyboardInputDevice.java @@ -0,0 +1,175 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:40 +//********************************************************************************************** +package de.hardcode.jxinput.keyboard; + + +import de.hardcode.jxinput.*; +import java.awt.Component; + + +/** + * Virtual input device treating a AWT keyboard as a source for Buttons. + * + * @author Herkules + */ +public class JXKeyboardInputDevice + implements JXInputDevice +{ + private static final String DEVICENAME = "Swing Keyboard"; + + /** The driver doing all the real work. */ + private final KeyboardDriver mDriver = new KeyboardDriver(); + + /** The Component I am listening to. */ + private Component mComponent = null; + + /** Hold the biggest keycode for which a button has been created. */ + private int mMaxIdxCreated = 0; + + + /** + * Creates a new instance of JXKeyboardInputDevice. + */ + public JXKeyboardInputDevice() + { + } + + + /** + * Creates a new instance of JXKeyboardInputDevice + * immediately listening to a JComponent. + */ + public JXKeyboardInputDevice( Component comp ) + { + listenTo( comp ); + } + + /** + * Makes this device listen to a certain JComponent. + */ + public final void listenTo( Component comp ) + { + shutdown(); + mComponent = comp; + mComponent.addKeyListener( mDriver ); + } + + /** + * Shut down. No longer listen to my JComponent. + */ + public final void shutdown() + { + if ( null != mComponent ) + mComponent.removeKeyListener( mDriver ); + } + + + /** + * Create a button object for a certain keycode. + */ + public Button createButton( int keycode ) + { + if ( 0 > keycode || 0x100 < keycode ) + throw new InvalidKeyCodeException(); + + KeyButton b; + if ( null == (b = mDriver.getButton( keycode ) ) ) + { + b = new KeyButton( keycode ); + mDriver.registerKeyButton( b ); + if ( keycode > mMaxIdxCreated ) + mMaxIdxCreated = keycode; + } + return b; + } + + + public void removeButton( Button b ) + { + mDriver.unregisterKeyButton( (KeyButton) b ); + } + + + + //********************************************************************************************* + // + // Implement JXInputDevice + // + //********************************************************************************************* + + public Axis getAxis(int idx) + { + // No axes on keyboard. + return null; + } + + + public Button getButton(int idx) + { + // idx is interpreted as the keycode + return mDriver.getButton( idx ); + } + + public Directional getDirectional(int idx) + { + // No directionals on keyboard. + return null; + } + + /** Maximum number of axes as an upper bound for index values. */ + public int getMaxNumberOfAxes() + { + // No axes on keyboard. + return 0; + } + + /** Maximum number of buttons as an upper bound for index values. */ + public int getMaxNumberOfButtons() + { + // Return biggest keycode (inclusive). + return mMaxIdxCreated + 1; + } + + /** Maximum number of directional features as an upper bound for index values. */ + public int getMaxNumberOfDirectionals() + { + // No directionals on keyboard. + return 0; + } + + /** + * Devices may have a name. + * This name might be provided by a system dependant driver. + */ + public String getName() + { + return DEVICENAME; + } + + /** Actual number of available axes. */ + public int getNumberOfAxes() + { + // No axes on keyboard. + return 0; + } + + /** Actual number of available buttons. */ + public int getNumberOfButtons() + { + return mDriver.getNumberOfButtons(); + } + + /** Actual number of available directional features. */ + public int getNumberOfDirectionals() + { + // No directionals on keyboard. + return 0; + } + +} diff --git a/java/de/hardcode/jxinput/keyboard/KeyButton.java b/java/de/hardcode/jxinput/keyboard/KeyButton.java new file mode 100644 index 0000000..3fd7130 --- /dev/null +++ b/java/de/hardcode/jxinput/keyboard/KeyButton.java @@ -0,0 +1,94 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:51 +//********************************************************************************************** +package de.hardcode.jxinput.keyboard; + +import de.hardcode.jxinput.Button; +import java.awt.event.KeyEvent; + + +/** + * Associates a keycode with a Button and handles the current state of that button. + * + * @author Herkules + */ +class KeyButton + implements Button +{ + private final int mKeyCode; + private boolean mIsPressed; + private boolean mHasChanged; + + /** + * Creates a new instance of KeyButton. + */ + public KeyButton( int keycode ) + { + mKeyCode = keycode; + } + + + /** + * Return the keycode assigned with this button. + */ + public final int getKeyCode() + { + return mKeyCode; + } + + final void setIsPressed( boolean flag ) + { + mIsPressed = flag; + } + + //********************************************************************************************* + // + // Implement Button + // + //********************************************************************************************* + + + /** + * Features may have a name provided e.g. by the driver. + */ + public String getName() + { + return KeyEvent.getKeyText( mKeyCode ); + } + + /** + * Tells the state of the button at last update. + */ + public boolean getState() + { + return mIsPressed; + } + + /** + * Retrieve the type of the button. + * Pushbutton will deliver true==getState() as long as they are pressed down. + * Togglebuttons will change their state once they are pressed and keep that state + * until they are pressed again. + * @return [ PUSHBUTTON | TOGGLEBUTTON ] + */ + public int getType() + { + return Button.PUSHBUTTON; + } + + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + +} diff --git a/java/de/hardcode/jxinput/keyboard/KeyboardDriver.java b/java/de/hardcode/jxinput/keyboard/KeyboardDriver.java new file mode 100644 index 0000000..7eb6232 --- /dev/null +++ b/java/de/hardcode/jxinput/keyboard/KeyboardDriver.java @@ -0,0 +1,141 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:43 +//********************************************************************************************** +package de.hardcode.jxinput.keyboard; + +import java.awt.event.KeyListener; +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.security.InvalidParameterException; + + + +/** + * Listen to a JComponent handle handle all associated button objects. + * This is the main worker class for JXKeyboardInputDevice. + * + * @author Herkules + */ +class KeyboardDriver implements KeyListener +{ +// HashMap mKeysToObserveMap = new HashMap(); + + int mNumberOfKeysObserved = 0; + KeyButton [] mKeysObserved = new KeyButton [ 0x100 ]; + + + /** + * Creates a new instance of KeyboardDriver. + */ + public KeyboardDriver() + { + } + + + /** + * How many buttons are registered? + */ + final int getNumberOfButtons() + { + return mNumberOfKeysObserved; +// return mKeysToObserveMap.size(); + } + + + /** + * Place a new button under my observation. + */ + final boolean registerKeyButton( KeyButton b ) + { + final int keycode = b.getKeyCode(); + + if ( 0 > keycode || 0x100 < keycode ) + throw new InvalidKeyCodeException(); + + if ( null == mKeysObserved[ keycode ] ) + { + mKeysObserved[ keycode ] = b; + mNumberOfKeysObserved++; + return true; + } + else + { + return false; + } + +// Integer code = new Integer( b.getKeyCode() ); +// if ( ! mKeysToObserveMap.containsKey( code ) ) +// { +// mKeysToObserveMap.put( code, b ); +// return true; +// } +// else +// { +// return false; +// } + } + + final void unregisterKeyButton( KeyButton b ) + { + final int keycode = b.getKeyCode(); + + if ( 0 > keycode || 0x100 < keycode ) + throw new InvalidKeyCodeException(); + + if ( null != mKeysObserved[ b.getKeyCode() ] ) + { + mKeysObserved[ keycode ] = null; + mNumberOfKeysObserved--; + } + +// Integer code = new Integer( b.getKeyCode() ); +// mKeysToObserveMap.remove( code ); + } + + + /** + * Retrieve the button from its keycode. + */ + final KeyButton getButton( int keycode ) + { + if ( 0 > keycode || 0x100 < keycode ) + throw new InvalidKeyCodeException(); + + return mKeysObserved[ keycode ]; + +// Integer code = new Integer( keycode ); +// return (KeyButton)mKeysToObserveMap.get( code ); + } + + + //********************************************************************************************* + // + // Implement KeyListener + // + //********************************************************************************************* + + public void keyPressed( KeyEvent keyEvent ) + { + KeyButton b = getButton( keyEvent.getKeyCode() ); + if ( null != b ) + b.setIsPressed( true ); + } + + public void keyReleased( KeyEvent keyEvent ) + { + KeyButton b = getButton( keyEvent.getKeyCode() ); + if ( null != b ) + b.setIsPressed( false ); + } + + public void keyTyped( KeyEvent keyEvent ) + { + // Intentionally empty. + } + +} diff --git a/java/de/hardcode/jxinput/keyboard/package.html b/java/de/hardcode/jxinput/keyboard/package.html new file mode 100644 index 0000000..e1021d1 --- /dev/null +++ b/java/de/hardcode/jxinput/keyboard/package.html @@ -0,0 +1,10 @@ + + + + + de.hardcode.jxinput.keyboard + + +Connects Swing keyboard handling to the JXInput infrastructure. + + diff --git a/java/de/hardcode/jxinput/package.html b/java/de/hardcode/jxinput/package.html new file mode 100644 index 0000000..c449914 --- /dev/null +++ b/java/de/hardcode/jxinput/package.html @@ -0,0 +1,15 @@ + + + + + + + +JXInput by HARDCODE Dev., Dipl. Phys. Joerg Plewe. +

+JXInput connects gaming input devices like joysticks or gamepads to the Java +environment. +

+Comments send to jxinput@hardcode.de. + + diff --git a/java/de/hardcode/jxinput/test/AxisListener.java b/java/de/hardcode/jxinput/test/AxisListener.java new file mode 100644 index 0000000..7d2b138 --- /dev/null +++ b/java/de/hardcode/jxinput/test/AxisListener.java @@ -0,0 +1,39 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 20. Februar 2002, 22:19 +//********************************************************************************************** +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.event.JXInputEventManager; +import de.hardcode.jxinput.event.JXInputAxisEventListener; +import de.hardcode.jxinput.event.JXInputAxisEvent; +import de.hardcode.jxinput.Axis; + +/** + * Example listener to an axis. + * + * @author Herkules + */ +public class AxisListener + implements JXInputAxisEventListener +{ + + /** + * Creates a new instance of AxisListener. + */ + public AxisListener( Axis axis ) + { + JXInputEventManager.addListener( this, axis, 0.1 ); + } + + + public void changed( JXInputAxisEvent ev ) + { + System.out.println( "Axis " + ev.getAxis().getName() + " changed : value=" + ev.getAxis().getValue() + ", event causing delta=" + ev.getDelta() ); + } + +} diff --git a/java/de/hardcode/jxinput/test/ButtonListener.java b/java/de/hardcode/jxinput/test/ButtonListener.java new file mode 100644 index 0000000..604002d --- /dev/null +++ b/java/de/hardcode/jxinput/test/ButtonListener.java @@ -0,0 +1,38 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 20. Februar 2002, 22:19 +//********************************************************************************************** +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.event.JXInputEventManager; +import de.hardcode.jxinput.event.JXInputButtonEventListener; +import de.hardcode.jxinput.event.JXInputButtonEvent; +import de.hardcode.jxinput.Button; + +/** + * Sample button listener. + * + * @author Herkules + */ +public class ButtonListener implements JXInputButtonEventListener +{ + + /** + * Creates a new instance of AxisListener. + */ + public ButtonListener( Button button ) + { + JXInputEventManager.addListener( this, button ); + } + + + public void changed( JXInputButtonEvent ev ) + { + System.out.println( "Button " + ev.getButton().getName() + " changed : state=" + ev.getButton().getState() ); + } + +} diff --git a/java/de/hardcode/jxinput/test/DirectionalListener.java b/java/de/hardcode/jxinput/test/DirectionalListener.java new file mode 100644 index 0000000..9f79796 --- /dev/null +++ b/java/de/hardcode/jxinput/test/DirectionalListener.java @@ -0,0 +1,37 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 20. Februar 2002, 22:19 +//********************************************************************************************** +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.event.JXInputEventManager; +import de.hardcode.jxinput.event.JXInputDirectionalEventListener; +import de.hardcode.jxinput.event.JXInputDirectionalEvent; +import de.hardcode.jxinput.Directional; + +/** + * Sample directional listener. + * + * @author Herkules + */ +public class DirectionalListener implements JXInputDirectionalEventListener +{ + /** + * Creates a new instance of AxisListener. + */ + public DirectionalListener( Directional directional ) + { + JXInputEventManager.addListener( this, directional, 1.0 ); + } + + + public void changed( JXInputDirectionalEvent ev ) + { + System.out.println( "Directional " + ev.getDirectional().getName() + " changed : direction=" + ev.getDirectional().getDirection() + ", value=" + ev.getDirectional().getValue() + ", event causing delta=" + ev.getDirectionDelta() ); + } + +} diff --git a/java/de/hardcode/jxinput/test/JXInputDevicePanel.form b/java/de/hardcode/jxinput/test/JXInputDevicePanel.form new file mode 100644 index 0000000..fe9f69e --- /dev/null +++ b/java/de/hardcode/jxinput/test/JXInputDevicePanel.form @@ -0,0 +1,97 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/java/de/hardcode/jxinput/test/JXInputDevicePanel.java b/java/de/hardcode/jxinput/test/JXInputDevicePanel.java new file mode 100644 index 0000000..81fbef3 --- /dev/null +++ b/java/de/hardcode/jxinput/test/JXInputDevicePanel.java @@ -0,0 +1,296 @@ +/* + * JXInputDevicePanel.java + * + * Created on 23. Januar 2002, 22:19 + */ +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.JXInputManager; +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Axis; +import de.hardcode.jxinput.Directional; +import de.hardcode.jxinput.Button; + +import javax.swing.*; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.Iterator; +import java.awt.BorderLayout; +import java.awt.Font; +import java.util.Dictionary; +import java.util.Enumeration; + +/** + * + * @author Herkules + */ +public class JXInputDevicePanel extends javax.swing.JPanel +{ + private static final Font AXIS_SLIDER_FONT = new Font( "Verdana", Font.PLAIN, 9 ); + + private final JXInputDevice mDev; + private final ArrayList mAxisSliders = new ArrayList(); + private final ArrayList mButtonCheckboxes = new ArrayList(); + private final ArrayList mDirectionalLabels = new ArrayList(); + + + /** Creates new form JXInputDevicePanel */ + public JXInputDevicePanel( JXInputDevice dev ) + { + mDev = dev; + initComponents(); + initFromDevice(); + } + + /** + * Helper class connecting a JSlider with an Axis. + */ + private class AxisSlider extends JSlider + { + Axis mAxis; + AxisSlider( Axis axis ) + { + super( ( Axis.SLIDER == axis.getType() ? 0 : -100 ), 100 ); + this.setMajorTickSpacing( Axis.SLIDER == axis.getType() ? 25 : 50 ); + this.setMinorTickSpacing( 5 ); + this.setPaintTicks( true ); + this.setPaintLabels( true ); + this.setEnabled( false ); + + Dictionary labeldict = this.getLabelTable(); + Enumeration labels = labeldict.elements(); + while ( labels.hasMoreElements() ) + { + JLabel label = (JLabel)labels.nextElement(); + label.setFont( AXIS_SLIDER_FONT ); + label.setSize( 32, 12 ); + label.setHorizontalAlignment( SwingConstants.LEFT ); + } + + mAxis = axis; + } + + void update() + { + int ax = (int)(mAxis.getValue() * 100.0); + + // + // Only if value really changes + // + if ( ax != this.getValue() ) + { + this.setValue( ax ); + this.setToolTipText( mAxis.getName() + ": " + Double.toString( mAxis.getValue() ) ); + } + } + + } + + + private class ButtonCheckbox extends JCheckBox + { + Button mButton; + ButtonCheckbox( Button button ) + { + super( button.getName() ); + this.setEnabled( false ); + mButton = button; + } + + void update() + { + boolean state = mButton.getState(); + + // + // Only if value really changes + // + if ( state != this.isSelected() ) + { + this.setSelected( state ); + } + } + } + + + private class DirectionalLabel extends JLabel + { + Directional mDirectional; + int mCurrent = 0; + + DirectionalLabel( Directional directional ) + { + super( directional.getName() ); + mDirectional = directional; + } + + void update() + { + int dir = mDirectional.getDirection(); + + // + // Only if value really changes + // + if ( dir != mCurrent ) + { + this.setText( mDirectional.getName() + ": " + ( mDirectional.isCentered() ? "-" : Integer.toString( dir ) ) ); + mCurrent = dir; + } + } + } + + + /** + * Setup the dialogs content from the JXInputDevice. + */ + void initFromDevice() + { + if ( null != mDev ) + { + ((GridLayout)mAxesPanel.getLayout()).setRows( mDev.getNumberOfAxes() ); + + for ( int i = 0; i < mDev.getMaxNumberOfAxes(); ++i ) + { + if ( null != mDev.getAxis( i ) ) + { + AxisSlider slider = new AxisSlider( mDev.getAxis( i ) ); + + JLabel name = new JLabel( mDev.getAxis( i ).getName() ); + name.setVerticalAlignment( SwingConstants.TOP ); + name.setHorizontalAlignment( SwingConstants.CENTER ); + name.setPreferredSize( new java.awt.Dimension( 90, 0 ) ); + + JPanel p = new JPanel(); + p.setLayout( new BorderLayout() ); + + p.add( name, BorderLayout.WEST ); + p.add( slider, BorderLayout.CENTER ); + + mAxesPanel.add( p ); + + // Add to list of all AxisSlider controls + mAxisSliders.add( slider ); + + // Add an event listener: + new AxisListener( mDev.getAxis( i ) ); + } + } + + + ((GridLayout)mButtonsPanel.getLayout()).setRows( mDev.getNumberOfButtons() ); + for ( int i = 0; i < mDev.getMaxNumberOfButtons(); ++i ) + { + if ( null != mDev.getButton( i ) ) + { + ButtonCheckbox chk = new ButtonCheckbox( mDev.getButton( i ) ); + mButtonCheckboxes.add( chk ); + mButtonsPanel.add( chk ); + + // Add an event listener: + new ButtonListener( mDev.getButton( i ) ); + } + } + + ((GridLayout)mDirectionalPanel.getLayout()).setRows( mDev.getNumberOfDirectionals() / 2 ); + for ( int i = 0; i < mDev.getMaxNumberOfDirectionals(); ++i ) + { + if ( null != mDev.getDirectional( i ) ) + { + DirectionalLabel lbl = new DirectionalLabel( mDev.getDirectional( i ) ); + mDirectionalLabels.add( lbl ); + mDirectionalPanel.add( lbl ); + + // Add an event listener: + new DirectionalListener( mDev.getDirectional( i ) ); + } + } + } + } + + + public void update() + { + Iterator it = mAxisSliders.iterator(); + while ( it.hasNext() ) + { + ((AxisSlider)it.next()).update(); + } + + it = mButtonCheckboxes.iterator(); + while ( it.hasNext() ) + { + ((ButtonCheckbox)it.next()).update(); + } + + it = mDirectionalLabels.iterator(); + while ( it.hasNext() ) + { + ((DirectionalLabel)it.next()).update(); + } + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + mAxesPanelContainer = new javax.swing.JPanel(); + mAxesPanel = new javax.swing.JPanel(); + mDirectionalPanel = new javax.swing.JPanel(); + mButtonScrollPane = new javax.swing.JScrollPane(); + mButtonsPanel = new javax.swing.JPanel(); + + setLayout(new java.awt.BorderLayout(2, 2)); + + addComponentListener(new java.awt.event.ComponentAdapter() + { + public void componentShown(java.awt.event.ComponentEvent evt) + { + OnShow(evt); + } + }); + + mAxesPanelContainer.setLayout(new java.awt.BorderLayout()); + + mAxesPanelContainer.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + mAxesPanel.setLayout(new java.awt.GridLayout(1, 1, 0, 20)); + + mAxesPanelContainer.add(mAxesPanel, java.awt.BorderLayout.NORTH); + + add(mAxesPanelContainer, java.awt.BorderLayout.CENTER); + + mDirectionalPanel.setLayout(new java.awt.GridLayout(1, 1)); + + mDirectionalPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + add(mDirectionalPanel, java.awt.BorderLayout.SOUTH); + + mButtonsPanel.setLayout(new java.awt.GridLayout(1, 1)); + + mButtonsPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + mButtonScrollPane.setViewportView(mButtonsPanel); + + add(mButtonScrollPane, java.awt.BorderLayout.EAST); + + }// //GEN-END:initComponents + + private void OnShow(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_OnShow + {//GEN-HEADEREND:event_OnShow + // Commented: the focus is held by a parent component +// System.out.println("OnShow"); +// this.requestFocus(); + }//GEN-LAST:event_OnShow + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel mAxesPanel; + private javax.swing.JPanel mAxesPanelContainer; + private javax.swing.JScrollPane mButtonScrollPane; + private javax.swing.JPanel mButtonsPanel; + private javax.swing.JPanel mDirectionalPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/java/de/hardcode/jxinput/test/JXInputTestDialog.form b/java/de/hardcode/jxinput/test/JXInputTestDialog.form new file mode 100644 index 0000000..1abc589 --- /dev/null +++ b/java/de/hardcode/jxinput/test/JXInputTestDialog.form @@ -0,0 +1,79 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/de/hardcode/jxinput/test/JXInputTestDialog.java b/java/de/hardcode/jxinput/test/JXInputTestDialog.java new file mode 100644 index 0000000..3829aa2 --- /dev/null +++ b/java/de/hardcode/jxinput/test/JXInputTestDialog.java @@ -0,0 +1,286 @@ +//********************************************************************************************** +// Dipl. Phys. Joerg Plewe, HARDCODE Development +// Created on 27. Dezember 2001, 01:15 +//********************************************************************************************** + +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.*; +import de.hardcode.jxinput.event.*; +import de.hardcode.jxinput.keyboard.JXKeyboardInputDevice; +import de.hardcode.jxinput.virtual.JXVirtualInputDevice; +import de.hardcode.jxinput.virtual.VirtualAxis; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + + +/** + * Test dialog showing some features of JXInput. + * @author Herkules + */ +public class JXInputTestDialog extends javax.swing.JDialog + implements ActionListener +{ + + private JXKeyboardInputDevice mKeyboardDevice = null; + private JXVirtualInputDevice mVirtualDevice = null; + + Button mButtonUp; + Button mButtonDown; + Button mButtonLeft; + Button mButtonRight; + Button mButtonFire; + Button mButtonSpace; + + /** Creates new form JXInputTestDialog */ + public JXInputTestDialog(java.awt.Frame parent, boolean modal) + { + super(parent, modal); + initComponents(); + configureKeyboardInputDevice(); + configureVirtualInputDevice(); + initDevicePanels(); + pack(); + + // Request the focus so that the keyboarddevice can work + mMainPanel.requestFocus(); + + new Timer( 50, this ).start(); + + // Uncomment this line as an alternative to the Timer above. + // Don't use both!! + //JXInputEventManager.setTriggerIntervall( 50 ); + } + + + /** + * Implement ActionListener#actionPerformed(). + * This is called by the Timer. + */ + public void actionPerformed( ActionEvent e ) + { + JXInputManager.updateFeatures(); + SwingUtilities.invokeLater( + new Runnable() + { + public void run() + { + for ( int i = 0; i < mDevicesTabbedPane.getComponentCount(); ++i ) + { + ((JXInputDevicePanel)mDevicesTabbedPane.getComponent( i )).update(); + } + } + } + ); + } + + + /** + * Configure a test JXKeyboardInputdevice. + */ + void configureKeyboardInputDevice() + { + mKeyboardDevice = JXInputManager.createKeyboardDevice(); + + mKeyboardDevice.createButton( KeyEvent.VK_ESCAPE ); + + mKeyboardDevice.createButton( KeyEvent.VK_F1 ); + mKeyboardDevice.createButton( KeyEvent.VK_F2 ); + mKeyboardDevice.createButton( KeyEvent.VK_F3 ); + mKeyboardDevice.createButton( KeyEvent.VK_F4 ); + + mKeyboardDevice.createButton( KeyEvent.VK_LEFT ); + mKeyboardDevice.createButton( KeyEvent.VK_RIGHT ); + mKeyboardDevice.createButton( KeyEvent.VK_UP ); + mKeyboardDevice.createButton( KeyEvent.VK_DOWN ); + + mKeyboardDevice.createButton( KeyEvent.VK_PAGE_UP ); + mKeyboardDevice.createButton( KeyEvent.VK_PAGE_DOWN ); + + mButtonSpace = mKeyboardDevice.createButton( KeyEvent.VK_SPACE ); + mButtonLeft = mKeyboardDevice.createButton( KeyEvent.VK_A ); + mButtonRight = mKeyboardDevice.createButton( KeyEvent.VK_D ); + mButtonDown = mKeyboardDevice.createButton( KeyEvent.VK_S ); + mButtonUp = mKeyboardDevice.createButton( KeyEvent.VK_W ); + + // Configure it to make it listen to the main panel. + // I try to keep the kbd focus on it. + mKeyboardDevice.listenTo( mMainPanel ); + } + + + /** + * Configure a test JXVirtualInputdevice. + */ + void configureVirtualInputDevice() + { + mVirtualDevice = JXInputManager.createVirtualDevice(); + + Button firebutton; + // + // Remember 'fire' button of first device for use + // in the virtual device. + // For we ran configureKeyboardInputDevice() before, + // getJXInputDevice( 0 ) should not return null + // + firebutton = JXInputManager.getJXInputDevice( 0 ).getButton( 0 ); + + VirtualAxis x = mVirtualDevice.createAxis( Axis.ID_X ); + x.setButtons( mButtonRight, mButtonLeft ); + x.setName( "x: A-D" ); + + VirtualAxis y = mVirtualDevice.createAxis( Axis.ID_Y ); + y.setButtons( mButtonUp, mButtonDown ); + y.setSpringSpeed( 0.0 ); + y.setName( "y: S|W" ); + + VirtualAxis slider = mVirtualDevice.createAxis( Axis.ID_SLIDER0 ); + slider.setIncreaseButton( mButtonSpace ); + slider.setTimeFor0To1( 2000 ); + slider.setName( "" ); + slider.setType( Axis.SLIDER ); + + if ( null != firebutton ) + { + slider = mVirtualDevice.createAxis( Axis.ID_SLIDER1 ); + slider.setIncreaseButton( firebutton ); + slider.setTimeFor0To1( 2000 ); + slider.setName( "JoyButton 0" ); + } + + + } + + + /** + * Initialize one panel for each device available. + */ + void initDevicePanels() + { + int cnt = JXInputManager.getNumberOfDevices(); + + mLabelNoDevice.setVisible( cnt == 0 ); + mDevicesTabbedPane.setVisible( cnt != 0 ); + + for ( int i = 0; i < cnt; ++i ) + { + JXInputDevice dev = JXInputManager.getJXInputDevice( i ); + if ( null != dev ) + { + // + // Setup an own panel for each device. + // + JPanel panel = new JXInputDevicePanel( dev ); + mDevicesTabbedPane.addTab( dev.getName(), panel ); + } + } + } + + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + mMainPanel = new javax.swing.JPanel(); + mLabelNoDevice = new javax.swing.JLabel(); + mDevicesTabbedPane = new javax.swing.JTabbedPane(); + mButtonReset = new javax.swing.JButton(); + + setTitle("JXInput (C) 2001-2006 HARDCODE Dev."); + addWindowListener(new java.awt.event.WindowAdapter() + { + public void windowClosing(java.awt.event.WindowEvent evt) + { + closeDialog(evt); + } + }); + + mMainPanel.setLayout(new java.awt.BorderLayout(10, 0)); + + mLabelNoDevice.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + mLabelNoDevice.setText("No JXInputDevice available!"); + mLabelNoDevice.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + mMainPanel.add(mLabelNoDevice, java.awt.BorderLayout.NORTH); + + mDevicesTabbedPane.addFocusListener(new java.awt.event.FocusAdapter() + { + public void focusGained(java.awt.event.FocusEvent evt) + { + mDevicesTabbedPaneFocusGained(evt); + } + }); + + mMainPanel.add(mDevicesTabbedPane, java.awt.BorderLayout.CENTER); + + mButtonReset.setText("Reset "); + mButtonReset.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + mButtonResetActionPerformed(evt); + } + }); + + mMainPanel.add(mButtonReset, java.awt.BorderLayout.SOUTH); + + getContentPane().add(mMainPanel, java.awt.BorderLayout.CENTER); + + pack(); + }// //GEN-END:initComponents + + private void mButtonResetActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_mButtonResetActionPerformed + {//GEN-HEADEREND:event_mButtonResetActionPerformed + + while ( this.mDevicesTabbedPane.getTabCount() > 0 ) + this.mDevicesTabbedPane.removeTabAt( 0 ); + + JXInputManager.reset(); + configureKeyboardInputDevice(); + configureVirtualInputDevice(); + initDevicePanels(); + pack(); + + // Request the focus so that the keyboarddevice can work + mMainPanel.requestFocus(); + + }//GEN-LAST:event_mButtonResetActionPerformed + + private void mDevicesTabbedPaneFocusGained(java.awt.event.FocusEvent evt)//GEN-FIRST:event_mDevicesTabbedPaneFocusGained + {//GEN-HEADEREND:event_mDevicesTabbedPaneFocusGained + // Switch focus back to main panel! + this.mMainPanel.requestFocus(); + }//GEN-LAST:event_mDevicesTabbedPaneFocusGained + + /** Closes the dialog */ + private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog + setVisible(false); + dispose(); + System.exit( 0 ); + }//GEN-LAST:event_closeDialog + + /** + * Allow the dialog to run standalone. + * @param args the command line arguments + */ + public static void main(String args[]) + { + new JXInputTestDialog(new javax.swing.JFrame(), true).setVisible(true); + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton mButtonReset; + private javax.swing.JTabbedPane mDevicesTabbedPane; + private javax.swing.JLabel mLabelNoDevice; + private javax.swing.JPanel mMainPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/java/de/hardcode/jxinput/util/LatestChangedValueAxis.java b/java/de/hardcode/jxinput/util/LatestChangedValueAxis.java new file mode 100644 index 0000000..f4f2c35 --- /dev/null +++ b/java/de/hardcode/jxinput/util/LatestChangedValueAxis.java @@ -0,0 +1,98 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 17. April 2002, 23:24 +//********************************************************************************************** +package de.hardcode.jxinput.util; + +import de.hardcode.jxinput.Axis; + +/** + * + * @author Herkules + */ +public class LatestChangedValueAxis implements Axis +{ + private final Axis mAxis1; + private final Axis mAxis2; + private Axis mAxisInUse; + + private double mSaved1; + private double mSaved2; + + /** + * Creates a new instance of MeanValueAxis. + */ + public LatestChangedValueAxis(Axis a1, Axis a2) + { + mAxis1 = a1; + mAxis2 = a2; + mAxisInUse = a1; + + mSaved1 = a1.getValue(); + mSaved2 = a2.getValue(); + } + + /** + * Features may have a name provided e.g. by the driver. + */ + public String getName() + { + return mAxis1.getName(); + } + + /** Inform about the resolution of the axis. + * + * @return resolution, e.g. 2^-16 + */ + public double getResolution() + { + return mAxis1.getResolution(); + } + + /** + * Retrieve the type of the axis. + * + * @return [ TRANSLATION | ROTATION | SLIDER ] + */ + public int getType() + { + return mAxis1.getType(); + } + + /** Returns the current value of the axis. + * The range of the result depends on the axis type. + *s + * @return value [-1.0,1.0] or [0.0,1.0] + */ + public double getValue() + { + double v1 = mAxis1.getValue(); + double v2 = mAxis2.getValue(); + + if ( Math.abs( v2 - mSaved2 ) > 0.2 ) + { + mAxisInUse = mAxis2; + mSaved2 = v2; + } + if ( Math.abs( v1 - mSaved1 ) > 0.2 ) + { + mAxisInUse = mAxis1; + mSaved1 = v1; + } + + return mAxisInUse.getValue(); + } + + /** Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + +} diff --git a/java/de/hardcode/jxinput/util/OrButton.java b/java/de/hardcode/jxinput/util/OrButton.java new file mode 100644 index 0000000..338538c --- /dev/null +++ b/java/de/hardcode/jxinput/util/OrButton.java @@ -0,0 +1,52 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 23. Dezember 2002, 19:21 +//********************************************************************************************** +package de.hardcode.jxinput.util; + +import de.hardcode.jxinput.Button; + +/** + * + * @author Herkules + */ +public class OrButton implements Button +{ + private final Button mButton1; + private final Button mButton2; + + + /** + * Creates a new instance of OrButton. + */ + public OrButton( Button b1, Button b2 ) + { + mButton1 = b1; + mButton2 = b2; + } + + public String getName() + { + return mButton1.getName(); + } + + public boolean getState() + { + return mButton1.getState() || mButton2.getState(); + } + + public int getType() + { + return mButton1.getType(); + } + + public boolean hasChanged() + { + return mButton1.hasChanged() || mButton2.hasChanged(); + } + +} diff --git a/java/de/hardcode/jxinput/virtual/JXVirtualInputDevice.java b/java/de/hardcode/jxinput/virtual/JXVirtualInputDevice.java new file mode 100644 index 0000000..aa125af --- /dev/null +++ b/java/de/hardcode/jxinput/virtual/JXVirtualInputDevice.java @@ -0,0 +1,140 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:40 +//********************************************************************************************** +package de.hardcode.jxinput.virtual; + + +import de.hardcode.jxinput.*; + + +/** + * Virtual input device. + * + * @author Herkules + */ +public class JXVirtualInputDevice implements JXInputDevice +{ + private static final String DEVICENAME = "Virtual Device"; + + /** The driver doing all the real work. */ + private final VirtualDriver mDriver = new VirtualDriver(); + + + /** + * Creates a new instance of JXKeyboardInputDevice. + */ + public JXVirtualInputDevice() + { + } + + + /** + * The virtual input device needs to be updated regularly. + */ + public final void update( long deltaT ) + { + // + // Delegate the update call to the driver. + // + mDriver.update( deltaT ); + } + + /** + * Create a virtual axis object with a certain ID, e.g. Axis.ID_X. + */ + public VirtualAxis createAxis( int id ) + { + VirtualAxis a; + a = new VirtualAxis( id ); + mDriver.registerVirtualAxis( id, a ); + return a; + } + + + public void removeAxis( VirtualAxis a ) + { + mDriver.unregisterVirtualAxis( a ); + } + + + + //********************************************************************************************* + // + // Implement JXInputDevice + // + //********************************************************************************************* + + public Axis getAxis(int idx) + { + return mDriver.getAxis( idx ); + } + + + public Button getButton(int idx) + { + // No virtual buttons. + return null; + } + + + public Directional getDirectional(int idx) + { + // No virtual directionals. + return null; + } + + /** Maximum number of axes as an upper bound for index values. */ + public int getMaxNumberOfAxes() + { + return Axis.NUMBER_OF_ID; + } + + /** Maximum number of buttons as an upper bound for index values. */ + public int getMaxNumberOfButtons() + { + // No virtual buttons. + return 0; + } + + /** Maximum number of directional features as an upper bound for index values. */ + public int getMaxNumberOfDirectionals() + { + // No virtual directionals. + return 0; + } + + /** + * Devices may have a name. + * This name might be provided by a system dependant driver. + */ + public String getName() + { + return DEVICENAME; + } + + /** Actual number of available axes. */ + public int getNumberOfAxes() + { + // No axes on keyboard. + return mDriver.getNumberOfAxes(); + } + + /** Actual number of available buttons. */ + public int getNumberOfButtons() + { + return 0; + } + + /** Actual number of available directional features. */ + public int getNumberOfDirectionals() + { + // No directionals on keyboard. + return 0; + } + +} diff --git a/java/de/hardcode/jxinput/virtual/VirtualAxis.java b/java/de/hardcode/jxinput/virtual/VirtualAxis.java new file mode 100644 index 0000000..b272c6e --- /dev/null +++ b/java/de/hardcode/jxinput/virtual/VirtualAxis.java @@ -0,0 +1,207 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 11. April 2002, 23:40 +//********************************************************************************************** +package de.hardcode.jxinput.virtual; + +import de.hardcode.jxinput.Axis; +import de.hardcode.jxinput.Button; +import java.security.InvalidParameterException; + +/** + * + * @author Jörg Plewe + */ +public class VirtualAxis + implements Axis +{ + + private int mType = Axis.TRANSLATION; + private final int mID; + private String mName = "VirtualAxis"; + private double mCurrentValue = 0; + + private Button mButtonIncrease = null; + private Button mButtonDecrease = null; + private double mSpeed = 1.0 / 500.0; + private double mSpringSpeed = 1.0 / 500.0; + + /** + * Creates a new instance of VirtualAxis. + */ + public VirtualAxis( int id ) + { + mID = id; + } + + + /** + * Set the type of this axis to be either Axis.ROTATION, + * Axis.TRANSLATION or Axis.SLIDER. + */ + public void setType( int type ) + { + if ( Axis.ROTATION != type + && Axis.TRANSLATION != type + && Axis.SLIDER != type + ) + throw new InvalidParameterException( "Invalid type for axis!" ); + + mType = type; + } + + /** + * Update features under my control. + */ + final void update( long deltaT ) + { + double change = mSpeed * deltaT; + double springchange = mSpringSpeed * deltaT; + boolean doincrease = ( null != mButtonIncrease && mButtonIncrease.getState() ); + boolean dodecrease = ( null != mButtonDecrease && mButtonDecrease.getState() ); + boolean iscontrolled = doincrease || dodecrease; + + double controlledchange = 0.0; + if ( doincrease ) + controlledchange += change; + if ( dodecrease ) + controlledchange -= change; + + mCurrentValue += controlledchange; + + if ( mCurrentValue > 0.0 && ! doincrease ) + { + springchange = Math.min( mCurrentValue, springchange ); + mCurrentValue -= springchange; + } + if ( mCurrentValue < 0.0 && ! dodecrease ) + { + springchange = Math.min( -mCurrentValue, springchange ); + mCurrentValue += springchange; + } + + // + // Hold value within range + // + if ( mCurrentValue > 1.0 ) + mCurrentValue = 1.0; + double lowerlimit = Axis.SLIDER == mType ? 0.0 : -1.0; + if ( mCurrentValue < lowerlimit ) + mCurrentValue = lowerlimit; + } + + + /** + * Set the button to increase the axis for a single button axis. + */ + public final void setIncreaseButton( Button b ) + { + if ( null == b ) + throw new InvalidParameterException( "Button may not be null!" ); + + mButtonIncrease = b; + } + + + /** + * Set the buttons to increase and descrease the axis. + */ + public final void setButtons( Button increase, Button decrease ) + { + if ( null == increase || null == decrease ) + throw new InvalidParameterException( "Buttons may not be null!" ); + + mButtonIncrease = increase; + mButtonDecrease = decrease; + } + + + public final void setSpeed( double speed ) + { + mSpeed = speed; + } + + public final void setSpringSpeed( double springspeed ) + { + mSpringSpeed = springspeed; + } + + + public final void setTimeFor0To1( int ms ) + { + if ( 0 >= ms ) + mSpeed = 0.0; + else + mSpeed = 1.0/ ms; + } + public final void setTimeFor1To0( int ms ) + { + if ( 0 >= ms ) + mSpringSpeed = 0.0; + else + mSpringSpeed = 1.0/ ms; + } + + + public final void setName( String name ) + { + mName = name; + } + + //********************************************************************************************* + // + // Implement Axis + // + //********************************************************************************************* + + /** + * Features may have a name provided e.g. by the driver. + */ + public String getName() + { + return mName; + } + + /** + * Inform about the resolution of the axis. + * + * @return resolution, e.g. 2^-16 + */ + public double getResolution() + { + return 1.0/65536.0; + } + + + /** + * Retrieve the type of the axis. + * @return [ TRANSLATION | ROTATION | SLIDER ] + */ + public int getType() + { + return mType; + } + + /** Returns the current value of the axis. + * The range of the result depends on the axis type. + * + * @return value [-1.0,1.0] or [0.0,1.0] + */ + public double getValue() + { + return mCurrentValue; + } + + /** Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + +} diff --git a/java/de/hardcode/jxinput/virtual/VirtualDriver.java b/java/de/hardcode/jxinput/virtual/VirtualDriver.java new file mode 100644 index 0000000..5952eff --- /dev/null +++ b/java/de/hardcode/jxinput/virtual/VirtualDriver.java @@ -0,0 +1,95 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:43 +//********************************************************************************************** +package de.hardcode.jxinput.virtual; + +import java.util.ArrayList; +import de.hardcode.jxinput.Axis; + + + +/** + * This is the main worker class for JXVirtualInputDevice. + * + * @author Herkules + */ +class VirtualDriver +{ + + private final VirtualAxis[] mVAxes = new VirtualAxis[ Axis.NUMBER_OF_ID ]; + + /** + * Creates a new instance of KeyboardDriver. + */ + VirtualDriver() + { + } + + + /** + * Update features under my control. + */ + final void update( long deltaT ) + { + // + // Delegate the update call to the axes in use. + // + for ( int i = 0; i < mVAxes.length; i++ ) + { + if ( null != mVAxes[ i ] ) + mVAxes[ i ].update( deltaT ); + } + } + + + /** + * How many axes are registered? + */ + final int getNumberOfAxes() + { + int ctr = 0; + for ( int i = 0; i < mVAxes.length; i++ ) + { + if ( null != mVAxes[ i ] ) + ctr++; + } + return ctr; + } + + Axis getAxis(int idx) + { + return mVAxes[ idx ]; + } + + + /** + * Place a new axis under my observation. + */ + final void registerVirtualAxis( int id, VirtualAxis a ) + { + mVAxes[ id ] = a; + } + + + /** + * Remove an axis from my control. + */ + final void unregisterVirtualAxis( VirtualAxis a ) + { + for ( int i = 0; i < mVAxes.length; ++i ) + { + if ( mVAxes[ i ] == a ) + { + mVAxes[ i ] = null; + break; + } + } + } + + +} diff --git a/java/de/hardcode/jxinput/virtual/package.html b/java/de/hardcode/jxinput/virtual/package.html new file mode 100644 index 0000000..d8e1d6a --- /dev/null +++ b/java/de/hardcode/jxinput/virtual/package.html @@ -0,0 +1,11 @@ + + + + + de.hardcode.jxinput.virtual + + +Allows to define virtual axes that are not derived from any device +but from other JXInput feature objects. + + diff --git a/win32/.cvsignore b/win32/.cvsignore new file mode 100644 index 0000000..252078e --- /dev/null +++ b/win32/.cvsignore @@ -0,0 +1,8 @@ +*.ncb +Release +*.plg +Debug +*~ +jxinput.vcproj.HERKBOOK.Herkules.user +jxinput.suo +*.opt diff --git a/win32/JXInputManager.cpp b/win32/JXInputManager.cpp new file mode 100644 index 0000000..3718a7f --- /dev/null +++ b/win32/JXInputManager.cpp @@ -0,0 +1,175 @@ + +#include "stdafx.h" +#include "JXInputManager.h" +#include "JXInput.h" + +// +// Globals +// +extern HINSTANCE g_hInst; + + +JXInputManager::JXInputManager( HWND hWnd ) : +mhWnd( hWnd ), +mDeviceCounter( 0 ) +{ + + for ( int i = 0; i < MAX_JXINPUTS; ++i ) + { + mDevices[ i ] = NULL; + } + + + if ( FAILED( InitDirectInput( hWnd ) ) ) + { + FreeDirectInput(); + } + +} + +JXInputManager::~JXInputManager() +{ + for ( int i = 0; i < getNumberOfJXInputs(); ++i ) + { + delete mDevices[ i ]; + mDevices[ i ] = NULL; + } + + FreeDirectInput(); +} + +int JXInputManager::getNumberOfJXInputs() const +{ + return mDeviceCounter; +} + +JXInput& JXInputManager::getJXInput( int idx ) const +{ + assert( idx < mDeviceCounter ); + return * mDevices[ idx ]; +} + + +int JXInputManager::getMaxNumberOfAxes() const +{ + return JXINPUT_MAX_AXES; +} + +int JXInputManager::getMaxNumberOfButtons() const +{ + return JXINPUT_MAX_BUTTONS; +} + +int JXInputManager::getMaxNumberOfDirectionals() const +{ + return JXINPUT_MAX_DIRECTIONALS; +} + + + +//----------------------------------------------------------------------------- +// Name: InitDirectInput() +// Desc: Initialize the DirectInput variables. +//----------------------------------------------------------------------------- +HRESULT JXInputManager::InitDirectInput( HWND hWnd ) +{ + HRESULT hr; + + // Register with the DirectInput subsystem and get a pointer + // to a IDirectInput interface we can use. + // Create a DInput object + if( FAILED( hr = DirectInput8Create( g_hInst, DIRECTINPUT_VERSION, + IID_IDirectInput8, (VOID**)&mpDI, NULL ) ) ) + return hr; + + // Look for a simple joystick we can use for this sample program. + if( FAILED( hr = mpDI->EnumDevices( DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + (VOID*)this, DIEDFL_ALLDEVICES /*| DIEDFL_INCLUDEPHANTOMS*/ ) ) ) + return hr; + + // Look for a other devices + if( FAILED( hr = mpDI->EnumDevices( DI8DEVCLASS_DEVICE, + EnumJoysticksCallback, + (VOID*)this, DIEDFL_ALLDEVICES /*| DIEDFL_INCLUDEPHANTOMS*/ ) ) ) + return hr; + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: FreeDirectInput() +// Desc: Initialize the DirectInput variables. +//----------------------------------------------------------------------------- +HRESULT JXInputManager::FreeDirectInput() +{ + + if ( NULL != mpDI ) + mpDI->Release(); + mpDI = NULL; + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: EnumJoysticksCallback() +// Desc: Called once for each enumerated joystick. If we find one, create a +// device interface on it so we can play with it. +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInputManager::EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, + VOID* pContext ) +{ + HRESULT hr; + LPDIRECTINPUTDEVICE8 pJoystick; + + JXInputManager* pThis = (JXInputManager*)pContext; + + // + // if the maximum number of devices is already registered, + // issue a warning and stop enumeration. + // + if( MAX_JXINPUTS == pThis->mDeviceCounter ) + { + OutputDebugString( "Max. number of devices exceeded!" ); + return DIENUM_STOP; + } + + + + // Obtain an interface to the enumerated joystick. + hr = pThis->mpDI->CreateDevice( pdidInstance->guidInstance, &pJoystick, NULL ); + + // If it failed, then we can't use this joystick. (Maybe the user unplugged + // it while we were in the middle of enumerating it.) + if( FAILED(hr) ) + return DIENUM_CONTINUE; + + JXInput* pJ = new JXInput( pJoystick, pThis->mhWnd ); + + // + // only register useful devices + // + if( pJ->getNumberOfAxes() + pJ->getNumberOfButtons() + pJ->getNumberOfDirectionals() > 0 ) + { + pThis->addJXInput( pJ ); + } + else + { + delete pJ; + } + + return DIENUM_CONTINUE; +} + + +/** + * Register a JXInput device. + */ +void JXInputManager::addJXInput( JXInput* pJ ) +{ + assert( mDeviceCounter < MAX_JXINPUTS ); + + if( mDeviceCounter < MAX_JXINPUTS ) + mDevices[ mDeviceCounter++ ] = pJ; +} diff --git a/win32/JXInputManager.h b/win32/JXInputManager.h new file mode 100644 index 0000000..41b9da4 --- /dev/null +++ b/win32/JXInputManager.h @@ -0,0 +1,47 @@ +// JXInputManager.h: Schnittstelle für die Klasse JXInputManager. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_JXINPUTMANAGER_H__24862402_14C9_407D_8532_A16A6E3A7D64__INCLUDED_) +#define AFX_JXINPUTMANAGER_H__24862402_14C9_407D_8532_A16A6E3A7D64__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +#define MAX_JXINPUTS 10 + +class JXInput; + +class JXINPUT_API JXInputManager +{ +public: + JXInputManager( HWND hWnd ); + virtual ~JXInputManager(); + + int getNumberOfJXInputs() const; + JXInput& getJXInput( int idx ) const; + + // + // Numbering methods + // + int getMaxNumberOfAxes() const; + int getMaxNumberOfButtons() const; + int getMaxNumberOfDirectionals() const; + +private: + LPDIRECTINPUT8 mpDI; + HWND mhWnd; + JXInput* mDevices[ MAX_JXINPUTS ]; + int mDeviceCounter; + + HRESULT InitDirectInput( HWND hWnd = NULL ); + HRESULT FreeDirectInput(); + + static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, + VOID* pContext ); + void addJXInput( JXInput* pJ ); +}; + +#endif // !defined(AFX_JXINPUTMANAGER_H__24862402_14C9_407D_8532_A16A6E3A7D64__INCLUDED_) diff --git a/win32/ReadMe.txt b/win32/ReadMe.txt new file mode 100644 index 0000000..755cd4c --- /dev/null +++ b/win32/ReadMe.txt @@ -0,0 +1,37 @@ +======================================================================== + DYNAMIC LINK LIBRARY : jxinput +======================================================================== + + +Diese jxinput-DLL hat der Anwendungs-Assistent für Sie erstellt. + +Diese Datei enthält eine Zusammenfassung dessen, was Sie in jeder der Dateien +finden, die Ihre jxinput-Anwendung bilden. + +jxinput.dsp + Diese Datei (Projektdatei) enthält Informationen auf Projektebene und wird zur + Erstellung eines einzelnen Projekts oder Teilprojekts verwendet. Andere Benutzer können + die Projektdatei (.dsp) gemeinsam nutzen, sollten aber die Makefiles lokal exportieren. + +jxinput.cpp + Dies ist die Hauptquellcodedatei für die DLL. + +jxinput.h + Diese Datei enthält Ihre DLL-Exporte. + +///////////////////////////////////////////////////////////////////////////// +Weitere Standarddateien: + +StdAfx.h, StdAfx.cpp + Diese Dateien werden zum Erstellen einer vorkompilierten Header-Datei (PCH) namens + jxinput.pch und einer vorkompilierten Typdatei namens StdAfx.obj verwendet. + + +///////////////////////////////////////////////////////////////////////////// +Weitere Hinweise: + +Der Anwendungs-Assistent verwendet "ZU ERLEDIGEN:", um Bereiche des Quellcodes zu +kennzeichnen, die Sie hinzufügen oder anpassen sollten. + + +///////////////////////////////////////////////////////////////////////////// diff --git a/win32/StdAfx.cpp b/win32/StdAfx.cpp new file mode 100644 index 0000000..a144a09 --- /dev/null +++ b/win32/StdAfx.cpp @@ -0,0 +1,9 @@ +// stdafx.cpp : Quelltextdatei, die nur die Standard-Includes einbindet +// jxinput.pch ist die vorkompilierte Header-Datei +// stdafx.obj enthält die vorkompilierte Typinformation + +#include "stdafx.h" + +// ZU ERLEDIGEN: Verweis auf alle zusätzlichen Header-Dateien, die Sie in STDAFX.H +// und nicht in dieser Datei benötigen + diff --git a/win32/StdAfx.h b/win32/StdAfx.h new file mode 100644 index 0000000..e139c4c --- /dev/null +++ b/win32/StdAfx.h @@ -0,0 +1,32 @@ +// stdafx.h : Include-Datei für Standard-System-Include-Dateien, +// oder projektspezifische Include-Dateien, die häufig benutzt, aber +// in unregelmäßigen Abständen geändert werden. +// + +#if !defined(AFX_STDAFX_H__68E14C76_098F_47ED_932B_4C01E8E9EFFB__INCLUDED_) +#define AFX_STDAFX_H__68E14C76_098F_47ED_932B_4C01E8E9EFFB__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// Fügen Sie hier Ihre Header-Dateien ein +#define WIN32_LEAN_AND_MEAN // Selten benutzte Teile der Windows-Header nicht einbinden +#define STRICT +#include + +// ZU ERLEDIGEN: Verweisen Sie hier auf zusätzliche Header-Dateien, die Ihr Programm benötigt +#ifdef JXINPUT_EXPORTS +#define JXINPUT_API __declspec(dllexport) +#else +#define JXINPUT_API __declspec(dllimport) +#endif + +#include +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fügt zusätzliche Deklarationen unmittelbar vor der vorherigen Zeile ein. + +#endif // !defined(AFX_STDAFX_H__68E14C76_098F_47ED_932B_4C01E8E9EFFB__INCLUDED_) diff --git a/win32/de_hardcode_jxinput_directinput_DirectInputDriver.cpp b/win32/de_hardcode_jxinput_directinput_DirectInputDriver.cpp new file mode 100644 index 0000000..077afe8 --- /dev/null +++ b/win32/de_hardcode_jxinput_directinput_DirectInputDriver.cpp @@ -0,0 +1,279 @@ +#include "stdafx.h" + +#include "de_hardcode_jxinput_directinput_DirectInputDriver.h" +#include "jxinput.h" +#include "JXInputManager.h" + + +// +// Globals +// +extern HINSTANCE g_hInst; + +static JXInputManager* pJXInputManager = NULL; +static JXInput* apJXInput[ MAX_JXINPUTS ]; +static HWND hWndJava; + +// +// IDs of the static Java arrays. +// +static jfieldID sAxesFieldID; +static jfieldID sButtonsFieldID; +static jfieldID sDirectionsFieldID; + + + +/** + * Remove all resources allocated by the Java binding. + */ +void shutdownJavaResources() +{ + if ( NULL != pJXInputManager ) + delete pJXInputManager; + + if ( NULL != hWndJava ) + DestroyWindow( hWndJava ); + + pJXInputManager = NULL; + + for( int i = 0; i < MAX_JXINPUTS; ++i ) + apJXInput[ i ] = NULL; + + hWndJava = NULL; +} + + + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) +{ + return JNI_VERSION_1_2; +} + + +JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) +{ + shutdownJavaResources(); +} + + +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeinit + (JNIEnv * penv, jclass pClazz ) +{ + + // + // Create a non-visible window as 'owner' of the DI device. + // + hWndJava = CreateWindowEx( + 0/*WS_EX_APPWINDOW*/, // DWORD dwExStyle, // extended window style + "STATIC", // LPCTSTR lpClassName, // pointer to registered class name + NULL, // LPCTSTR lpWindowName, // pointer to window name + 0/*WS_CAPTION*/, // DWORD dwStyle, // window style + 0, // int x, // horizontal position of window + 0, // int y, // vertical position of window + 0, // int nWidth, // window width + 0, // int nHeight, // window height + NULL, // HWND hWndParent, // handle to parent or owner window + NULL, // HMENU hMenu, // handle to menu, or child-window identifier + g_hInst, // HINSTANCE hInstance, // handle to application instance + NULL // LPVOID lpParam // pointer to window-creation data + ); + + + if ( NULL == pJXInputManager ) + { + pJXInputManager = new JXInputManager( hWndJava ); + + for( int i = 0; i < MAX_JXINPUTS; ++i ) + apJXInput[ i ] = NULL; + + for ( int i = 0; i < pJXInputManager->getNumberOfJXInputs(); ++i ) + { + apJXInput[ i ] = & pJXInputManager->getJXInput( i ); + } + } + + return true; +} + + + +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeexit + (JNIEnv *, jclass ) +{ + shutdownJavaResources(); +} + + +/** + * Bind my field IDs to the Java variables. + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_bind + (JNIEnv * penv, jclass pClazz) +{ + // + // All fields are static. + // + sAxesFieldID = penv->GetStaticFieldID( pClazz, "sAxisValues", "[[D" ); + sButtonsFieldID = penv->GetStaticFieldID( pClazz, "sButtonStates", "[[Z" ); + sDirectionsFieldID = penv->GetStaticFieldID( pClazz, "sDirectionalValues", "[[I" ); +} + + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfDevices + (JNIEnv *penv, jclass) +{ + return pJXInputManager->getNumberOfJXInputs(); +} + + +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getName + (JNIEnv *penv, jclass, jint dev) +{ + return penv->NewStringUTF( apJXInput[ dev ]->getName() ); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfAxes + (JNIEnv *, jclass, jint dev) +{ + return apJXInput[ dev ]->getNumberOfAxes(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfButtons + (JNIEnv *, jclass, jint dev) +{ + return apJXInput[ dev ]->getNumberOfButtons(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfDirectionals + (JNIEnv *, jclass, jint dev) +{ + return apJXInput[ dev ]->getNumberOfDirectionals(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfAxes + (JNIEnv *, jclass) +{ + return pJXInputManager->getMaxNumberOfAxes(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfButtons + (JNIEnv *, jclass) +{ + return pJXInputManager->getMaxNumberOfButtons(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfDirectionals + (JNIEnv *, jclass) +{ + return pJXInputManager->getMaxNumberOfDirectionals(); +} + +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isAxisAvailable + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->isAxisAvailable( idx ); +} + +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getAxisName + (JNIEnv *penv, jclass, jint dev, jint idx ) +{ + return penv->NewStringUTF( apJXInput[ dev ]->getAxisName( idx ) ); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getAxisType + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->getAxisType( idx ); +} + + +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isButtonAvailable + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->isButtonAvailable( idx ); +} + +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getButtonName + (JNIEnv *penv, jclass, jint dev, jint idx ) +{ + return penv->NewStringUTF( apJXInput[ dev ]->getButtonName( idx ) ); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getButtonType + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->getButtonType( idx ); +} + +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isDirectionalAvailable + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->isDirectionalAvailable( idx ); +} + +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getDirectionalName + (JNIEnv *penv, jclass, jint dev, jint idx ) +{ + return penv->NewStringUTF( apJXInput[ dev ]->getDirectionalName( idx ) ); +} + + + +/** + * The main update method. + * Here, the actual work is done. + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeupdate + (JNIEnv * penv, jclass pClazz ) +{ + + static jdouble axes [ MAX_JXINPUTS ][ JXINPUT_MAX_AXES ]; + static jboolean buttons [ MAX_JXINPUTS ][ JXINPUT_MAX_BUTTONS ]; + static jint directions [ MAX_JXINPUTS ][ JXINPUT_MAX_DIRECTIONALS ]; + + static jobjectArray axisarrayarray; + static jobjectArray buttonarrayarray; + static jobjectArray directionarrayarray; + + static jdoubleArray axisarray; + static jbooleanArray buttonarray; + static jintArray directionarray; + + axisarrayarray = (jobjectArray)penv->GetStaticObjectField( pClazz, sAxesFieldID ); + buttonarrayarray = (jobjectArray)penv->GetStaticObjectField( pClazz, sButtonsFieldID ); + directionarrayarray = (jobjectArray)penv->GetStaticObjectField( pClazz, sDirectionsFieldID ); + + // + // For each device.... + // + for ( int dev = 0; dev < pJXInputManager->getNumberOfJXInputs(); ++dev ) + { + // Do the update of the device. + apJXInput[ dev ]->update(); + + // + // Copy all values into my arrays. + // + for ( int i = 0; i < JXINPUT_MAX_AXES; ++i ) + axes[ dev ][ i ] = apJXInput[ dev ]->getAxisValue( i ); + for ( int i = 0; i < JXINPUT_MAX_BUTTONS; ++i ) + buttons[ dev ][ i ] = apJXInput[ dev ]->isButtonDown( i ); + for ( int i = 0; i < JXINPUT_MAX_DIRECTIONALS; ++i ) + directions[ dev ][ i ] = apJXInput[ dev ]->getDirection( i ); + + + // + // Move my arrays to the Java arrays. + // + axisarray = (jdoubleArray)penv->GetObjectArrayElement( axisarrayarray, dev ); + penv->SetDoubleArrayRegion( axisarray, 0, JXINPUT_MAX_AXES, axes[ dev ] ); + + buttonarray = (jbooleanArray)penv->GetObjectArrayElement( buttonarrayarray, dev ); + penv->SetBooleanArrayRegion( buttonarray, 0, JXINPUT_MAX_BUTTONS, buttons[ dev ] ); + + directionarray = (jintArray)penv->GetObjectArrayElement( directionarrayarray, dev ); + penv->SetIntArrayRegion( directionarray, 0, JXINPUT_MAX_DIRECTIONALS, directions[ dev ] ); + } + +} + diff --git a/win32/de_hardcode_jxinput_directinput_DirectInputDriver.h b/win32/de_hardcode_jxinput_directinput_DirectInputDriver.h new file mode 100644 index 0000000..bb93548 --- /dev/null +++ b/win32/de_hardcode_jxinput_directinput_DirectInputDriver.h @@ -0,0 +1,183 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include + +/* Header for class de_hardcode_jxinput_directinput_DirectInputDriver */ + +#ifndef _Included_de_hardcode_jxinput_directinput_DirectInputDriver +#define _Included_de_hardcode_jxinput_directinput_DirectInputDriver + +#ifdef __cplusplus +extern "C" { +#endif + +/* Inaccessible static: sIsOperational */ +/* Inaccessible static: sAxisValues */ +/* Inaccessible static: sButtonStates */ +/* Inaccessible static: sDirectionalValues */ +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: nativeinit + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeinit + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: nativeexit + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeexit + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: bind + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_bind + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getNumberOfDevices + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfDevices + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getName + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getName + (JNIEnv *, jclass, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getNumberOfAxes + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfAxes + + (JNIEnv *, jclass, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getNumberOfButtons + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfButtons + (JNIEnv *, jclass, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getNumberOfDirectionals + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfDirectionals + (JNIEnv *, jclass, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getMaxNumberOfAxes + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfAxes + (JNIEnv *, jclass); + + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getMaxNumberOfButtons + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfButtons + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getMaxNumberOfDirectionals + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfDirectionals + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: isAxisAvailable + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isAxisAvailable + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getAxisName + * Signature: (II)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getAxisName + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getAxisType + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getAxisType + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: isButtonAvailable + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isButtonAvailable + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getButtonName + * Signature: (II)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getButtonName + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getButtonType + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getButtonType + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: isDirectionalAvailable + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isDirectionalAvailable + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getDirectionalName + * Signature: (II)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getDirectionalName + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: nativeupdate + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeupdate + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/win32/dllmain.cpp b/win32/dllmain.cpp new file mode 100644 index 0000000..567e8d4 --- /dev/null +++ b/win32/dllmain.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" + +HINSTANCE g_hInst; + + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + g_hInst = (HINSTANCE)hModule; + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + g_hInst = NULL; + break; + } + return TRUE; +} diff --git a/win32/jxinput.cpp b/win32/jxinput.cpp new file mode 100644 index 0000000..890805b --- /dev/null +++ b/win32/jxinput.cpp @@ -0,0 +1,600 @@ +// +// jxinput.cpp +// +#include "stdafx.h" +#include "jxinput.h" + + +// +// Globals +// +extern HINSTANCE g_hInst; + + +/** + * Ctor: Connect with DI + */ +JXInput::JXInput( LPDIRECTINPUTDEVICE8 pJoystick, HWND hWnd ) : + mpJoystick( pJoystick ), + mSliderCount( 0 ), + mPOVCount( 0 ), + mButtonCount( 0 ) +{ + initAxisConfig(); + initButtonsConfig(); + initDirectionalsConfig(); + + if ( FAILED( InitDirectInput( hWnd ) ) ) + { + FreeDirectInput(); + } +} + + + +/** + * Destructor: + * Free DirectInput. + */ +JXInput::~JXInput() +{ + FreeDirectInput(); +} + + +void JXInput::update() +{ + UpdateInputState(); +} + + +TCHAR * const JXInput::getName() const +{ + return (TCHAR*)mdiDevInfo.tszInstanceName; +} + + + +int JXInput::getNumberOfAxes() const +{ + return mdiDevCaps.dwAxes; +} + +int JXInput::getNumberOfButtons() const +{ + return mButtonCount; +} + +int JXInput::getNumberOfDirectionals() const +{ + return mPOVCount; +} + + +double JXInput::getAxisValueHelper( LONG val, int idx ) const +{ + const AxisConfig& cfg = mAxisConfig[ idx ]; + + double span = (double)( cfg.mMaxValue - cfg.mMinValue ); + double ret = (double)(val - cfg.mMinValue) / span; + + if ( TYPE_SLIDER != cfg.mType ) + return ret*2.0 - 1.0; + return ret; +} + +double JXInput::getX() const +{ + return getAxisValueHelper( mJS.lX, ID_X ); +} +double JXInput::getY() const +{ + return getAxisValueHelper( mJS.lY, ID_Y ); +} +double JXInput::getZ() const +{ + return getAxisValueHelper( mJS.lZ, ID_Z ); +} +double JXInput::getRotX() const +{ + return getAxisValueHelper( mJS.lRx, ID_ROTX ); +} +double JXInput::getRotY() const +{ + return getAxisValueHelper( mJS.lRy, ID_ROTY ); +} +double JXInput::getRotZ() const +{ + return getAxisValueHelper( mJS.lRz, ID_ROTZ ); +} +double JXInput::getSlider0() const +{ + return getAxisValueHelper( mJS.rglSlider[ 0 ], ID_SLIDER0 ); +} +double JXInput::getSlider1() const +{ + return getAxisValueHelper( mJS.rglSlider[ 1 ], ID_SLIDER1 ); +} + + + +bool JXInput::isAxisAvailable( int idx ) const +{ + assert( idx < JXINPUT_MAX_AXES ); + return mAxisConfig[ idx ].mIsAvailable; +} + +TCHAR * const JXInput::getAxisName( int idx ) const +{ + assert( idx < JXINPUT_MAX_AXES ); + return (char*const)mAxisConfig[ idx ].mName; +} + +int JXInput::getAxisType( int idx ) const +{ + assert( idx < JXINPUT_MAX_AXES ); + return mAxisConfig[ idx ].mType; +} + +double JXInput::getAxisValue( int idx ) const +{ + assert( idx < JXINPUT_MAX_AXES ); + + // Failsafe if called accidentally + if ( ! mAxisConfig[ idx ].mIsAvailable ) + return 0.0; + + return (this->*mAxisConfig[ idx ].mGetValueMethod)(); +} + + + + + +bool JXInput::isButtonAvailable( int idx ) const +{ + assert( idx < JXINPUT_MAX_BUTTONS ); + return mButtonConfig[ idx ].mIsAvailable; +} + +TCHAR * const JXInput::getButtonName( int idx ) const +{ + assert( idx < JXINPUT_MAX_BUTTONS ); + return (char*const)mButtonConfig[ idx ].mName; +} + +int JXInput::getButtonType( int idx ) const +{ + assert( idx < JXINPUT_MAX_BUTTONS ); + return mButtonConfig[ idx ].mType; +} + +bool JXInput::isButtonDown( int idx ) const +{ + assert( idx < JXINPUT_MAX_BUTTONS ); + return 0 != mJS.rgbButtons[ idx ] ; +} + + +bool JXInput::isDirectionalAvailable( int idx ) const +{ + assert( idx < JXINPUT_MAX_DIRECTIONALS ); + return mDirectionalConfig[ idx ].mIsAvailable; +} + +TCHAR * const JXInput::getDirectionalName( int idx ) const +{ + assert( idx < JXINPUT_MAX_DIRECTIONALS ); + return (char*const)mDirectionalConfig[ idx ].mName; +} + +int JXInput::getDirection( int idx ) const +{ + assert( idx < JXINPUT_MAX_DIRECTIONALS ); + return mJS.rgdwPOV[ idx ] ; +} + + +/** + * Initialize axis configuration array. + */ +void JXInput::initAxisConfig() +{ + mAxisConfig[ ID_X ].mIsAvailable = false; + mAxisConfig[ ID_X ].mType = TYPE_TRANSLATION; + mAxisConfig[ ID_X ].mGetValueMethod = &JXInput::getX; + + mAxisConfig[ ID_Y ].mIsAvailable = false; + mAxisConfig[ ID_Y ].mType = TYPE_TRANSLATION; + mAxisConfig[ ID_Y ].mGetValueMethod = &JXInput::getY; + + mAxisConfig[ ID_Z ].mIsAvailable = false; + mAxisConfig[ ID_Z ].mType = TYPE_TRANSLATION; + mAxisConfig[ ID_Z ].mGetValueMethod = &JXInput::getZ; + + mAxisConfig[ ID_ROTX ].mIsAvailable = false; + mAxisConfig[ ID_ROTX ].mType = TYPE_ROTATION; + mAxisConfig[ ID_ROTX ].mGetValueMethod = &JXInput::getRotX; + + mAxisConfig[ ID_ROTY ].mIsAvailable = false; + mAxisConfig[ ID_ROTY ].mType = TYPE_ROTATION; + mAxisConfig[ ID_ROTY ].mGetValueMethod = &JXInput::getRotY; + + mAxisConfig[ ID_ROTZ ].mIsAvailable = false; + mAxisConfig[ ID_ROTZ ].mType = TYPE_ROTATION; + mAxisConfig[ ID_ROTZ ].mGetValueMethod = &JXInput::getRotZ; + + mAxisConfig[ ID_SLIDER0 ].mIsAvailable = false; + mAxisConfig[ ID_SLIDER0 ].mType = TYPE_SLIDER; + mAxisConfig[ ID_SLIDER0 ].mGetValueMethod = &JXInput::getSlider0; + + mAxisConfig[ ID_SLIDER1 ].mIsAvailable = false; + mAxisConfig[ ID_SLIDER1 ].mType = TYPE_SLIDER; + mAxisConfig[ ID_SLIDER1 ].mGetValueMethod = &JXInput::getSlider1; +} + + +/** + * Initialize buttons configuration array. + */ +void JXInput::initButtonsConfig() +{ + for ( int i = 0; i < JXINPUT_MAX_BUTTONS; ++i ) + { + mButtonConfig[ i ].mIsAvailable = false; + mButtonConfig[ i ].mName[ 0 ] = '\0'; + mButtonConfig[ i ].mType = TYPE_PUSHBUTTON; + } + +} + + +/** + * Initialize directionals configuration array. + */ +void JXInput::initDirectionalsConfig() +{ + for ( int i = 0; i < JXINPUT_MAX_DIRECTIONALS; ++i ) + { + mDirectionalConfig[ i ].mIsAvailable = false; + mDirectionalConfig[ i ].mName[ 0 ] = '\0'; + } + +} + + + +//----------------------------------------------------------------------------- +// Name: EnumAxesCallback() +// Desc: Callback function for enumerating the axes on a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInput::EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + JXInput* pThis = (JXInput*)pContext; + + AxisConfig* pAxCfg = NULL; + + // Set the UI to reflect what objects the joystick supports + // Code derived from M$ samples, really sucks, eh? + if (pdidoi->guidType == GUID_XAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_X ]; + } + if (pdidoi->guidType == GUID_YAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_Y ]; + } + if (pdidoi->guidType == GUID_ZAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_Z ]; + } + if (pdidoi->guidType == GUID_RxAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_ROTX ]; + } + if (pdidoi->guidType == GUID_RyAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_ROTY ]; + } + if (pdidoi->guidType == GUID_RzAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_ROTZ ]; + } + if (pdidoi->guidType == GUID_Slider) + { + switch( pThis->mSliderCount++ ) + { + case 0 : + pAxCfg = & pThis->mAxisConfig[ ID_SLIDER0 ]; + break; + + case 1 : + pAxCfg = & pThis->mAxisConfig[ ID_SLIDER1 ]; + break; + } + } + + // fail-safe + if( NULL == pAxCfg ) // e.g. GUID_Unknown + return DIENUM_CONTINUE; + + + // + // Perform config. + // + + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis + + // Get the range for the axis + if( FAILED( pThis->mpJoystick->GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) + return DIENUM_CONTINUE; + + pAxCfg->mMinValue = diprg.lMin; + pAxCfg->mMaxValue = diprg.lMax; + + strcpy( (char*)pAxCfg->mName, (char*)pdidoi->tszName ); + pAxCfg->mIsAvailable = true; + + return DIENUM_CONTINUE; +} + + + +//----------------------------------------------------------------------------- +// Name: EnumButtonsCallback() +// Desc: Callback function for enumerating the axes on a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInput::EnumButtonsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + JXInput* pThis = (JXInput*)pContext; + + // + // if the maximum number of buttons is already registered, + // issue a warning and stop enumeration. + // + if( JXINPUT_MAX_BUTTONS == pThis->mButtonCount ) + { + OutputDebugString( "Max. number of buttons exceeded!" ); + return DIENUM_STOP; + } + + + ButtonConfig* pBtCfg = NULL; + + if ( pdidoi->guidType == GUID_Button ) + { + assert( JXINPUT_MAX_BUTTONS > pThis->mButtonCount ); + pBtCfg = & pThis->mButtonConfig[ pThis->mButtonCount++ ]; + } + + + // fail-safe + if( NULL == pBtCfg ) // e.g. unknown stuff + return DIENUM_CONTINUE; + assert( NULL != pBtCfg ); + + // + // Perform config. + // + + strcpy( (char*)pBtCfg->mName, (char*)pdidoi->tszName ); + pBtCfg->mIsAvailable = true; + + return DIENUM_CONTINUE; +} + + +//----------------------------------------------------------------------------- +// Name: EnumPOVsCallback() +// Desc: Callback function for enumerating the axes on a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInput::EnumPOVsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + JXInput* pThis = (JXInput*)pContext; + + // + // if the maximum number of buttons is already registered, + // issue a warning and stop enumeration. + // + if( JXINPUT_MAX_DIRECTIONALS == pThis->mPOVCount ) + { + OutputDebugString( "Max. number of POVs exceeded!" ); + return DIENUM_STOP; + } + + DirectionalConfig* pDirCfg = NULL; + + + if (pdidoi->guidType == GUID_POV) + { + assert( JXINPUT_MAX_DIRECTIONALS > pThis->mPOVCount ); + pDirCfg = & pThis->mDirectionalConfig[ pThis->mPOVCount++ ]; + } + + // fail-safe + if( NULL == pDirCfg ) // e.g. unknown stuff + return DIENUM_CONTINUE; + assert( NULL != pDirCfg ); + + // + // Perform config. + // + + strcpy( (char*)pDirCfg->mName, (char*)pdidoi->tszName ); + pDirCfg->mIsAvailable = true; + + return DIENUM_CONTINUE; +} + + + +//----------------------------------------------------------------------------- +// Name: EnumEffectsCallback() +// Desc: Callback function for enumerating the effects of a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInput::EnumEffectsCallback( const DIEFFECTINFO* pdidoi, + VOID* pContext ) +{ + JXInput* pThis = (JXInput*)pContext; + + // + // Work on that!! + // + + return DIENUM_CONTINUE; +} + + + +//----------------------------------------------------------------------------- +// Name: InitDirectInput() +// Desc: Initialize the DirectInput variables. +//----------------------------------------------------------------------------- +HRESULT JXInput::InitDirectInput( HWND hWnd ) +{ + HRESULT hr; + + // Make sure we got a joystick + if( NULL == mpJoystick ) + { + return E_FAIL; + } + + + // + // Ask the device for some useful information. + // + mdiDevInfo.dwSize = sizeof( DIDEVICEINSTANCE ); + hr = mpJoystick->GetDeviceInfo( &mdiDevInfo ); + if( FAILED(hr) ) + return hr; + + // Set the data format to "simple joystick" - a predefined data format + // + // A data format specifies which controls on a device we are interested in, + // and how they should be reported. This tells DInput that we will be + // passing a DIJOYSTATE structure to IDirectInputDevice::GetDeviceState(). + hr = mpJoystick->SetDataFormat( &c_dfDIJoystick2 ); + if( FAILED(hr) ) + return hr; + + // Set the cooperative level to let DInput know how this device should + // interact with the system and with other DInput applications. +// hr = g_pJoystick->SetCooperativeLevel( hDlg, DISCL_EXCLUSIVE|DISCL_FOREGROUND ); + DWORD mode = ( NULL == hWnd ? DISCL_NONEXCLUSIVE|DISCL_BACKGROUND : DISCL_EXCLUSIVE|DISCL_BACKGROUND ); + hr = mpJoystick->SetCooperativeLevel( hWnd, mode ); + if( FAILED(hr) ) + return hr; + + // Determine how many axis the joystick has (so we don't error out setting + // properties for unavailable axis) + mdiDevCaps.dwSize = sizeof(DIDEVCAPS); + hr = mpJoystick->GetCapabilities(&mdiDevCaps); + if ( FAILED(hr) ) + return hr; + + + // Enumerate the axes of the joyctick and set the range of each axis. Note: + // we could just use the defaults, but we're just trying to show an example + // of enumerating device objects (axes, buttons, etc.). + mpJoystick->EnumObjects( EnumAxesCallback, (VOID*)this, DIDFT_AXIS ); + mpJoystick->EnumObjects( EnumButtonsCallback, (VOID*)this, DIDFT_BUTTON ); + mpJoystick->EnumObjects( EnumPOVsCallback, (VOID*)this, DIDFT_POV ); + + mpJoystick->EnumEffects( EnumEffectsCallback, (VOID*)this, DIEFT_ALL ); + + // For FF sticks, switch on autocenter as long as we do not use real FF + SwitchAutoCenter( true ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: UpdateInputState() +// Desc: Get the input device's state and display it. +//----------------------------------------------------------------------------- +HRESULT JXInput::UpdateInputState() +{ + HRESULT hr; + + if( mpJoystick ) + { + + // Poll the device to read the current state + hr = mpJoystick->Poll(); + if( FAILED(hr) ) + { + // DInput is telling us that the input stream has been + // interrupted. We aren't tracking any state between polls, so + // we don't have any special reset that needs to be done. We + // just re-acquire and try again. + hr = mpJoystick->Acquire(); + while( hr == DIERR_INPUTLOST ) + hr = mpJoystick->Acquire(); + + // hr may be DIERR_OTHERAPPHASPRIO or other errors. This + // may occur when the app is minimized or in the process of + // switching, so just try again later + return S_OK; + } + + // Get the input's device state + if( FAILED( hr = mpJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &mJS ) ) ) + return hr; // The device should have been acquired during the Poll() + + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: FreeDirectInput() +// Desc: Initialize the DirectInput variables. +//----------------------------------------------------------------------------- +HRESULT JXInput::FreeDirectInput() +{ + // Unacquire and release any DirectInputDevice objects. + if( NULL != mpJoystick ) + { + // Unacquire the device one last time just in case + // the app tried to exit while the device is still acquired. + mpJoystick->Unacquire(); + + mpJoystick->Release(); + mpJoystick = NULL; + } + + return S_OK; +} + + + +HRESULT JXInput::SwitchAutoCenter( bool onoff ) +{ + HRESULT hr; + + DIPROPDWORD DIPropAutoCenter; + + DIPropAutoCenter.diph.dwSize = sizeof(DIPropAutoCenter); + DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER); + DIPropAutoCenter.diph.dwObj = 0; + DIPropAutoCenter.diph.dwHow = DIPH_DEVICE; + DIPropAutoCenter.dwData = ( onoff ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF ); + + hr = mpJoystick->SetProperty( DIPROP_AUTOCENTER, &DIPropAutoCenter.diph ); + return hr; +} diff --git a/win32/jxinput.dsp b/win32/jxinput.dsp new file mode 100644 index 0000000..aac15c1 --- /dev/null +++ b/win32/jxinput.dsp @@ -0,0 +1,175 @@ +# Microsoft Developer Studio Project File - Name="jxinput" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=jxinput - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "jxinput.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "jxinput.mak" CFG="jxinput - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "jxinput - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "jxinput - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "jxinput - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JXINPUT_EXPORTS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "C:\j2sdk1.4.2\include" /I "C:\j2sdk1.4.2\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JXINPUT_EXPORTS" /FR /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 dxguid.lib dinput8.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\build\jxinput.dll" + +!ELSEIF "$(CFG)" == "jxinput - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JXINPUT_EXPORTS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "C:\j2sdk1.4.2\include" /I "C:\j2sdk1.4.2\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JXINPUT_EXPORTS" /FR /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 dxguid.lib dinput8.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\Classes\jxinput.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "jxinput - Win32 Release" +# Name "jxinput - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\de_hardcode_jxinput_directinput_DirectInputDriver.cpp +# End Source File +# Begin Source File + +SOURCE=.\dllmain.cpp +# End Source File +# Begin Source File + +SOURCE=.\jxinput.cpp +# End Source File +# Begin Source File + +SOURCE=.\JXInputManager.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\de_hardcode_jxinput_directinput_DirectInputDriver.h + +!IF "$(CFG)" == "jxinput - Win32 Release" + +# PROP Ignore_Default_Tool 1 +USERDEP__DE_HA="..\classes\de\hardcode\jxinput\directinput\DirectInputDriver.class" +# Begin Custom Build +InputPath=.\de_hardcode_jxinput_directinput_DirectInputDriver.h + +"de_hardcode_jxinput_directinput_DirectInputDriver.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cd ..\Classes + C:\j2sdk1.4.2\bin\javah -classpath . -d ..\win32 de.hardcode.jxinput.directinput.DirectInputDriver + cd ..\win32 + +# End Custom Build + +!ELSEIF "$(CFG)" == "jxinput - Win32 Debug" + +# PROP Ignore_Default_Tool 1 +USERDEP__DE_HA="..\classes\de\hardcode\jxinput\directinput\DirectInputDriver.class" +# Begin Custom Build +InputPath=.\de_hardcode_jxinput_directinput_DirectInputDriver.h + +"de_hardcode_jxinput_directinput_DirectInputDriver.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cd ..\Classes + C:\j2sdk1.4.2\bin\javah -classpath . -d ..\win32 de.hardcode.jxinput.directinput.DirectInputDriver + cd ..\win32 + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\jxinput.h +# End Source File +# Begin Source File + +SOURCE=.\JXInputManager.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/win32/jxinput.dsw b/win32/jxinput.dsw new file mode 100644 index 0000000..deb2877 --- /dev/null +++ b/win32/jxinput.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "jxinput"=".\jxinput.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/win32/jxinput.h b/win32/jxinput.h new file mode 100644 index 0000000..6d47a31 --- /dev/null +++ b/win32/jxinput.h @@ -0,0 +1,183 @@ + +#define JXINPUT_MAX_AXES 8 +#define JXINPUT_MAX_BUTTONS 256 +#define JXINPUT_MAX_DIRECTIONALS 4 + + +/** + * This class will be exported by jxinput.dll. + */ +class JXINPUT_API JXInput +{ + +public: + + typedef enum AXISTYPE + { + TYPE_TRANSLATION, + TYPE_ROTATION, + TYPE_SLIDER + }; + + typedef enum BUTTONTYPE + { + TYPE_PUSHBUTTON, + TYPE_TOGGLEBUTTON + }; + + typedef enum AXISID + { + ID_X, ID_Y, ID_Z, + ID_ROTX, ID_ROTY, ID_ROTZ, + ID_SLIDER0, ID_SLIDER1 + }; + + + // + // Ctor + // + JXInput( LPDIRECTINPUTDEVICE8 pJoystick, HWND hWnd = NULL ); + + // + // Dtor + // + virtual ~JXInput(); + + // + // Operational methods + // + void update(); + + // Ask for the name + TCHAR * const getName() const; + + // + // Numbering methods + // + int getNumberOfAxes() const; + int getNumberOfButtons() const; + int getNumberOfDirectionals() const; + + + // + // Access axes + // + double getX() const; /** -1.0 .... 1.0 */ + double getY() const; /** -1.0 .... 1.0 */ + double getZ() const; /** -1.0 .... 1.0 */ + double getRotX() const; /** -1.0 .... 1.0 */ + double getRotY() const; /** -1.0 .... 1.0 */ + double getRotZ() const; /** -1.0 .... 1.0 */ + double getSlider0() const; /** 0.0 .... 1.0 */ + double getSlider1() const; /** 0.0 .... 1.0 */ + + + // + // Axis methods + // + bool isAxisAvailable( int idx ) const; + TCHAR* const getAxisName( int idx ) const; + int getAxisType( int idx ) const; + double getAxisValue( int idx ) const; + + // + // Button methods + // + bool isButtonAvailable( int idx ) const; + TCHAR* const getButtonName( int idx ) const; + int getButtonType( int idx ) const; + bool isButtonDown( int idx ) const; + + // + // Directional methods + // + bool isDirectionalAvailable( int idx ) const; + TCHAR* const getDirectionalName( int idx ) const; + int getDirection( int idx ) const; + +private://----------------------------------------------------------------------------------------- + LPDIRECTINPUTDEVICE8 mpJoystick; + + DIDEVICEINSTANCE mdiDevInfo; + DIDEVCAPS mdiDevCaps; + DIJOYSTATE2 mJS; // DInput joystick state + + int mSliderCount; + int mPOVCount; + int mButtonCount; + + double getAxisValueHelper( LONG val, int idx ) const; + + HRESULT SwitchAutoCenter( bool onoff = true ); + + HRESULT InitDirectInput( HWND hWnd = NULL ); + HRESULT FreeDirectInput(); + HRESULT UpdateInputState(); + + + static BOOL CALLBACK EnumAxesCallback + ( + const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext + ); + + static BOOL CALLBACK EnumButtonsCallback + ( + const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext + ); + + static BOOL CALLBACK EnumPOVsCallback + ( + const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext + ); + + static BOOL CALLBACK EnumEffectsCallback + ( + const DIEFFECTINFO* pdidoi, + VOID* pContext + ); + + + class JXINPUT_API AxisConfig + { + + public: + bool mIsAvailable; + CHAR mName[MAX_PATH]; + AXISTYPE mType; + LONG mMinValue; + LONG mMaxValue; + double (JXInput::*mGetValueMethod)() const; + + } mAxisConfig [ JXINPUT_MAX_AXES ]; + + void initAxisConfig(); + + + class JXINPUT_API ButtonConfig + { + + public: + bool mIsAvailable; + CHAR mName[MAX_PATH]; + BUTTONTYPE mType; + + } mButtonConfig[ JXINPUT_MAX_BUTTONS ]; + + void initButtonsConfig(); + + + class JXINPUT_API DirectionalConfig + { + + public: + bool mIsAvailable; + CHAR mName[MAX_PATH]; + + } mDirectionalConfig[ JXINPUT_MAX_DIRECTIONALS ]; + + void initDirectionalsConfig(); +}; + diff --git a/win32/jxinput.sln b/win32/jxinput.sln new file mode 100644 index 0000000..714fdc7 --- /dev/null +++ b/win32/jxinput.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jxinput", "jxinput.vcproj", "{8AEA84DC-D8F0-4425-BEBF-A84E91115F76}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8AEA84DC-D8F0-4425-BEBF-A84E91115F76}.Debug|Win32.ActiveCfg = Debug|Win32 + {8AEA84DC-D8F0-4425-BEBF-A84E91115F76}.Debug|Win32.Build.0 = Debug|Win32 + {8AEA84DC-D8F0-4425-BEBF-A84E91115F76}.Release|Win32.ActiveCfg = Release|Win32 + {8AEA84DC-D8F0-4425-BEBF-A84E91115F76}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/jxinput.vcproj b/win32/jxinput.vcproj new file mode 100644 index 0000000..c87fc0f --- /dev/null +++ b/win32/jxinput.vcproj @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/.cvsignore b/www/.cvsignore new file mode 100644 index 0000000..a46c908 --- /dev/null +++ b/www/.cvsignore @@ -0,0 +1,5 @@ +.nbattrs +*~ +javadoc + + diff --git a/www/hardcode.gif b/www/hardcode.gif new file mode 100644 index 0000000..de640ec Binary files /dev/null and b/www/hardcode.gif differ diff --git a/www/images/dl-javawebstart3.jpg b/www/images/dl-javawebstart3.jpg new file mode 100644 index 0000000..2c1420d Binary files /dev/null and b/www/images/dl-javawebstart3.jpg differ diff --git a/www/images/download-button.gif b/www/images/download-button.gif new file mode 100644 index 0000000..b815543 Binary files /dev/null and b/www/images/download-button.gif differ diff --git a/www/images/download.j2se14.gif b/www/images/download.j2se14.gif new file mode 100644 index 0000000..cf0bad6 Binary files /dev/null and b/www/images/download.j2se14.gif differ diff --git a/www/images/downloadj3d.gif b/www/images/downloadj3d.gif new file mode 100644 index 0000000..4e0536a Binary files /dev/null and b/www/images/downloadj3d.gif differ diff --git a/www/images/footpedal-pic.gif b/www/images/footpedal-pic.gif new file mode 100644 index 0000000..e627bf7 Binary files /dev/null and b/www/images/footpedal-pic.gif differ diff --git a/www/images/getjavanow.gif b/www/images/getjavanow.gif new file mode 100644 index 0000000..bbf6f3e Binary files /dev/null and b/www/images/getjavanow.gif differ diff --git a/www/images/jxinput_architecture.gif b/www/images/jxinput_architecture.gif new file mode 100644 index 0000000..60a19c1 Binary files /dev/null and b/www/images/jxinput_architecture.gif differ diff --git a/www/index.htm b/www/index.htm new file mode 100644 index 0000000..d1734ed --- /dev/null +++ b/www/index.htm @@ -0,0 +1,18 @@ + + + + + + + + +JXInput - Gaming Input Devices (joystick/gamepad/DirectInput) for Java + + + + + + +Joystick Java Gamepad DirectInput JNI + + diff --git a/www/jnlp/JXInput.jar b/www/jnlp/JXInput.jar new file mode 100644 index 0000000..f2cff97 Binary files /dev/null and b/www/jnlp/JXInput.jar differ diff --git a/www/jnlp/JXInputKeystore b/www/jnlp/JXInputKeystore new file mode 100644 index 0000000..0ed7755 Binary files /dev/null and b/www/jnlp/JXInputKeystore differ diff --git a/www/jnlp/jxinput.dll b/www/jnlp/jxinput.dll new file mode 100644 index 0000000..8ff71f9 Binary files /dev/null and b/www/jnlp/jxinput.dll differ diff --git a/www/jnlp/jxinputdll.jar b/www/jnlp/jxinputdll.jar new file mode 100644 index 0000000..0436405 Binary files /dev/null and b/www/jnlp/jxinputdll.jar differ diff --git a/www/jnlp/jxinputtestdialog.jnlp b/www/jnlp/jxinputtestdialog.jnlp new file mode 100644 index 0000000..bcf5d9d --- /dev/null +++ b/www/jnlp/jxinputtestdialog.jnlp @@ -0,0 +1,28 @@ + + + + JXInput Test Dialog + HARDCODE Development + + Demonstration of JXInput + A Test Dialog + + + + + + + + + + + + + + + + + + diff --git a/www/jnlp/sign.bat b/www/jnlp/sign.bat new file mode 100644 index 0000000..0ca94fc --- /dev/null +++ b/www/jnlp/sign.bat @@ -0,0 +1,8 @@ +rem keytool -genkey -alias jxinput -keypass jxinput -keystore JXInputKeystore + +set PATH=c:\j2sdk1.4.1\bin;%PATH% +copy /Y ..\..\Distribution\0.3\JXInput.jar . +copy /Y ..\..\Distribution\0.3\jxinput.dll . +jar cf jxinputdll.jar jxinput.dll +jarsigner -keystore JXInputKeystore -storepass jxinput -keypass jxinput JXInput.jar jxinput +jarsigner -keystore JXInputKeystore -storepass jxinput -keypass jxinput jxinputdll.jar jxinput \ No newline at end of file diff --git a/www/jxdownload.htm b/www/jxdownload.htm new file mode 100644 index 0000000..ec84e9b --- /dev/null +++ b/www/jxdownload.htm @@ -0,0 +1,105 @@ + + + + + + + +Download - Gaming Input Devices (joystick/gamepad/DirectInput) for Java + + + + + + +

Download and Installation

+

+

+ + +

Prerequisits

+

+In order to operate JXInput a Java Runtime Environment in version 1.3 or newer is needed. + +To compile the sourcecode, a corresponding JDK is useful for the Java source codes. The C++ +things have been developed with Microsoft Visual Studio 6.0. + +The Java technology may be downloaded here: + +

+ + + + +
+ + + + + + +
 Download J2SE 1.4 Now!Download
J2SETM v1.4 Now!
+
+ + +

+ + +Get Java Runtime +

+ +Get Java Web Start NOW! +

+ +Get Java3D +

+ + + +

Download distribution

+

+ +While downloading the package you agree with my +license agreement. +

+

+V0.3.3 runtime +
+V0.3.3 with source +
+

+ + +

Installation

+ +In order to operate, JXInput needs only two files. There is the file JXInput.jar that contains +the compiled Java classes and JXInput.dll holding the native code. +

+JXInput.jar has to be part of your CLASSPATH, JXInput.dll has to be in a place where Windows is +able to find it. I prefer to have the DLL just in the directory where the application starts. +

+Place both files into one directory and double-click JXInput.jar. If your JRE is setup +correctly, this should start an dialog showing what your inputdevice is able to perform. +This is a good and easy test to find out wether everything is fine with JXInput. + + + + +

Older versions:

+ +
+V0.2.0 runtime +
+V0.2.0 with source +
+

+

+V0.1.0 runtime +
+V0.1.0 with source +
+

+ + + + diff --git a/www/jxinput_in_space/abstract.pdf b/www/jxinput_in_space/abstract.pdf new file mode 100644 index 0000000..152039c Binary files /dev/null and b/www/jxinput_in_space/abstract.pdf differ diff --git a/www/jxinput_in_space/canadarm2_training.jpg b/www/jxinput_in_space/canadarm2_training.jpg new file mode 100644 index 0000000..f67e68f Binary files /dev/null and b/www/jxinput_in_space/canadarm2_training.jpg differ diff --git a/www/jxinput_in_space/index.htm b/www/jxinput_in_space/index.htm new file mode 100644 index 0000000..008ed70 --- /dev/null +++ b/www/jxinput_in_space/index.htm @@ -0,0 +1,49 @@ + + + + + + + + + +JXInput - Gaming Input Devices in space! (joystick/gamepad/DirectInput/Java) + + + + + +

+

JXInput - now in space on the ISS!

+ +
+

+JXInput found it's way to the ISS (International Space +Station). There, it +allows a Java-written simulation program to connect to the custom input device +used by the astronauts to control the robot +Canadarm2. + +

+

+
+
+ + +

+the device +
+

+ +

+simulation running +
+

+ +

+from ISS presskit +
+

+ + + diff --git a/www/jxinput_in_space/smp_hardware_components.jpg b/www/jxinput_in_space/smp_hardware_components.jpg new file mode 100644 index 0000000..eeaffe8 Binary files /dev/null and b/www/jxinput_in_space/smp_hardware_components.jpg differ diff --git a/www/jxinput_in_space/smp_simulation_running.jpg b/www/jxinput_in_space/smp_simulation_running.jpg new file mode 100644 index 0000000..9802406 Binary files /dev/null and b/www/jxinput_in_space/smp_simulation_running.jpg differ diff --git a/www/jxlicense.htm b/www/jxlicense.htm new file mode 100644 index 0000000..ae69409 --- /dev/null +++ b/www/jxlicense.htm @@ -0,0 +1,53 @@ + + +JXInput - License Agreement + + + + + + + + +

+ +

JXInput - License Agreement - Gaming Input Devices (joystick/gamepad/DirectInput) for Java

+

+ +IF YOU DO NOT AGREE TO THE TERMS OF THIS AGREEMENT, DO NOT USE THIS SOFTWARE! +

+

+Software is copyrighted. JXInput software is the intellectual property of HARDCODE, + http://www.hardcode.de, + Dipl. Phys. Joerg Plewe, Muelheim, Germany. The author retains the copyright, title and ownership +of the provided software. +

+The provided software may be used and redistributed in non-commercial applications. +The right is limited to the current version of the software and does not include +the right to upgrades, updates or further developed versions.
+

+Commercial use of the provided software requires licensing. Licenses can be requested +by mail to jxinput@hardcode.de. +

+You are not permitted to sell, lease, decompile or modify the JXInput module +provided in jxinput.jar/jxinput.dll without the permission of the author. All open code +(Java/C++ files) is public domain and can be used without any restrictions.
+

+JXInput SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OR LIABILITY. +THE ENTIRE RISK AS TO THE RESULTS OF THE USAGE OF THE SOFTWARE IS ASSUMED BY +YOU. +

+ +Conditions for redistribution of the provided software in non-commercial applications: +

    +
  • Redistribution is only permitted if the original and unmodified files jxinput.jar/jxinput.dll are supplied.
  • + +
  • This license file is to be placed in the same folder as jxinput.jar. Should the +name of this file conflict with other files in the same folder, it can be +renamed to "jxinput_lic.html". +
  • +
      +

      + + + \ No newline at end of file diff --git a/www/jxlinks.htm b/www/jxlinks.htm new file mode 100644 index 0000000..37325ad --- /dev/null +++ b/www/jxlinks.htm @@ -0,0 +1,53 @@ + + + + + + + + +JXLinks - Gaming Input Devices (joystick/gamepad/DirectInput) for Java + + + + + + + +

      Links

      +

      +

      + + +

      Other input devices with Java

      + + + +

      Java related links

      + + + + + + + diff --git a/www/jxversion.htm b/www/jxversion.htm new file mode 100644 index 0000000..bedeca4 --- /dev/null +++ b/www/jxversion.htm @@ -0,0 +1,98 @@ + + + + + + + + + +Version - Gaming Input Devices (joystick/gamepad/DirectInput) for Java + + + + + + +

      Version

      + +The current version of the package is V0.3.3. + +

      How are the versions counted?

      + +The goal of the development is version V1.0. V1.0 means the whole thing is +feature-complete, tested, documented. Additionally some people should have agreed +that the design is useful. + +Meanwhile, the version number will increase in the first decimal whenever a +significant change in one of the interfaces occured or a new features is added. +For minor changes like bugfixes, non-code-breaking enhancements or additional +documentation, the second decimal will be counted. +

      +A new version will be released as soon as it is implemented. That means that +versions like 0.X.0 may lack of samples or documentation. +

      + +

      History

      + +

      V0.3:

      + +
        +
      • JXInput gives access to the Swing keyboard interpreted as buttons. +
      • 'Virtual' axes can be emulated with the help of buttons (e.g. from the keyboard). +
      + +

      V0.3.1:

      + +
        +
      • JXInputManager#createKeyboardDevice() needs only Component + instead of JComponent. +
      • Online demo with WebStart . +
      • Bugfixes. +
      • Improved documentation. +
      + +

      V0.3.2:

      + +
        +
      • Bugfix: Z-axis now works correctly. +
      + +

      V0.3.3:

      + +
        +
      • Introduced overall reset()-method that allows to changes devices at +runtime. +
      • The type of virtual axes (TRANSLATIONAL, ROTATIONAL, SLIDER) can be set explicitely. +
      • Success story: JXInput used in space. +
      + + +

      V0.2:

      + +
        +
      • Support of DirectX8. +
      • +
      • Support of multiple devices. +
      • +
      • Introduced eventing system (de.hardcode.jxinput.event). +
      • +
      • Support of Java3D sensoring interface (de.hardcode.jxinput.j3d). +
      + + +

      V0.1:

      + +
        +
      • First attempts with DirectInput and JNI. +
      • +
      • Setup of project structure. +
      • +
      • Setup of project structure. +
      • +
      • Tests with WebStart. + +
      + + + diff --git a/www/leftmenu.htm b/www/leftmenu.htm new file mode 100644 index 0000000..4ec8bb7 --- /dev/null +++ b/www/leftmenu.htm @@ -0,0 +1,33 @@ + + + + + + + + +Menu - Gaming Input Devices (joystick/gamepad/DirectInput) for Java + + + + + +About JXInput +

      +Version +

      +Documentation +

      +Contact +

      +Download +

      +Links +

      +Test Online! +

      + +

      + + +