mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-14 18:57:07 -07:00
Send DPad Input to Session on Android
This commit is contained in:
parent
b007f93d16
commit
884333ed65
10 changed files with 152 additions and 56 deletions
|
@ -258,12 +258,12 @@ JNIEXPORT void JNICALL Java_com_metallic_chiaki_lib_ChiakiNative_sessionCreate(J
|
|||
|
||||
jclass controller_state_class = E->FindClass(env, "com/metallic/chiaki/lib/ControllerState");
|
||||
session->java_controller_state_buttons = E->GetFieldID(env, controller_state_class, "buttons", "I");
|
||||
session->java_controller_state_l2_state = E->GetFieldID(env, controller_state_class, "l2_state", "B");
|
||||
session->java_controller_state_r2_state = E->GetFieldID(env, controller_state_class, "r2_state", "B");
|
||||
session->java_controller_state_left_x = E->GetFieldID(env, controller_state_class, "left_x", "S");
|
||||
session->java_controller_state_left_y = E->GetFieldID(env, controller_state_class, "left_y", "S");
|
||||
session->java_controller_state_right_x = E->GetFieldID(env, controller_state_class, "right_x", "S");
|
||||
session->java_controller_state_right_y = E->GetFieldID(env, controller_state_class, "right_y", "S");
|
||||
session->java_controller_state_l2_state = E->GetFieldID(env, controller_state_class, "l2State", "B");
|
||||
session->java_controller_state_r2_state = E->GetFieldID(env, controller_state_class, "r2State", "B");
|
||||
session->java_controller_state_left_x = E->GetFieldID(env, controller_state_class, "leftX", "S");
|
||||
session->java_controller_state_left_y = E->GetFieldID(env, controller_state_class, "leftY", "S");
|
||||
session->java_controller_state_right_x = E->GetFieldID(env, controller_state_class, "rightX", "S");
|
||||
session->java_controller_state_right_y = E->GetFieldID(env, controller_state_class, "rightY", "S");
|
||||
|
||||
chiaki_session_set_event_cb(&session->session, android_chiaki_event_cb, session);
|
||||
chiaki_session_set_video_sample_cb(&session->session, android_chiaki_video_decoder_video_sample, &session->video_decoder);
|
||||
|
|
|
@ -32,6 +32,7 @@ data class StreamStateCreateError(val error: SessionCreateError): StreamState()
|
|||
data class StreamStateQuit(val reason: QuitReason, val reasonString: String?): StreamState()
|
||||
data class StreamStateLoginPinRequest(val pinIncorrect: Boolean): StreamState()
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
class StreamSession(val connectInfo: ConnectInfo)
|
||||
{
|
||||
var session: Session? = null
|
||||
|
@ -40,8 +41,8 @@ class StreamSession(val connectInfo: ConnectInfo)
|
|||
private val _state = MutableLiveData<StreamState>(StreamStateIdle)
|
||||
val state: LiveData<StreamState> get() = _state
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
private val controllerState = ControllerState()
|
||||
private var touchControllerState = ControllerState()
|
||||
|
||||
var surfaceTexture: SurfaceTexture? = null
|
||||
|
||||
|
@ -147,8 +148,18 @@ class StreamSession(val connectInfo: ConnectInfo)
|
|||
}
|
||||
}
|
||||
|
||||
session?.setControllerState(controllerState)
|
||||
|
||||
sendControllerState()
|
||||
return true
|
||||
}
|
||||
|
||||
fun updateTouchControllerState(controllerState: ControllerState)
|
||||
{
|
||||
touchControllerState = controllerState
|
||||
sendControllerState()
|
||||
}
|
||||
|
||||
private fun sendControllerState()
|
||||
{
|
||||
session?.setControllerState(controllerState or touchControllerState)
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package com.metallic.chiaki.lib
|
||||
|
||||
import android.os.Parcelable
|
||||
import android.util.Log
|
||||
import android.view.Surface
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import java.lang.Exception
|
||||
import kotlin.math.abs
|
||||
|
||||
@Parcelize
|
||||
data class ConnectVideoProfile(
|
||||
|
@ -49,14 +49,17 @@ class ErrorCode(val value: Int)
|
|||
var isSuccess = value == 0
|
||||
}
|
||||
|
||||
data class ControllerState @ExperimentalUnsignedTypes constructor(
|
||||
private fun maxAbs(a: Short, b: Short) = if(abs(a.toInt()) > abs(b.toInt())) a else b
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
data class ControllerState constructor(
|
||||
var buttons: UInt = 0U,
|
||||
var l2_state: UByte = 0U,
|
||||
var r2_state: UByte = 0U,
|
||||
var left_x: Short = 0,
|
||||
var left_y: Short = 0,
|
||||
var right_x: Short = 0,
|
||||
var right_y: Short = 0
|
||||
var l2State: UByte = 0U,
|
||||
var r2State: UByte = 0U,
|
||||
var leftX: Short = 0,
|
||||
var leftY: Short = 0,
|
||||
var rightX: Short = 0,
|
||||
var rightY: Short = 0
|
||||
){
|
||||
companion object
|
||||
{
|
||||
|
@ -77,6 +80,16 @@ data class ControllerState @ExperimentalUnsignedTypes constructor(
|
|||
val BUTTON_TOUCHPAD = (1 shl 14).toUInt()
|
||||
val BUTTON_PS = (1 shl 15).toUInt()
|
||||
}
|
||||
|
||||
infix fun or(o: ControllerState) = ControllerState(
|
||||
buttons = buttons or o.buttons,
|
||||
l2State = maxOf(l2State, o.l2State),
|
||||
r2State = maxOf(r2State, o.r2State),
|
||||
leftX = maxAbs(leftX, o.leftX),
|
||||
leftY = maxAbs(leftY, o.leftY),
|
||||
rightX = maxAbs(rightX, o.rightX),
|
||||
rightY = maxAbs(rightY, o.rightY)
|
||||
)
|
||||
}
|
||||
|
||||
class QuitReason(val value: Int)
|
||||
|
|
|
@ -19,15 +19,17 @@ package com.metallic.chiaki.stream
|
|||
|
||||
import android.graphics.Matrix
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.*
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.lib.ConnectInfo
|
||||
import com.metallic.chiaki.touchcontrols.TouchControlsFragment
|
||||
import kotlinx.android.synthetic.main.activity_stream.*
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
class StreamActivity : AppCompatActivity()
|
||||
{
|
||||
companion object
|
||||
|
@ -40,7 +42,6 @@ class StreamActivity : AppCompatActivity()
|
|||
override fun onCreate(savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_stream)
|
||||
|
||||
viewModel = ViewModelProviders.of(this)[StreamViewModel::class.java]
|
||||
if(!viewModel.isInitialized)
|
||||
|
@ -54,6 +55,8 @@ class StreamActivity : AppCompatActivity()
|
|||
viewModel.init(connectInfo)
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_stream)
|
||||
|
||||
viewModel.session.attachToTextureView(textureView)
|
||||
|
||||
viewModel.session.state.observe(this, Observer {
|
||||
|
@ -65,6 +68,13 @@ class StreamActivity : AppCompatActivity()
|
|||
}
|
||||
}
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
override fun onAttachFragment(fragment: Fragment)
|
||||
{
|
||||
super.onAttachFragment(fragment)
|
||||
(fragment as? TouchControlsFragment)?.controllerStateCallback = viewModel.session::updateTouchControllerState
|
||||
}
|
||||
|
||||
override fun onResume()
|
||||
{
|
||||
super.onResume()
|
||||
|
|
|
@ -37,6 +37,8 @@ class DPadView @JvmOverloads constructor(
|
|||
var state: Direction? = null
|
||||
private set
|
||||
|
||||
var stateChangeCallback: ((Direction?) -> Unit)? = null
|
||||
|
||||
/**
|
||||
* Radius (as a fraction of the entire DPad Radius)
|
||||
* to be used as a deadzone in the center on move events
|
||||
|
@ -69,7 +71,7 @@ class DPadView @JvmOverloads constructor(
|
|||
drawable = dpadIdleDrawable
|
||||
|
||||
drawable?.setBounds(0, 0, width, height)
|
||||
drawable?.alpha = 127
|
||||
//drawable?.alpha = 127
|
||||
drawable?.draw(canvas)
|
||||
}
|
||||
|
||||
|
@ -106,7 +108,7 @@ class DPadView @JvmOverloads constructor(
|
|||
{
|
||||
state = newState
|
||||
invalidate()
|
||||
// TODO: callback
|
||||
stateChangeCallback?.let { it(state) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* This file is part of Chiaki.
|
||||
*
|
||||
* Chiaki is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Chiaki is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.metallic.chiaki.touchcontrols
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.metallic.chiaki.R
|
||||
import com.metallic.chiaki.lib.ControllerState
|
||||
import kotlinx.android.synthetic.main.fragment_controls.*
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
class TouchControlsFragment : Fragment()
|
||||
{
|
||||
var controllerState = ControllerState()
|
||||
private set(value)
|
||||
{
|
||||
val diff = field != value
|
||||
field = value
|
||||
if(diff)
|
||||
controllerStateCallback?.let { it(value) }
|
||||
}
|
||||
|
||||
var controllerStateCallback: ((ControllerState) -> Unit)? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
|
||||
= inflater.inflate(R.layout.fragment_controls, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
dpadView.stateChangeCallback = this::dpadStateChanged
|
||||
}
|
||||
|
||||
private fun dpadStateChanged(direction: DPadView.Direction?)
|
||||
{
|
||||
controllerState = controllerState.copy().apply {
|
||||
buttons = ((buttons
|
||||
and ControllerState.BUTTON_DPAD_LEFT.inv()
|
||||
and ControllerState.BUTTON_DPAD_RIGHT.inv()
|
||||
and ControllerState.BUTTON_DPAD_UP.inv()
|
||||
and ControllerState.BUTTON_DPAD_DOWN.inv())
|
||||
or when(direction)
|
||||
{
|
||||
DPadView.Direction.UP -> ControllerState.BUTTON_DPAD_UP
|
||||
DPadView.Direction.DOWN -> ControllerState.BUTTON_DPAD_DOWN
|
||||
DPadView.Direction.LEFT -> ControllerState.BUTTON_DPAD_LEFT
|
||||
DPadView.Direction.RIGHT -> ControllerState.BUTTON_DPAD_RIGHT
|
||||
null -> 0U
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,20 +51,4 @@
|
|||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/morningEditText" />
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.DPadView
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.DPadView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -17,24 +17,10 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ControlsBackgroundView
|
||||
<fragment
|
||||
android:id="@+id/controlsFragment"
|
||||
android:name="com.metallic.chiaki.touchcontrols.TouchControlsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.DPadView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_marginLeft="32dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.DPadView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_marginRight="32dp"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
20
android/app/src/main/res/layout/fragment_controls.xml
Normal file
20
android/app/src/main/res/layout/fragment_controls.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.ControlsBackgroundView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.metallic.chiaki.touchcontrols.DPadView
|
||||
android:id="@+id/dpadView"
|
||||
android:layout_width="130dp"
|
||||
android:layout_height="130dp"
|
||||
android:layout_marginLeft="32dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -7,6 +7,6 @@
|
|||
<color name="stream_text">@android:color/white</color>
|
||||
<color name="stream_background">@android:color/black</color>
|
||||
|
||||
<color name="control_primary">@android:color/white</color>
|
||||
<color name="control_pressed">#8888ff</color>
|
||||
<color name="control_primary">#44ffffff</color>
|
||||
<color name="control_pressed">#88ffffff</color>
|
||||
</resources>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue