Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ android {

defaultConfig {
applicationId = "com.example.helloandroidxr"
minSdk = 23
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0"
Expand Down Expand Up @@ -63,7 +63,6 @@ android {
dependencies {
val composeBom = platform(libs.androidx.compose.bom)
implementation(composeBom)
implementation(libs.impress)
implementation(libs.androidx.arcore)
implementation(libs.androidx.scenecore)
implementation(libs.androidx.compose)
Expand Down
5 changes: 2 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<!-- This is necessary due to a known issue causing a higher minSDK than intended-->
<uses-sdk tools:overrideLibrary="androidx.xr.scenecore, androidx.xr.compose"/>

<uses-feature android:name="android.software.xr.api.spatial" android:required="false" />

<application
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,69 +19,69 @@ package com.example.helloandroidxr.environment
import android.util.Log
import androidx.concurrent.futures.await
import androidx.xr.scenecore.GltfModel
import androidx.xr.scenecore.Session
import androidx.xr.runtime.Session
import androidx.xr.scenecore.SpatialEnvironment
import androidx.xr.scenecore.scene
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

class EnvironmentController(private val xrSession: Session, private val coroutineScope: CoroutineScope) {

private val assetCache: HashMap<String, Any> = HashMap()
private var activeEnvironmentModelName: String? = null

fun requestHomeSpaceMode() = xrSession.requestHomeSpaceMode()
fun requestHomeSpaceMode() = xrSession.scene.spatialEnvironment.requestHomeSpaceMode()

fun requestFullSpaceMode() = xrSession.requestFullSpaceMode()
fun requestFullSpaceMode() = xrSession.scene.spatialEnvironment.requestFullSpaceMode()

fun requestPassthrough() = xrSession.spatialEnvironment.setPassthroughOpacityPreference(1f)
fun requestPassthrough() = xrSession.scene.spatialEnvironment.setPassthroughOpacityPreference(1f)

/**
* Request the system load a custom Environment
*/
fun requestCustomEnvironment(environmentModelName: String) {
coroutineScope.launch {
try {

if (activeEnvironmentModelName == null ||
activeEnvironmentModelName != environmentModelName){
activeEnvironmentModelName != environmentModelName
) {

val environmentModel = assetCache[environmentModelName] as GltfModel

SpatialEnvironment.SpatialEnvironmentPreference(
skybox = null,
geometry = environmentModel).let {
xrSession.spatialEnvironment.setSpatialEnvironmentPreference(
geometry = environmentModel
).let {
xrSession.scene.spatialEnvironment.setSpatialEnvironmentPreference(
it
)
}

activeEnvironmentModelName = environmentModelName
}
xrSession.spatialEnvironment.setPassthroughOpacityPreference(0f)
xrSession.scene.spatialEnvironment.setPassthroughOpacityPreference(0f)

} catch (e: Exception){
} catch (e: Exception) {
Log.e(
"Hello Android XR",
"Failed to update Environment Preference for $environmentModelName: $e")
"Failed to update Environment Preference for $environmentModelName: $e"
)
}

}
}

fun loadModelAsset(modelName: String) {
coroutineScope.launch {
//load the asset if it hasn't been loaded previously
if (!assetCache.containsKey(modelName)){
if (!assetCache.containsKey(modelName)) {
try {
val gltfModel =
xrSession.createGltfResourceAsync(modelName).await()

GltfModel.create(xrSession, modelName).await()
assetCache[modelName] = gltfModel

}catch (e: Exception) {
} catch (e: Exception) {
Log.e(
"Hello Android XR",
"Failed to load model for $modelName: $e")
"Failed to load model for $modelName: $e"
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.SpatialRow
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.alpha
import androidx.xr.compose.subspace.layout.fillMaxHeight
import androidx.xr.compose.subspace.layout.fillMaxSize
import androidx.xr.compose.subspace.layout.fillMaxWidth
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.padding
import androidx.xr.compose.subspace.layout.size
Expand Down Expand Up @@ -107,24 +108,23 @@ private fun SpatialLayout(
}
}
Subspace {
SpatialRow(modifier = SubspaceModifier.height(816.dp)) {
SpatialColumn {
SpatialRow(modifier = SubspaceModifier.height(816.dp).fillMaxWidth()) {
SpatialColumn(modifier = SubspaceModifier.width(400.dp)) {
SpatialPanel(
SubspaceModifier.alpha(animatedAlpha.value).size(400.dp).padding(bottom = 16.dp)
) {
firstSupportingContent()
}
SpatialPanel(
SubspaceModifier.alpha(animatedAlpha.value).width(400.dp).weight(1f)
SubspaceModifier.alpha(animatedAlpha.value).weight(1f)
) {
secondSupportingContent()
}
}
SpatialPanel(
modifier = SubspaceModifier
.alpha(animatedAlpha.value)
.width(1488.dp)
.fillMaxHeight()
.fillMaxSize()
.padding(left = 16.dp)
) {
Column {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
Expand All @@ -42,7 +43,6 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import androidx.xr.compose.platform.LocalSession
import androidx.xr.compose.platform.LocalSpatialCapabilities
import androidx.xr.scenecore.Session
import com.example.helloandroidxr.R
import com.example.helloandroidxr.environment.EnvironmentController
import com.example.helloandroidxr.ui.theme.HelloAndroidXRTheme
Expand All @@ -54,10 +54,10 @@ import com.example.helloandroidxr.ui.theme.HelloAndroidXRTheme
fun EnvironmentControls(modifier: Modifier = Modifier) {
// If we aren't able to access the session, these buttons wouldn't work and shouldn't be shown
val activity = LocalActivity.current
if (LocalSession.current != null && activity is ComponentActivity) {
val session = LocalSession.current
if (session != null && activity is ComponentActivity) {
val uiIsSpatialized = LocalSpatialCapabilities.current.isSpatialUiEnabled
val environmentController = remember(activity) {
val session = Session.create(activity)
EnvironmentController(session, activity.lifecycleScope)
}
//load the model early so it's in memory for when we need it
Expand Down Expand Up @@ -97,6 +97,7 @@ private fun SetVirtualEnvironmentButton(
modifier = modifier
.padding(16.dp)
.background(MaterialTheme.colorScheme.onSecondary, CircleShape)
.size(56.dp)
) {
Icon(
painter = painterResource(R.drawable.environment_24px),
Expand All @@ -114,6 +115,7 @@ private fun SetPassthroughButton(
modifier = modifier
.padding(top = 16.dp, bottom = 16.dp, end = 16.dp)
.background(MaterialTheme.colorScheme.onSecondary, CircleShape)
.size(56.dp)
) {
Icon(
painter = painterResource(R.drawable.passthrough_24px),
Expand All @@ -129,6 +131,7 @@ private fun RequestHomeSpaceButton(onclick: () -> Unit) {
modifier = Modifier
.padding(16.dp)
.background(MaterialTheme.colorScheme.onSecondary, CircleShape)
.size(56.dp)
) {
Icon(
painter = painterResource(id = R.drawable.ic_request_home_space),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ package com.example.helloandroidxr.ui.components

import android.content.Context
import android.widget.Toast
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardActions
Expand All @@ -47,7 +46,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.xr.compose.platform.LocalSpatialCapabilities
import com.example.helloandroidxr.R
import com.example.helloandroidxr.ui.theme.HelloAndroidXRTheme

Expand All @@ -56,30 +54,17 @@ import com.example.helloandroidxr.ui.theme.HelloAndroidXRTheme
*/
@Composable
fun SearchBar(modifier: Modifier = Modifier) {
val uiIsSpatialized = LocalSpatialCapabilities.current.isSpatialUiEnabled
val context = LocalContext.current

Surface(modifier = modifier.clip(CircleShape)) {
if (uiIsSpatialized) {
Spacer(Modifier.width(208.dp))
}
SearchTextBox(
onSearch = { query ->
showNotImplementedToast(
query = query,
context = context
)
},
modifier = if (uiIsSpatialized) {
Modifier.padding(
horizontal = 208.dp,
vertical = 16.dp,
)
} else Modifier
modifier = Modifier.padding(16.dp),
)
if (uiIsSpatialized) {
Spacer(Modifier.width(208.dp))
}
}
}

Expand All @@ -95,7 +80,11 @@ fun SearchTextBox(
TextField(
value = text,
onValueChange = { text = it },
placeholder = { Text(stringResource(R.string.search_product_name)) },
placeholder = {
Text(
stringResource(R.string.search_product_name),
)
},
leadingIcon = { Icon(Icons.Filled.Search, null) },
colors = TextFieldDefaults.colors(
focusedIndicatorColor = Color.Transparent,
Expand All @@ -112,7 +101,8 @@ fun SearchTextBox(
focusManager.clearFocus(force = true)
}),
modifier = modifier
.size(640.dp, 64.dp)
.width(640.dp)
.height(56.dp)
.clip(CircleShape)
)
}
Expand Down
8 changes: 3 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
[versions]
androidx-runtime = "1.8.0-alpha06"
agp = "8.6.1"
arcore = "1.0.0-alpha01"
compose = "1.0.0-alpha01"
impress = "0.0.1"
arcore = "1.0.0-alpha04"
compose = "1.0.0-alpha04"
scenecore = "1.0.0-alpha04"
kotlinxCoroutinesGuava = "1.9.0"
scenecore = "1.0.0-alpha01"
kotlin = "2.0.21"
concurrentFuturesKtx = "1.2.0"
activityCompose = "1.10.0-beta01"
Expand All @@ -18,7 +17,6 @@ adaptiveAndroid = "1.0.0"
androidx-arcore = { module = "androidx.xr.arcore:arcore", version.ref = "arcore" }
androidx-compose = { module = "androidx.xr.compose:compose", version.ref = "compose" }
androidx-scenecore = { module = "androidx.xr.scenecore:scenecore", version.ref = "scenecore" }
impress = { module = "com.google.ar:impress", version.ref = "impress" }
kotlinx-coroutines-guava = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-guava", version.ref = "kotlinxCoroutinesGuava" }
androidx-compose-material3 = { module = "androidx.compose.material3:material3" }
material = { module = "com.google.android.material:material", version.ref = "material" }
Expand Down