1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.xr.arcore 18 19 import android.annotation.SuppressLint 20 import androidx.xr.runtime.internal.Hand as RuntimeHand 21 import androidx.xr.runtime.internal.LifecycleManager 22 import androidx.xr.runtime.internal.Plane as RuntimePlane 23 import androidx.xr.runtime.internal.Trackable as RuntimeTrackable 24 import java.util.Queue 25 import java.util.concurrent.ConcurrentLinkedQueue 26 import java.util.concurrent.CopyOnWriteArrayList 27 28 /** Manages all XR resources that are used by the ARCore for XR API. */ 29 internal class XrResourcesManager { 30 31 internal lateinit var lifecycleManager: LifecycleManager 32 33 /** List of [Updatable]s that are updated every frame. */ 34 private val _updatables = CopyOnWriteArrayList<Updatable>() 35 val updatables: List<Updatable> = _updatables 36 37 /** Queue of [Anchor]s that will be detached on the next frame update. */ 38 private val _anchorsToDetachQueue = ConcurrentLinkedQueue<Anchor>() 39 val anchorsToDetachQueue: Queue<Anchor> = _anchorsToDetachQueue 40 41 /** Map of runtime trackable pointer to [Trackable]. */ 42 @SuppressLint("BanConcurrentHashMap") 43 private val _trackablesMap = 44 java.util.concurrent.ConcurrentHashMap<RuntimeTrackable, Trackable<Trackable.State>>() 45 val trackablesMap: Map<RuntimeTrackable, Trackable<Trackable.State>> = _trackablesMap 46 47 /** The data of hands */ 48 private var _leftRuntimeHand: RuntimeHand? = null 49 private var _rightRuntimeHand: RuntimeHand? = null <lambda>null50 val leftHand: Hand? by lazy { _leftRuntimeHand?.let { Hand(it) } } <lambda>null51 val rightHand: Hand? by lazy { _rightRuntimeHand?.let { Hand(it) } } 52 initiateHandsnull53 internal fun initiateHands(leftRuntimeHand: RuntimeHand?, rightRuntimeHand: RuntimeHand?) { 54 _leftRuntimeHand = leftRuntimeHand 55 _rightRuntimeHand = rightRuntimeHand 56 } 57 addUpdatablenull58 internal fun addUpdatable(updatable: Updatable) { 59 _updatables.add(updatable) 60 } 61 removeUpdatablenull62 internal fun removeUpdatable(updatable: Updatable) { 63 _updatables.remove(updatable) 64 } 65 queueAnchorToDetachnull66 internal fun queueAnchorToDetach(anchor: Anchor) { 67 _anchorsToDetachQueue.add(anchor) 68 } 69 updatenull70 internal suspend fun update() { 71 while (!_anchorsToDetachQueue.isEmpty()) { 72 _anchorsToDetachQueue.poll()?.runtimeAnchor?.detach() 73 } 74 75 for (updatable in updatables) { 76 updatable.update() 77 } 78 } 79 syncTrackablesnull80 internal fun syncTrackables(runtimeTrackables: Collection<RuntimeTrackable>) { 81 val toRemoveTrackables = _trackablesMap.keys - runtimeTrackables 82 val toAddTrackables = runtimeTrackables - _trackablesMap.keys 83 84 for (runtimeTrackable in toRemoveTrackables) { 85 removeUpdatable(_trackablesMap[runtimeTrackable]!! as Updatable) 86 _trackablesMap.remove(runtimeTrackable) 87 } 88 89 for (runtimeTrackable in toAddTrackables) { 90 val trackable = createTrackable(runtimeTrackable) 91 _trackablesMap[runtimeTrackable] = trackable 92 addUpdatable(trackable as Updatable) 93 } 94 } 95 clearnull96 internal fun clear() { 97 _updatables.clear() 98 _trackablesMap.clear() 99 } 100 createTrackablenull101 private fun createTrackable(runtimeTrackable: RuntimeTrackable): Trackable<Trackable.State> { 102 if (_trackablesMap.containsKey(runtimeTrackable)) { 103 return _trackablesMap[runtimeTrackable]!! 104 } 105 106 val trackable = 107 when (runtimeTrackable) { 108 is RuntimePlane -> Plane(runtimeTrackable, this) 109 else -> 110 throw IllegalArgumentException( 111 "Unsupported trackable type: ${runtimeTrackable.javaClass}" 112 ) 113 } 114 _trackablesMap[runtimeTrackable] = trackable 115 return trackable 116 } 117 } 118