Angle update
This commit is contained in:
@@ -33,16 +33,12 @@ import java.util.concurrent.Executors
|
||||
*/
|
||||
class BowlingCameraActivity : AppCompatActivity(), CameraXController.Callback {
|
||||
|
||||
/** Which button a recording in progress was started from. */
|
||||
private enum class RecordMode { VIDEO, POSE }
|
||||
|
||||
private lateinit var binding: ActivityBowlingCameraBinding
|
||||
private val viewModel: CameraViewModel by viewModels()
|
||||
|
||||
private lateinit var cameraExecutor: ExecutorService
|
||||
private lateinit var cameraXController: CameraXController
|
||||
private var lensFacing = CameraSelector.LENS_FACING_BACK
|
||||
private var activeRecordMode: RecordMode? = null
|
||||
|
||||
private val permissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { _ ->
|
||||
@@ -67,8 +63,8 @@ class BowlingCameraActivity : AppCompatActivity(), CameraXController.Callback {
|
||||
binding.btnGrantPermissions.setOnClickListener {
|
||||
permissionLauncher.launch(CameraPermissions.REQUIRED)
|
||||
}
|
||||
binding.btnRecordVideo.setOnClickListener { onRecordClicked(RecordMode.VIDEO) }
|
||||
binding.btnRecordWithPose.setOnClickListener { onRecordClicked(RecordMode.POSE) }
|
||||
binding.btnRecord.setOnClickListener { onRecordClicked() }
|
||||
binding.switchPose.setOnCheckedChangeListener { _, isChecked -> viewModel.onPoseToggled(isChecked) }
|
||||
binding.btnSwitchCamera.setOnClickListener { onSwitchCameraClicked() }
|
||||
binding.btnBack.setOnClickListener { finish() }
|
||||
|
||||
@@ -93,17 +89,14 @@ class BowlingCameraActivity : AppCompatActivity(), CameraXController.Callback {
|
||||
)
|
||||
}
|
||||
|
||||
private fun onRecordClicked(mode: RecordMode) {
|
||||
private fun onRecordClicked() {
|
||||
if (cameraXController.isRecording) {
|
||||
cameraXController.stopRecording()
|
||||
} else {
|
||||
activeRecordMode = mode
|
||||
val withPose = mode == RecordMode.POSE
|
||||
cameraXController.setPoseDetectionEnabled(withPose)
|
||||
if (!withPose) {
|
||||
// Clear any skeleton left over from a previous "with pose" recording.
|
||||
binding.poseOverlay.clear()
|
||||
}
|
||||
// Pose mode for this recording is whatever switch_pose is
|
||||
// already set to -- see the poseEnabled collector in
|
||||
// observeViewModel(), which keeps cameraXController's live pose
|
||||
// state in sync with the toggle as it's flipped.
|
||||
viewModel.onRecordingStarting()
|
||||
cameraXController.startRecording()
|
||||
}
|
||||
@@ -133,6 +126,19 @@ class BowlingCameraActivity : AppCompatActivity(), CameraXController.Callback {
|
||||
launch {
|
||||
viewModel.recordingState.collect { state -> renderRecordingState(state) }
|
||||
}
|
||||
launch {
|
||||
viewModel.poseEnabled.collect { enabled ->
|
||||
// Also drives the switch's checked state (idempotent
|
||||
// if the user just flipped it themselves), so it
|
||||
// reflects viewModel state after an Activity
|
||||
// recreation, e.g. on rotation.
|
||||
if (binding.switchPose.isChecked != enabled) {
|
||||
binding.switchPose.isChecked = enabled
|
||||
}
|
||||
cameraXController.setPoseDetectionEnabled(enabled)
|
||||
if (!enabled) binding.poseOverlay.clear()
|
||||
}
|
||||
}
|
||||
launch {
|
||||
viewModel.errorEvents.collect { message ->
|
||||
Toast.makeText(this@BowlingCameraActivity, message, Toast.LENGTH_LONG).show()
|
||||
@@ -157,28 +163,23 @@ class BowlingCameraActivity : AppCompatActivity(), CameraXController.Callback {
|
||||
}
|
||||
when (state) {
|
||||
is CameraViewModel.RecordingState.Idle -> {
|
||||
activeRecordMode = null
|
||||
binding.layoutRecordingIndicator.visibility = View.GONE
|
||||
binding.btnRecordVideo.isEnabled = true
|
||||
binding.btnRecordVideo.setText(R.string.record_video)
|
||||
binding.btnRecordWithPose.isEnabled = true
|
||||
binding.btnRecordWithPose.setText(R.string.record_with_pose)
|
||||
binding.btnRecord.isEnabled = true
|
||||
binding.btnRecord.setText(R.string.record)
|
||||
// Pose mode can only be changed between recordings, not
|
||||
// mid-flight -- see setPoseDetectionEnabled()'s doc comment.
|
||||
binding.switchPose.isEnabled = true
|
||||
}
|
||||
is CameraViewModel.RecordingState.Starting -> {
|
||||
// Neither button switches mode mid-flight, and neither can
|
||||
// stop a recording that hasn't started yet.
|
||||
binding.btnRecordVideo.isEnabled = false
|
||||
binding.btnRecordWithPose.isEnabled = false
|
||||
// Can't stop a recording that hasn't started yet, and pose
|
||||
// mode for it is already locked in.
|
||||
binding.btnRecord.isEnabled = false
|
||||
binding.switchPose.isEnabled = false
|
||||
}
|
||||
is CameraViewModel.RecordingState.Recording -> {
|
||||
// Only the button that started this recording stays enabled
|
||||
// (now as the stop trigger); the other is disabled rather
|
||||
// than switching mode mid-recording.
|
||||
val videoActive = activeRecordMode == RecordMode.VIDEO
|
||||
binding.btnRecordVideo.isEnabled = videoActive
|
||||
binding.btnRecordVideo.setText(if (videoActive) R.string.stop_recording else R.string.record_video)
|
||||
binding.btnRecordWithPose.isEnabled = !videoActive
|
||||
binding.btnRecordWithPose.setText(if (!videoActive) R.string.stop_recording else R.string.record_with_pose)
|
||||
binding.btnRecord.isEnabled = true
|
||||
binding.btnRecord.setText(R.string.stop_recording)
|
||||
binding.switchPose.isEnabled = false
|
||||
binding.layoutRecordingIndicator.visibility = View.VISIBLE
|
||||
val minutes = state.elapsedSeconds / 60
|
||||
val seconds = state.elapsedSeconds % 60
|
||||
@@ -232,6 +233,7 @@ class BowlingCameraActivity : AppCompatActivity(), CameraXController.Callback {
|
||||
// (see PoseAnalyzer) deliver on the main thread by default even
|
||||
// though inference itself runs on the background camera executor.
|
||||
binding.poseOverlay.update(result)
|
||||
viewModel.onPoseAnglesUpdated(result.angles)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
||||
Reference in New Issue
Block a user