mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-19 21:13:12 -07:00
Add Motion to Android
This commit is contained in:
parent
2a4b67b58e
commit
2906cfdd69
3 changed files with 95 additions and 13 deletions
|
@ -1,19 +1,36 @@
|
||||||
package com.metallic.chiaki.session
|
package com.metallic.chiaki.session
|
||||||
|
|
||||||
import android.util.Log
|
import android.content.Context
|
||||||
import android.view.InputDevice
|
import android.hardware.*
|
||||||
import android.view.KeyEvent
|
import android.view.*
|
||||||
import android.view.MotionEvent
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleObserver
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
import com.metallic.chiaki.common.Preferences
|
import com.metallic.chiaki.common.Preferences
|
||||||
import com.metallic.chiaki.lib.ControllerState
|
import com.metallic.chiaki.lib.ControllerState
|
||||||
|
|
||||||
class StreamInput(val preferences: Preferences)
|
class StreamInput(val context: Context, val preferences: Preferences)
|
||||||
{
|
{
|
||||||
var controllerStateChangedCallback: ((ControllerState) -> Unit)? = null
|
var controllerStateChangedCallback: ((ControllerState) -> Unit)? = null
|
||||||
|
|
||||||
val controllerState: ControllerState get()
|
val controllerState: ControllerState get()
|
||||||
{
|
{
|
||||||
val controllerState = keyControllerState or motionControllerState
|
val controllerState = sensorControllerState or keyControllerState or motionControllerState
|
||||||
|
|
||||||
|
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||||
|
when(windowManager.defaultDisplay.rotation)
|
||||||
|
{
|
||||||
|
Surface.ROTATION_90 -> {
|
||||||
|
controllerState.accelX *= -1.0f
|
||||||
|
controllerState.accelZ *= -1.0f
|
||||||
|
controllerState.gyroX *= -1.0f
|
||||||
|
controllerState.gyroZ *= -1.0f
|
||||||
|
controllerState.orientX *= -1.0f
|
||||||
|
controllerState.orientZ *= -1.0f
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
// prioritize motion controller's l2 and r2 over key
|
// prioritize motion controller's l2 and r2 over key
|
||||||
// (some controllers send only key, others both but key earlier than full press)
|
// (some controllers send only key, others both but key earlier than full press)
|
||||||
|
@ -25,6 +42,7 @@ class StreamInput(val preferences: Preferences)
|
||||||
return controllerState or touchControllerState
|
return controllerState or touchControllerState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val sensorControllerState = ControllerState() // from Motion Sensors
|
||||||
private val keyControllerState = ControllerState() // from KeyEvents
|
private val keyControllerState = ControllerState() // from KeyEvents
|
||||||
private val motionControllerState = ControllerState() // from MotionEvents
|
private val motionControllerState = ControllerState() // from MotionEvents
|
||||||
var touchControllerState = ControllerState()
|
var touchControllerState = ControllerState()
|
||||||
|
@ -36,6 +54,65 @@ class StreamInput(val preferences: Preferences)
|
||||||
|
|
||||||
private val swapCrossMoon = preferences.swapCrossMoon
|
private val swapCrossMoon = preferences.swapCrossMoon
|
||||||
|
|
||||||
|
private val sensorEventListener = object: SensorEventListener {
|
||||||
|
override fun onSensorChanged(event: SensorEvent)
|
||||||
|
{
|
||||||
|
when(event.sensor.type)
|
||||||
|
{
|
||||||
|
Sensor.TYPE_ACCELEROMETER -> {
|
||||||
|
sensorControllerState.accelX = event.values[1] / SensorManager.GRAVITY_EARTH
|
||||||
|
sensorControllerState.accelY = event.values[2] / SensorManager.GRAVITY_EARTH
|
||||||
|
sensorControllerState.accelZ = event.values[0] / SensorManager.GRAVITY_EARTH
|
||||||
|
}
|
||||||
|
Sensor.TYPE_GYROSCOPE -> {
|
||||||
|
sensorControllerState.gyroX = event.values[1]
|
||||||
|
sensorControllerState.gyroY = event.values[2]
|
||||||
|
sensorControllerState.gyroZ = event.values[0]
|
||||||
|
}
|
||||||
|
Sensor.TYPE_ROTATION_VECTOR -> {
|
||||||
|
val q = floatArrayOf(0f, 0f, 0f, 0f)
|
||||||
|
SensorManager.getQuaternionFromVector(q, event.values)
|
||||||
|
sensorControllerState.orientX = q[2]
|
||||||
|
sensorControllerState.orientY = q[3]
|
||||||
|
sensorControllerState.orientZ = q[1]
|
||||||
|
sensorControllerState.orientW = q[0]
|
||||||
|
}
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
controllerStateUpdated()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val lifecycleObserver = object: LifecycleObserver {
|
||||||
|
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||||
|
fun onResume()
|
||||||
|
{
|
||||||
|
val samplingPeriodUs = 4000
|
||||||
|
val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||||
|
listOfNotNull(
|
||||||
|
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
|
||||||
|
sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
|
||||||
|
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
|
||||||
|
).forEach {
|
||||||
|
sensorManager.registerListener(sensorEventListener, it, samplingPeriodUs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||||
|
fun onPause()
|
||||||
|
{
|
||||||
|
val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||||
|
sensorManager.unregisterListener(sensorEventListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun observe(lifecycleOwner: LifecycleOwner)
|
||||||
|
{
|
||||||
|
lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
|
||||||
|
}
|
||||||
|
|
||||||
private fun controllerStateUpdated()
|
private fun controllerStateUpdated()
|
||||||
{
|
{
|
||||||
controllerStateChangedCallback?.let { it(controllerState) }
|
controllerStateChangedCallback?.let { it(controllerState) }
|
||||||
|
|
|
@ -5,6 +5,7 @@ package com.metallic.chiaki.stream
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
import android.animation.AnimatorListenerAdapter
|
import android.animation.AnimatorListenerAdapter
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
|
import android.content.res.Configuration
|
||||||
import android.graphics.Matrix
|
import android.graphics.Matrix
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
@ -58,9 +59,11 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel = ViewModelProvider(this, viewModelFactory {
|
viewModel = ViewModelProvider(this, viewModelFactory {
|
||||||
StreamViewModel(Preferences(this), LogManager(this), connectInfo)
|
StreamViewModel(application, connectInfo)
|
||||||
})[StreamViewModel::class.java]
|
})[StreamViewModel::class.java]
|
||||||
|
|
||||||
|
viewModel.input.observe(this)
|
||||||
|
|
||||||
setContentView(R.layout.activity_stream)
|
setContentView(R.layout.activity_stream)
|
||||||
window.decorView.setOnSystemUiVisibilityChangeListener(this)
|
window.decorView.setOnSystemUiVisibilityChangeListener(this)
|
||||||
|
|
||||||
|
@ -305,7 +308,6 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
||||||
|
|
||||||
override fun dispatchKeyEvent(event: KeyEvent) = viewModel.input.dispatchKeyEvent(event) || super.dispatchKeyEvent(event)
|
override fun dispatchKeyEvent(event: KeyEvent) = viewModel.input.dispatchKeyEvent(event) || super.dispatchKeyEvent(event)
|
||||||
override fun onGenericMotionEvent(event: MotionEvent) = viewModel.input.onGenericMotionEvent(event) || super.onGenericMotionEvent(event)
|
override fun onGenericMotionEvent(event: MotionEvent) = viewModel.input.onGenericMotionEvent(event) || super.onGenericMotionEvent(event)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,22 @@
|
||||||
|
|
||||||
package com.metallic.chiaki.stream
|
package com.metallic.chiaki.stream
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import android.app.Application
|
||||||
import androidx.lifecycle.MutableLiveData
|
import android.content.Context
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.*
|
||||||
import com.metallic.chiaki.common.LogManager
|
import com.metallic.chiaki.common.LogManager
|
||||||
import com.metallic.chiaki.session.StreamSession
|
import com.metallic.chiaki.session.StreamSession
|
||||||
import com.metallic.chiaki.common.Preferences
|
import com.metallic.chiaki.common.Preferences
|
||||||
import com.metallic.chiaki.lib.*
|
import com.metallic.chiaki.lib.*
|
||||||
import com.metallic.chiaki.session.StreamInput
|
import com.metallic.chiaki.session.StreamInput
|
||||||
|
|
||||||
class StreamViewModel(val preferences: Preferences, val logManager: LogManager, val connectInfo: ConnectInfo): ViewModel()
|
class StreamViewModel(val application: Application, val connectInfo: ConnectInfo): ViewModel()
|
||||||
{
|
{
|
||||||
|
val preferences = Preferences(application)
|
||||||
|
val logManager = LogManager(application)
|
||||||
|
|
||||||
private var _session: StreamSession? = null
|
private var _session: StreamSession? = null
|
||||||
val input = StreamInput(preferences)
|
val input = StreamInput(application, preferences)
|
||||||
val session = StreamSession(connectInfo, logManager, preferences.logVerbose, input)
|
val session = StreamSession(connectInfo, logManager, preferences.logVerbose, input)
|
||||||
|
|
||||||
private var _onScreenControlsEnabled = MutableLiveData<Boolean>(preferences.onScreenControlsEnabled)
|
private var _onScreenControlsEnabled = MutableLiveData<Boolean>(preferences.onScreenControlsEnabled)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue