mindaptiv / Saul

Grabs system and user information in an Android context.
MIT License
1 stars 0 forks source link

KeyEvent Handling #36

Closed Scrubsauce closed 9 years ago

Scrubsauce commented 9 years ago

In order to detect the current state of the gamepad in Android, we have to process events either from the main activity object or the current view object. Activity was the easiest route from examples and documentation, so I went down that route for further information.

While XINPUT could just tell us what the current state was, we're going to have to build that state in Saul.

In order to send incoming KeyEvents out to your code, you have to override the dispatchKeyEvent() method for the activity, then (based on my understanding from docs and examples), Android will execute this function whenever a KeyEvent occurs.

There is a point of concern in that this code seems like it was intended for a slightly different context than what we're using it for. In the instance of a game loop, you would dispatch a KeyEvent to your game View, then the game View would process the input and save it for use during its update loop (or in yet another layer lower update method for a controller/player character/etc.).

Here we're not running any game loop, and are just trying to get a snapshot of what the gamepad is up to before we ship off the Cylon. After drawing/erasing/redrawing/re-reading docs several times I came up with this:

20150406_134817

The main activity's dispatchKeyEvent method would need to be overridden to point to the handler located in Cylon. Other examples have this code pointing directly to the controller, but since we're actively trying to determine what (if any) controllers there are AND all of this is occurring in a library external from the main activity that's not an option.

Instead, since we'll only ever be creating one Cylon at a time for the current device, I propose we make said Cylon a member variable of the main activity, so we can directly call its KeyEvent handler, which will then inspect the id value of the key event, and adjust the buttons mask of the appropriate device.

This means that we need to take into account three things when we start creating the actual application on Android (the thing Saul will plug into):

  1. That the main activity class will have a Cylon member variable that Saul can fill in, instead of creating a Cylon at runtime within the onCreate method. (The difference being right now is in the main function we call Cylon saul = new Cylon(); but what we need instead for this to work is this.saul = new Cylon())
  2. (not on the whiteboard requirements) The main activity class will need to have its dispatchKeyListener() method overridden and pointed towards Cylon.java's handler function.
  3. We'll have to accept that the state of any controllers we receive will be "in flux" and not a constant value until we send the value over to native code for export to Essence.

Before I can proceed, I need to know if this a. makes sense/are we now on the same page with what's going on here and b. if there are any issues with the above 3 points.

Simulacrum0 commented 9 years ago

a). Makes sense to me as a solution. Wondering if there's a NativeCode backdoor to read the state, like XINPUT and other systems. Seems like a lot of coding work, a lot of runtime functions/potential-latency, and an overall messy way to detect input. I would not be surprised at all if this was indeed, 'the best way to do it' on Android. Have you checked the Oculus OpenVR SDK used for Samsung GearVR? All open source, certainly supports controllers/input. Might not be helpful, but an idea-

b). All the issues in 1..3 seem sensible and doable. Am assuming you'll add a 'Saul' member variable to your Test Framework that i'll replicate in our Android "Host" structure and add the same init calls, passing over the dispatchKeyListener() stuff as well.

Scrubsauce commented 9 years ago

Seems like the Oculus Mobile SDK at least uses the same dispatching method to catch events, so we'd have to start in the same place as with the above, but they do pass data to native code... Problem is native code still has to rely on the workflow of the event handler: Input to the application is intercepted in the Java code in VrActivity.java in the dispatchKeyEvent() method. If the event is NOT of type ACTION_DOWN or ACTION_UP, the event passed to the default dispatchKeyEvent() handler. If this is a volume up or down action, it is handled in Java code. Otherwise the key is passed to the buttonEvent() method. buttonEvent()passes the event to nativeKeyEvent(). https://developer.oculus.com/documentation/#filter=mobile

Simulacrum0 commented 9 years ago

Ugh-