diff --git a/android/app/src/main/cpp/chiaki-jni.c b/android/app/src/main/cpp/chiaki-jni.c index 9e1acc5..6c29f17 100644 --- a/android/app/src/main/cpp/chiaki-jni.c +++ b/android/app/src/main/cpp/chiaki-jni.c @@ -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); diff --git a/android/app/src/main/java/com/metallic/chiaki/StreamSession.kt b/android/app/src/main/java/com/metallic/chiaki/StreamSession.kt index b3af30f..f5db53f 100644 --- a/android/app/src/main/java/com/metallic/chiaki/StreamSession.kt +++ b/android/app/src/main/java/com/metallic/chiaki/StreamSession.kt @@ -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(StreamStateIdle) val state: LiveData 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) + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/metallic/chiaki/lib/Chiaki.kt b/android/app/src/main/java/com/metallic/chiaki/lib/Chiaki.kt index 1c74de3..4084e5b 100644 --- a/android/app/src/main/java/com/metallic/chiaki/lib/Chiaki.kt +++ b/android/app/src/main/java/com/metallic/chiaki/lib/Chiaki.kt @@ -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) diff --git a/android/app/src/main/java/com/metallic/chiaki/stream/StreamActivity.kt b/android/app/src/main/java/com/metallic/chiaki/stream/StreamActivity.kt index 5851f4d..1ccf44e 100644 --- a/android/app/src/main/java/com/metallic/chiaki/stream/StreamActivity.kt +++ b/android/app/src/main/java/com/metallic/chiaki/stream/StreamActivity.kt @@ -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() diff --git a/android/app/src/main/java/com/metallic/chiaki/touchcontrols/DPadView.kt b/android/app/src/main/java/com/metallic/chiaki/touchcontrols/DPadView.kt index 2155381..a997b79 100644 --- a/android/app/src/main/java/com/metallic/chiaki/touchcontrols/DPadView.kt +++ b/android/app/src/main/java/com/metallic/chiaki/touchcontrols/DPadView.kt @@ -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) } } } diff --git a/android/app/src/main/java/com/metallic/chiaki/touchcontrols/TouchControlsFragment.kt b/android/app/src/main/java/com/metallic/chiaki/touchcontrols/TouchControlsFragment.kt new file mode 100644 index 0000000..d1c4948 --- /dev/null +++ b/android/app/src/main/java/com/metallic/chiaki/touchcontrols/TouchControlsFragment.kt @@ -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 . + */ + +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 + }) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index 69d2f21..7e350d7 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -51,20 +51,4 @@ app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/morningEditText" /> - - - - \ No newline at end of file diff --git a/android/app/src/main/res/layout/activity_stream.xml b/android/app/src/main/res/layout/activity_stream.xml index 7a25c1b..aec07ee 100644 --- a/android/app/src/main/res/layout/activity_stream.xml +++ b/android/app/src/main/res/layout/activity_stream.xml @@ -17,24 +17,10 @@ android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent"/> - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/layout/fragment_controls.xml b/android/app/src/main/res/layout/fragment_controls.xml new file mode 100644 index 0000000..1d04353 --- /dev/null +++ b/android/app/src/main/res/layout/fragment_controls.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 0db3df8..470f28e 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -7,6 +7,6 @@ @android:color/white @android:color/black - @android:color/white - #8888ff + #44ffffff + #88ffffff