This repository has been archived by the owner on Jul 7, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
ArChessBoardScreen.kt
87 lines (73 loc) · 2.64 KB
/
ArChessBoardScreen.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package ch.epfl.sdp.mobile.ui.game.ar
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.viewinterop.AndroidView
import ch.epfl.sdp.mobile.state.LocalLocalizedStrings
import ch.epfl.sdp.mobile.ui.game.ChessBoardState
import com.google.ar.core.Anchor
import com.gorisse.thomas.lifecycle.lifecycleScope
import io.github.sceneview.ar.ArSceneView
private const val BoardScale = 0.2f
/**
* Composable used to display a AR chess board
*
* @param state The state of the game, it's used to track the modification on the game
* @param modifier modifier the [Modifier] for this composable.
*/
@Composable
fun <Piece : ChessBoardState.Piece> ArChessBoardScreen(
state: ChessBoardState<Piece>,
modifier: Modifier = Modifier
) {
val view = LocalView.current
val strings = LocalLocalizedStrings.current
var chessScene by remember { mutableStateOf<ChessScene<Piece>?>(null) }
// Keep the screen on only for this composable
DisposableEffect(view) {
view.keepScreenOn = true
onDispose { view.keepScreenOn = false }
}
AndroidView(
factory = { context ->
// Create the view
val arSceneView = ArSceneView(context)
chessScene =
ChessScene(context, view.lifecycleScope, state.pieces).apply {
// Scale the board
this.scale(BoardScale)
// Place the chess board on the tapped position.
arSceneView.onTouchAr =
{ hitResult, _ ->
anchorOrMoveBoard(arSceneView, chessScene, hitResult.createAnchor())
}
}
arSceneView
},
modifier = modifier.semantics { this.contentDescription = strings.arContentDescription },
update = { chessScene?.update(state.pieces) })
}
/**
* If not already in the scene, the board will be added. Update the board anchor with the given one
* and change the displayed position
*
* @param arSceneView The view where the scene will be displayed
* @param chessScene The scene that contains the boards node
* @param anchor The (new) board's anchor position
*/
private fun <Piece : ChessBoardState.Piece> anchorOrMoveBoard(
arSceneView: ArSceneView,
chessScene: ChessScene<Piece>?,
anchor: Anchor
) {
val currentChessScene = chessScene ?: return
currentChessScene.let {
// Add only one instance of the node
if (!arSceneView.children.contains(it.boardNode)) {
arSceneView.addChild(it.boardNode)
}
it.boardNode.anchor = anchor
}
}