Create a user-centric 3D space that is ideal for spatial UI content that follows a target.
FollowingSubspaceSample
@OptIn(ExperimentalFollowingSubspaceApi::class)
public fun FollowingSubspaceSample() {
val TAG = "AnchoredSubspaceSample"
@Composable
fun MainPanelContent() {
Text("Main panel")
}
@Composable
fun AppContent() {
MainPanelContent()
val session: Session? = LocalSession.current
if (session == null) return
session.configure(
config = session.config.copy(deviceTracking = DeviceTrackingMode.LAST_KNOWN)
)
FollowingSubspace(
target = FollowTarget.ArDevice(session),
behavior = FollowBehavior.Soft(durationMs = 500),
) {
SpatialPanel(SubspaceModifier.height(100.dp).width(200.dp)) {
Text(
modifier =
Modifier.fillMaxWidth()
.fillMaxHeight()
.background(Color.White)
.padding(all = 32.dp),
text = "This panel will follow AR device movement.",
)
}
}
val anchor =
remember(session) {
when (val anchorResult = Anchor.create(session, Pose.Identity)) {
is AnchorCreateSuccess -> AnchorEntity.create(session, anchorResult.anchor)
else -> {
Log.e(TAG, "Failed to create anchor: ${anchorResult::class.simpleName}")
null
}
}
}
if (anchor != null) {
FollowingSubspace(
target = FollowTarget.Anchor(anchorEntity = anchor),
behavior = FollowBehavior.Tight,
modifier = SubspaceModifier.rotate(pitch = -90f, yaw = 0f, roll = 0f),
) {
SpatialRow {
SpatialPanel { Text("Spatial panel") }
SpatialMainPanel()
}
}
DisposableEffect(anchor) { onDispose { anchor.dispose() } }
}
}
}