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.scenecore
18 
19 import android.content.Context
20 import android.view.View
21 import androidx.annotation.RestrictTo
22 import androidx.xr.runtime.Session
23 import androidx.xr.runtime.internal.JxrPlatformAdapter
24 import androidx.xr.runtime.internal.PanelEntity as RtPanelEntity
25 import androidx.xr.runtime.math.Pose
26 import androidx.xr.runtime.math.Vector3
27 
28 /** Provides implementations for common Panel functionality. */
29 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
30 public sealed class BasePanelEntity<out RtPanelEntityType : RtPanelEntity>(
31     private val rtPanelEntity: RtPanelEntityType,
32     entityManager: EntityManager,
33 ) : BaseEntity<RtPanelEntity>(rtPanelEntity, entityManager) {
34 
35     /**
36      * Sets the corner radius of the PanelEntity.
37      *
38      * @param radius The radius of the corners, in meters.
39      * @throws IllegalArgumentException if radius is <= 0.0f.
40      */
setCornerRadiusnull41     public fun setCornerRadius(radius: Float) {
42         rtPanelEntity.cornerRadius = radius
43     }
44 
45     /** Gets the corner radius of this PanelEntity in meters. Has a default value of 0. */
getCornerRadiusnull46     public fun getCornerRadius(): Float {
47         return rtPanelEntity.cornerRadius
48     }
49 
50     /**
51      * Returns the dimensions in local space, in unscaled meters for this panel entity.
52      *
53      * <p>
54      * Users of this api can convert this entity's local space dimensions to real world meters by
55      * multiplying the local space dimensions with relative scale of this entity in unscaled world
56      * space i.e. real meters = local space dimensions getScale(Space.REAL_WORLD) and vice versa.
57      * For example a panel entity 1x1 dimensions in local space will look 2x2 meters in real world
58      * if the relative scale applied to this entity in the world space is 2.
59      */
getSizenull60     public fun getSize(): Dimensions {
61         return rtPanelEntity.size.toDimensions()
62     }
63 
64     /** Returns the dimensions in Pixels for this panel entity. */
getSizeInPixelsnull65     public fun getSizeInPixels(): PixelDimensions {
66         return rtPanelEntity.sizeInPixels.toPixelDimensions()
67     }
68 
69     /**
70      * Gets the number of pixels per meter for this panel. This value reflects changes to scale,
71      * including parent scale.
72      *
73      * @return Vector3 scale applied to pixels within the Panel. (Z will be 0)
74      */
75     @Deprecated("This api will be removed in a future release.")
getPixelDensitynull76     public fun getPixelDensity(): Vector3 {
77         return rtPanelEntity.pixelDensity
78     }
79 
80     /**
81      * Sets the size in meters for the surface on which the View is laid out. The dimensions
82      * provided are unscaled meters in the local space.
83      *
84      * <p>
85      * Users of this api can convert this entity's local space dimensions to real world meters by
86      * multiplying the local space dimensions with relative scale of this entity in unscaled world
87      * space i.e. real meters = local space dimensions * getScale(Space.REAL_WORLD) and vice versa.
88      * For example a panel entity 1x1 dimensions in local space will look 2x2 meters in real world
89      * if the relative scale applied to this entity in the world space is 2.
90      *
91      * @param dimensions Dimensions in meters in local space.
92      */
setSizenull93     public fun setSize(dimensions: Dimensions) {
94         rtPanelEntity.size = dimensions.toRtDimensions()
95     }
96 
97     /**
98      * Sets the size in pixels for the surface on which the view is laid out. This essentially sets
99      * the resolution of underlying surface. The dimensions provided are in pixels.
100      *
101      * <p>
102      * This API doesn't do any scale compensation to pixel dimensions provided.
103      *
104      * @param pixelDimensions Dimensions in pixels.
105      */
setSizeInPixelsnull106     public fun setSizeInPixels(pixelDimensions: PixelDimensions) {
107         rtPanelEntity.sizeInPixels = pixelDimensions.toRtPixelDimensions()
108     }
109 }
110 
111 /** PanelEntity creates a spatial panel in Android XR. */
112 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
113 public open class PanelEntity
114 internal constructor(
115     rtEntity: RtPanelEntity,
116     entityManager: EntityManager,
117     // TODO(ricknels): move isMainPanelEntity check to JxrPlatformAdapter.
118     public val isMainPanelEntity: Boolean = false,
119 ) : BasePanelEntity<RtPanelEntity>(rtEntity, entityManager) {
120 
121     public companion object {
createnull122         internal fun create(
123             context: Context,
124             adapter: JxrPlatformAdapter,
125             entityManager: EntityManager,
126             view: View,
127             dimensions: Dimensions,
128             name: String,
129             pose: Pose = Pose.Identity,
130         ): PanelEntity =
131             PanelEntity(
132                 adapter.createPanelEntity(
133                     context,
134                     pose,
135                     view,
136                     dimensions.toRtDimensions(),
137                     name,
138                     adapter.activitySpaceRootImpl,
139                 ),
140                 entityManager,
141             )
142 
143         internal fun create(
144             context: Context,
145             adapter: JxrPlatformAdapter,
146             entityManager: EntityManager,
147             view: View,
148             pixelDimensions: PixelDimensions,
149             name: String,
150             pose: Pose = Pose.Identity,
151         ): PanelEntity =
152             PanelEntity(
153                 adapter.createPanelEntity(
154                     context,
155                     pose,
156                     view,
157                     pixelDimensions.toRtPixelDimensions(),
158                     name,
159                     adapter.activitySpaceRootImpl,
160                 ),
161                 entityManager,
162             )
163 
164         /**
165          * Public factory function for a spatialized PanelEntity.
166          *
167          * @param session Session to create the PanelEntity in.
168          * @param view View to embed in this panel entity.
169          * @param dimensions Dimensions for the underlying surface for the given view in meters.
170          * @param name Name of the panel.
171          * @param pose Pose of this entity relative to its parent, default value is Identity.
172          * @return a PanelEntity instance.
173          */
174         @JvmOverloads
175         @JvmStatic
176         public fun create(
177             session: Session,
178             view: View,
179             dimensions: Dimensions,
180             name: String,
181             pose: Pose = Pose.Identity,
182         ): PanelEntity =
183             PanelEntity.create(
184                 session.activity,
185                 session.platformAdapter,
186                 session.scene.entityManager,
187                 view,
188                 dimensions,
189                 name,
190                 pose,
191             )
192 
193         /**
194          * Public factory function for a spatialized PanelEntity.
195          *
196          * @param session Session to create the PanelEntity in.
197          * @param view View to embed in this panel entity.
198          * @param pixelDimensions Dimensions for the underlying surface for the given view in
199          *   pixels.
200          * @param name Name of the panel.
201          * @param pose Pose of this entity relative to its parent, default value is Identity.
202          * @return a PanelEntity instance.
203          */
204         @JvmOverloads
205         @JvmStatic
206         public fun create(
207             session: Session,
208             view: View,
209             pixelDimensions: PixelDimensions,
210             name: String,
211             pose: Pose = Pose.Identity,
212         ): PanelEntity =
213             PanelEntity.create(
214                 session.activity,
215                 session.platformAdapter,
216                 session.scene.entityManager,
217                 view,
218                 pixelDimensions,
219                 name,
220                 pose,
221             )
222 
223         /** Returns the PanelEntity backed by the main window for the Activity. */
224         internal fun createMainPanelEntity(
225             adapter: JxrPlatformAdapter,
226             entityManager: EntityManager,
227         ): PanelEntity =
228             PanelEntity(adapter.mainPanelEntity, entityManager, isMainPanelEntity = true)
229     }
230 }
231