Hi,
when I bind a GameControl to MouseOffsetBinding, I get reasonable values only if I move mouse in the first quadrant of established screen space. Is this intended behaviour or a bug? My mouse is not grabbed by the application (MouseInput.setCursorVisible(true)
Hmm, only in first quadrant?
Can you make a small example which shows the problem?
Sure, here it is:
package skunkworks;
import com.jme.app.SimpleGame;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.input.action.KeyExitAction;
import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.MouseAxisBinding;
import com.jme.input.controls.binding.MouseOffsetBinding;
import com.jme.scene.Controller;
/**
* @author deus
* @version 1.0
* @since Jan 22, 2009 3:10:54 PM
*/
public class MouseTest extends SimpleGame {
private GameControl axisXControl;
private GameControl axisYControl;
protected void simpleInitGame() {
input = new InputHandler();
input.addAction(new KeyExitAction(this), "exit", KeyInput.KEY_ESCAPE, false);
MouseInput.get().setCursorVisible(true);
GameControlManager gcm = new GameControlManager();
axisXControl = gcm.addControl("mouse-axis-x");
axisXControl.addBinding(new MouseOffsetBinding(MouseAxisBinding.AXIS_X, false));
axisYControl = gcm.addControl("mouse-axis-y");
axisYControl.addBinding(new MouseOffsetBinding(MouseAxisBinding.AXIS_Y, false));
rootNode.addController(new Controller() {
public void update(float v) {
System.out.println("mouse-x/y: " + axisXControl.getValue() + " / " + axisYControl.getValue());
}
});
}
public static void main(String[] args) {
MouseTest mt = new MouseTest();
mt.setConfigShowMode(ConfigShowMode.ShowIfNoConfig);
mt.start();
}
}
Notice that number log shows valid values only 0.0 when mouse is in top right quarter of screen space. If you move below half or to the left half, instead going to minus, it locks to 0.0.
Heres a patch:
Index: MouseOffsetBinding.java
--- MouseOffsetBinding.java Base (BASE)
+++ MouseOffsetBinding.java Locally Modified (Based On LOCAL)
@@ -94,11 +94,12 @@
}
private float convert(float value) {
- if ((value < 0) && (!reverse)) {
+ if( reverse && axis == MouseAxisBinding.AXIS_X && ( value < 0 ) ){
return 0.0f;
- } else if ((value > 0) && (reverse)) {
+ } else if( reverse && axis == MouseAxisBinding.AXIS_Y && ( value > 0 ) ){
return 0.0f;
}
+
return Math.abs((float) value * 0.01f);
}
Also, the values will never go negative (although I think they should...); simply because of the (existing) Math.abs when returning the value...
Where did all these mouse bugs come from? Did they just all happen to be discovered at the same time, or have we updated LWJGL already and its a result of this? WIERD
I was wondering the same thing…
(although I don't think the LWJGL update is responsible)
Actually that might not be a Bug at all.
Look at TestMouseOffsetBinding.
There 4 GameControls are used up, down left and right. (thats how i use it in Stardust too), the GameControls are then used as Input for the RotationController which actually rotates the object.
With the patch, the Test dosen't work anymore
Good find. So its just a usage problem.
Well then maybe it's the JavaDoc that needs to be updated:
/**
* @param axis
* MouseAxisBinding.AXIS_X or AXIS_Y
* @param reverse
* true means only track the right/lower part of the screen
*/
public MouseOffsetBinding(int axis, boolean reverse) {
Thats what I changed the patch to do (true tracked only right/lower, false tracked whole screen)
Here are the screen quadrants:
x+true=yes | x+true=no
x+false=no | x+false=yes
y+true=no | y+true=no
y+false=yes | y+false=yes
+
x+true=yes | x+true=no
x+false=no | x+false=yes
y+true=yes | y+true=yes
y+false=no | y+false=no
(x/y=axis, true/false=reverse, yes/no=mouse tracked in quadrant)
Maybe something like this should be included...
(and actually the current JavaDoc is wrong, true means to track left/lower)
Does anyone else feel I should update the JavaDoc? To me it didn't seem very intuitive (in fact it was counter intuitive) but maybe thats just a personal matter
edit: should have done this in the earlier post…
Simple test used to get output (above):
import com.jme.app.SimpleGame;
import com.jme.input.MouseInput;
import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.MouseAxisBinding;
import com.jme.input.controls.binding.MouseOffsetBinding;
import com.jme.scene.Controller;
public class MouseOffsetTest extends SimpleGame {
protected void simpleInitGame() {
MouseInput.get().setCursorVisible( true );
GameControlManager gcm = new GameControlManager();
final GameControl axisXControl_TRUE = gcm.addControl( "mouse-axis-x" );
axisXControl_TRUE.addBinding( new MouseOffsetBinding( MouseAxisBinding.AXIS_X, true ) );
final GameControl axisYControl_TRUE = gcm.addControl( "mouse-axis-y" );
axisYControl_TRUE.addBinding( new MouseOffsetBinding( MouseAxisBinding.AXIS_Y, true ) );
final GameControl axisXControl_FALSE = gcm.addControl( "mouse-axis-x2" );
axisXControl_FALSE.addBinding( new MouseOffsetBinding( MouseAxisBinding.AXIS_X, false ) );
final GameControl axisYControl_FALSE = gcm.addControl( "mouse-axis-y2" );
axisYControl_FALSE.addBinding( new MouseOffsetBinding( MouseAxisBinding.AXIS_Y, false ) );
rootNode.addController( new Controller() {
public void update( float v ) {
System.out.println( "x+true = " + ( axisXControl_TRUE.getValue() != 0 ? " yes" : " no" ) + " |" );
System.out.println( "x+false = " + ( axisXControl_FALSE.getValue() != 0 ? "yes" : " no" ) + " |" );
System.out.println( "y+true = " + ( axisYControl_TRUE.getValue() != 0 ? " yes" : " no" ) + " |" );
System.out.println( "y+false = " + ( axisYControl_FALSE.getValue() != 0 ? "yes" : " no" ) + " |" );
System.out.println( "nn" );
}
} );
}
public static void main( String[] args ) {
new MouseOffsetTest().start();
}
}
Don't you think that the sample code shows that usage is a bit more complicated than simply returning minus values from center of the screen? Is there any advantage to class behavior working in this exact way? I have two controls for something that I intuitively feel should be only one control.
I have no problem with changing the behavior if it gets easier to use.
When i created MouseOffsetBinding i also found it a bit strange first, but it was based on MouseAxisBinding which does it the same way i think.
And it works nicely.
If the bindings are changed i guess the RotationController etc. would have to change too, since they receive separate GameControls for positive / negative values. (see TestMouseOffsetBinding)
The whole GameControl system needs to stay consistent somehow
Um, don't get me wrong, I didn't mean to say its bad now I spent almost 4 days refactoring our code to use GameControlManager input system for a reason
I was simply curious if there is any advantage to using it this way. For example, does the Binding.getValue() contracts that only values ranging 0.0F - 1.0F can be returned? If you tell me, I might have an idea how to make our controls configuration even better and more flexible.
Regarding MouseAxisBinding, you're right, I actually never noticed that it returns positive values only while testing it. And btw, that class doesn't work if mouse is not grabbed by application (at least on my system).
Um, don't get me wrong
no worries :)
i think a few more tests using different GameControls / Bindings (maybe replacing them on the fly) could help to understand the possibilities better.