diff --git a/app/src/main/assets/white.png b/app/src/main/assets/white.png new file mode 100644 index 0000000..dabb241 Binary files /dev/null and b/app/src/main/assets/white.png differ diff --git a/app/src/main/java/com/example/helloandroidxr/ui/components/BugdroidModel.kt b/app/src/main/java/com/example/helloandroidxr/ui/components/BugdroidModel.kt index b4af8de..7e7725d 100644 --- a/app/src/main/java/com/example/helloandroidxr/ui/components/BugdroidModel.kt +++ b/app/src/main/java/com/example/helloandroidxr/ui/components/BugdroidModel.kt @@ -29,18 +29,20 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.xr.compose.platform.LocalSession -import androidx.xr.compose.spatial.Subspace +import androidx.xr.compose.spatial.PlanarEmbeddedSubspace import androidx.xr.compose.subspace.SceneCoreEntity import androidx.xr.compose.subspace.SceneCoreEntitySizeAdapter import androidx.xr.compose.subspace.layout.SubspaceModifier import androidx.xr.compose.subspace.layout.scale import androidx.xr.compose.unit.Meter import androidx.xr.runtime.math.Vector4 +import androidx.xr.scenecore.AlphaMode import androidx.xr.scenecore.GltfModelEntity import androidx.xr.scenecore.KhronosPbrMaterial -import androidx.xr.scenecore.KhronosPbrMaterialSpec +import androidx.xr.scenecore.Texture import com.example.helloandroidxr.bugdroid.BugdroidController import com.example.helloandroidxr.viewmodel.ModelTransform +import kotlin.io.path.Path // Bugdroid glb height in meters private const val bugdroidHeight = 2.08f @@ -67,41 +69,52 @@ fun BugdroidModel( } val gltfModel = bugdroidController.gltfModel gltfModel?.let { model -> - Subspace { + PlanarEmbeddedSubspace { val density = LocalDensity.current var scaleFromLayout by remember { mutableFloatStateOf(1f) } var pbrMaterial by remember { mutableStateOf(null) } LaunchedEffect(xrSession) { try { - val spec = - KhronosPbrMaterialSpec.create( - lightingModel = KhronosPbrMaterialSpec.LightingModel.LIT, - blendMode = KhronosPbrMaterialSpec.BlendMode.OPAQUE, - doubleSidedMode = KhronosPbrMaterialSpec.DoubleSidedMode.SINGLE_SIDED, + pbrMaterial = KhronosPbrMaterial.create( + session = xrSession, + alphaMode = AlphaMode.OPAQUE + ) + val texture = Texture.create( + session = xrSession, + path = Path("white.png") // Used as a base texture for material properties. + ) + pbrMaterial?.setOcclusionTexture( + texture = texture, + strength = modelTransform.materialProperties.ambientOcclusion + ) + pbrMaterial?.setBaseColorFactor( + Vector4( + x = modelTransform.materialColor.x, + y = modelTransform.materialColor.y, + z = modelTransform.materialColor.z, + w = modelTransform.materialColor.w ) - pbrMaterial = KhronosPbrMaterial.create(xrSession, spec) + ) } catch (e: Exception) { Log.e(TAG, "Error creating material", e) } } LaunchedEffect( - pbrMaterial, modelTransform.materialColor.x, modelTransform.materialColor.y, modelTransform.materialColor.z, modelTransform.materialColor.w, - modelTransform.materialProperties.ambientOcclusion, modelTransform.materialProperties.metallic, modelTransform.materialProperties.roughness, ) { - pbrMaterial?.setBaseColorFactors( + pbrMaterial?.setBaseColorFactor( Vector4( x = modelTransform.materialColor.x, y = modelTransform.materialColor.y, z = modelTransform.materialColor.z, + w = modelTransform.materialColor.w ) ) - pbrMaterial?.setAmbientOcclusionFactor(modelTransform.materialProperties.ambientOcclusion) pbrMaterial?.setMetallicFactor(modelTransform.materialProperties.metallic) pbrMaterial?.setRoughnessFactor(modelTransform.materialProperties.roughness) } diff --git a/app/src/main/java/com/example/helloandroidxr/ui/components/BugdroidSliderControls.kt b/app/src/main/java/com/example/helloandroidxr/ui/components/BugdroidSliderControls.kt index 27cd041..e6ce42b 100644 --- a/app/src/main/java/com/example/helloandroidxr/ui/components/BugdroidSliderControls.kt +++ b/app/src/main/java/com/example/helloandroidxr/ui/components/BugdroidSliderControls.kt @@ -313,21 +313,6 @@ fun MaterialPropertySliders( Text(text = stringResource(R.string.change_material_factors)) Spacer(modifier = Modifier.padding(10.dp)) - Text(text = stringResource(R.string.ambient)) - Slider( - value = materialProperties.ambientOcclusion, - onValueChange = { newAmbientOcclusion -> - onMaterialPropertiesChange( - materialProperties.copy( - ambientOcclusion = newAmbientOcclusion - ) - ) - }, - valueRange = MIN_MATERIAL_PROP_VALUE..MAX_MATERIAL_PROP_VALUE, - modifier = Modifier.padding() - ) - Text(text = "%.2f".format(materialProperties.ambientOcclusion)) - Text(text = stringResource(R.string.metallic)) Slider( value = materialProperties.metallic, diff --git a/app/src/main/java/com/example/helloandroidxr/ui/components/SearchBar.kt b/app/src/main/java/com/example/helloandroidxr/ui/components/SearchBar.kt index 9135c36..6049bca 100644 --- a/app/src/main/java/com/example/helloandroidxr/ui/components/SearchBar.kt +++ b/app/src/main/java/com/example/helloandroidxr/ui/components/SearchBar.kt @@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Search import androidx.compose.material3.Icon import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -42,6 +40,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview @@ -85,7 +84,14 @@ fun SearchTextBox( stringResource(R.string.search_product_name), ) }, - leadingIcon = { Icon(Icons.Filled.Search, null) }, + leadingIcon = { + // This icon is decorative. The TextField's placeholder text is sufficient for screen + // readers. + Icon( + painter = painterResource(R.drawable.search_24px), + contentDescription = null, + ) + }, colors = TextFieldDefaults.colors( focusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent diff --git a/app/src/main/java/com/example/helloandroidxr/viewmodel/BugdroidViewModel.kt b/app/src/main/java/com/example/helloandroidxr/viewmodel/BugdroidViewModel.kt index cfffa1e..9f7f486 100644 --- a/app/src/main/java/com/example/helloandroidxr/viewmodel/BugdroidViewModel.kt +++ b/app/src/main/java/com/example/helloandroidxr/viewmodel/BugdroidViewModel.kt @@ -34,7 +34,7 @@ private const val DEFAULT_X_MATERIAL_COLOR = 0.0f private const val DEFAULT_Y_MATERIAL_COLOR = 1.0f private const val DEFAULT_Z_MATERIAL_COLOR = 0.0f private const val DEFAULT_W_MATERIAL_COLOR = 0.0f -private const val DEFAULT_AMBIENT_OCCLUSION = 0.5f +private const val DEFAULT_AMBIENT_OCCLUSION = 1.0f private const val DEFAULT_METALLIC = 0.0f private const val DEFAULT_ROUGHNESS = 0.0f const val MIN_SCALE_VALUE = 0.1f @@ -176,10 +176,22 @@ class BugdroidViewModel : ViewModel() { currentState.copy( modelTransform = currentState.modelTransform.copy( materialColor = currentState.modelTransform.materialColor.copy( - x = newMaterialColor.x.coerceIn(MIN_MATERIAL_COLOR_VALUE, MAX_MATERIAL_COLOR_VALUE), - y = newMaterialColor.y.coerceIn(MIN_MATERIAL_COLOR_VALUE, MAX_MATERIAL_COLOR_VALUE), - z = newMaterialColor.z.coerceIn(MIN_MATERIAL_COLOR_VALUE, MAX_MATERIAL_COLOR_VALUE), - w = newMaterialColor.w.coerceIn(MIN_MATERIAL_COLOR_VALUE, MAX_MATERIAL_COLOR_VALUE), + x = newMaterialColor.x.coerceIn( + MIN_MATERIAL_COLOR_VALUE, + MAX_MATERIAL_COLOR_VALUE + ), + y = newMaterialColor.y.coerceIn( + MIN_MATERIAL_COLOR_VALUE, + MAX_MATERIAL_COLOR_VALUE + ), + z = newMaterialColor.z.coerceIn( + MIN_MATERIAL_COLOR_VALUE, + MAX_MATERIAL_COLOR_VALUE + ), + w = newMaterialColor.w.coerceIn( + MIN_MATERIAL_COLOR_VALUE, + MAX_MATERIAL_COLOR_VALUE + ), ) ) ) diff --git a/app/src/main/res/drawable/search_24px.xml b/app/src/main/res/drawable/search_24px.xml new file mode 100644 index 0000000..9d6244a --- /dev/null +++ b/app/src/main/res/drawable/search_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b95edb9..a2708e4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,18 +1,18 @@ [versions] -androidx-runtime = "1.9.2" -agp = "8.13.0" -arcore = "1.0.0-alpha06" -compose = "1.0.0-alpha07" +androidx-runtime = "1.10.0" +agp = "8.13.1" +arcore = "1.0.0-alpha09" +compose = "1.0.0-alpha09" extensionsXr = "1.1.0" -scenecore = "1.0.0-alpha07" +scenecore = "1.0.0-alpha10" kotlinxCoroutinesGuava = "1.10.2" -kotlin = "2.2.0" +kotlin = "2.2.21" concurrentFuturesKtx = "1.3.0" -activityCompose = "1.10.1" -composeBom = "2025.08.00" -material = "1.12.0" -adaptiveAndroid = "1.1.0" -kotlinAndroid = "2.2.0" +activityCompose = "1.12.1" +composeBom = "2025.12.00" +material = "1.13.0" +adaptiveAndroid = "1.2.0" +kotlinAndroid = "2.2.21" [libraries] androidx-arcore = { module = "androidx.xr.arcore:arcore", version.ref = "arcore" }