@webspatial/core-sdk 1.2.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ import { SpatialObject } from '../SpatialObject'
2
+ import {
3
+ CreateAttachmentEntityCommand,
4
+ UpdateAttachmentEntityCommand,
5
+ InitializeAttachmentCommand,
6
+ } from '../JSBCommand'
7
+ import {
8
+ AttachmentEntityOptions,
9
+ AttachmentEntityUpdateOptions,
10
+ } from '../types/types'
11
+
12
+ export class Attachment extends SpatialObject {
13
+ constructor(
14
+ id: string,
15
+ private readonly windowProxy: WindowProxy,
16
+ private options: AttachmentEntityOptions,
17
+ ) {
18
+ super(id)
19
+ }
20
+
21
+ getContainer(): HTMLElement {
22
+ return (this.windowProxy as Window).document.body
23
+ }
24
+
25
+ getWindowProxy(): WindowProxy {
26
+ return this.windowProxy
27
+ }
28
+
29
+ async update(options: AttachmentEntityUpdateOptions) {
30
+ if (this.isDestroyed) return
31
+ if (options.position) this.options.position = options.position
32
+ if (options.size) this.options.size = options.size
33
+ return new UpdateAttachmentEntityCommand(this.id, options).execute()
34
+ }
35
+ }
36
+
37
+ export async function createAttachmentEntity(
38
+ options: AttachmentEntityOptions,
39
+ ): Promise<Attachment> {
40
+ const result = await new CreateAttachmentEntityCommand(options).execute()
41
+ if (!result.success) {
42
+ throw new Error('createAttachmentEntity failed: ' + result?.errorMessage)
43
+ }
44
+ const { id, windowProxy } = result.data!
45
+ await new InitializeAttachmentCommand(id, options).execute()
46
+ return new Attachment(id, windowProxy, options)
47
+ }
@@ -23,16 +23,16 @@ import { SpatialComponent } from '../component/SpatialComponent'
23
23
  import { SpatialWebEvent } from '../../SpatialWebEvent'
24
24
  import { createSpatialEvent } from '../../SpatialWebEventCreator'
25
25
  import {
26
- CubeInfoMsg,
27
26
  ObjectDestroyMsg,
28
27
  SpatialDragEndMsg,
29
28
  SpatialDragMsg,
29
+ SpatialDragStartMsg,
30
+ SpatialMagnifyEndMsg,
30
31
  SpatialMagnifyMsg,
31
32
  SpatialRotateEndMsg,
32
33
  SpatialRotateMsg,
33
34
  SpatialTapMsg,
34
35
  SpatialWebMsgType,
35
- TransformMsg,
36
36
  } from '../../WebMsgCommand'
37
37
 
38
38
  export class SpatialEntity extends SpatialObject {
@@ -43,6 +43,31 @@ export class SpatialEntity extends SpatialObject {
43
43
  events: Record<string, (data: any) => void> = {}
44
44
  children: SpatialEntity[] = []
45
45
  parent: SpatialEntityOrReality | null = null
46
+ private _enableInput: boolean = false
47
+
48
+ get enableInput(): boolean {
49
+ return this._enableInput
50
+ }
51
+
52
+ set enableInput(value: boolean) {
53
+ // Why enabling only 'spatialtap' makes the entity interactive:
54
+ // - On the native (Swift/RealityKit) side, SpatialEntity.updateGesture(type, isEnable)
55
+ // toggles per-gesture flags. Then enableInteractive = enableTap || enableRotate || enableDrag || enableMagnify.
56
+ // - As soon as any gesture (e.g., 'spatialtap') is enabled, enableInteractive becomes true and
57
+ // InputTargetComponent is attached, making the entity targetable by targetedToAnyEntity().
58
+ // - The view layer forwards hit gestures to the web, so enabling 'spatialtap' is sufficient to
59
+ // make the entity targetable; enable additional gestures only when needed.
60
+ if (this._enableInput === value) return
61
+ this._enableInput = value
62
+ void this.updateEntityEvent('spatialtap', value).catch(err => {
63
+ console.error('enableInput updateEntityEvent failed', 'spatialtap', err)
64
+ // Roll back local flag if the native toggle fails to keep web/native states consistent.
65
+ // Otherwise, the web side would think the entity is interactive while RealityKit is not.
66
+ if (this._enableInput === value) {
67
+ this._enableInput = !value
68
+ }
69
+ })
70
+ }
46
71
  constructor(
47
72
  id: string,
48
73
  public userData?: SpatialEntityUserData,
@@ -123,13 +148,15 @@ export class SpatialEntity extends SpatialObject {
123
148
  return new UpdateEntityEventCommand(this, eventName, isEnable).execute()
124
149
  }
125
150
  private onReceiveEvent = (
126
- data: // | CubeInfoMsg
127
- // | TransformMsg
128
- | SpatialTapMsg
129
- // | SpatialDragMsg
130
- // | SpatialDragEndMsg
131
- // | SpatialRotateMsg
132
- // | SpatialRotateEndMsg
151
+ data:
152
+ | SpatialTapMsg
153
+ | SpatialDragStartMsg
154
+ | SpatialDragMsg
155
+ | SpatialDragEndMsg
156
+ | SpatialMagnifyMsg
157
+ | SpatialMagnifyEndMsg
158
+ | SpatialRotateMsg
159
+ | SpatialRotateEndMsg
133
160
  | ObjectDestroyMsg,
134
161
  ) => {
135
162
  // console.log('SpatialEntityEvent', data)
@@ -139,27 +166,21 @@ export class SpatialEntity extends SpatialObject {
139
166
  }
140
167
  // tap
141
168
  else if (type === SpatialWebMsgType.spatialtap) {
142
- const evt = createSpatialEvent(
143
- SpatialWebMsgType.spatialtap,
144
- (data as SpatialTapMsg).detail,
145
- )
169
+ const evt = createSpatialEvent(SpatialWebMsgType.spatialtap, data.detail)
146
170
  this.dispatchEvent(evt)
147
171
  } else if (type === SpatialWebMsgType.spatialdragstart) {
148
172
  const evt = createSpatialEvent(
149
173
  SpatialWebMsgType.spatialdragstart,
150
- (data as SpatialDragMsg).detail,
174
+ data.detail,
151
175
  )
152
176
  this.dispatchEvent(evt)
153
177
  } else if (type === SpatialWebMsgType.spatialdrag) {
154
- const evt = createSpatialEvent(
155
- SpatialWebMsgType.spatialdrag,
156
- (data as SpatialDragMsg).detail,
157
- )
178
+ const evt = createSpatialEvent(SpatialWebMsgType.spatialdrag, data.detail)
158
179
  this.dispatchEvent(evt)
159
180
  } else if (type === SpatialWebMsgType.spatialdragend) {
160
181
  const evt = createSpatialEvent(
161
182
  SpatialWebMsgType.spatialdragend,
162
- (data as SpatialDragEndMsg).detail,
183
+ data.detail,
163
184
  )
164
185
  this.dispatchEvent(evt)
165
186
  }
@@ -167,13 +188,13 @@ export class SpatialEntity extends SpatialObject {
167
188
  else if (type === SpatialWebMsgType.spatialrotate) {
168
189
  const evt = createSpatialEvent(
169
190
  SpatialWebMsgType.spatialrotate,
170
- (data as SpatialRotateMsg).detail,
191
+ data.detail,
171
192
  )
172
193
  this.dispatchEvent(evt)
173
194
  } else if (type === SpatialWebMsgType.spatialrotateend) {
174
195
  const evt = createSpatialEvent(
175
196
  SpatialWebMsgType.spatialrotateend,
176
- (data as SpatialRotateEndMsg).detail,
197
+ data.detail,
177
198
  )
178
199
  this.dispatchEvent(evt)
179
200
  }
@@ -181,13 +202,13 @@ export class SpatialEntity extends SpatialObject {
181
202
  else if (type === SpatialWebMsgType.spatialmagnify) {
182
203
  const evt = createSpatialEvent(
183
204
  SpatialWebMsgType.spatialmagnify,
184
- (data as SpatialMagnifyMsg).detail,
205
+ data.detail,
185
206
  )
186
207
  this.dispatchEvent(evt)
187
208
  } else if (type === SpatialWebMsgType.spatialmagnifyend) {
188
209
  const evt = createSpatialEvent(
189
210
  SpatialWebMsgType.spatialmagnifyend,
190
- (data as SpatialMagnifyMsg).detail,
211
+ data.detail,
191
212
  )
192
213
  this.dispatchEvent(evt)
193
214
  }
@@ -200,7 +221,7 @@ export class SpatialEntity extends SpatialObject {
200
221
  }
201
222
  this.events[evt.type]?.(evt)
202
223
  if (evt.bubbles && !evt.cancelBubble) {
203
- if (this.parent && this.parent instanceof SpatialEntity) {
224
+ if (this.parent) {
204
225
  this.parent.dispatchEvent(evt)
205
226
  }
206
227
  }
@@ -3,3 +3,4 @@ export * from './component'
3
3
  export * from './material'
4
4
  export * from './geometry'
5
5
  export * from './resource'
6
+ export * from './Attachment'
@@ -1,3 +1,5 @@
1
+ import type { PhysicalMetricsValueShape } from '../physicalMetrics'
2
+
1
3
  declare global {
2
4
  declare const __WEBSPATIAL_CORE_SDK_VERSION__: string
3
5
 
@@ -28,16 +30,16 @@ declare global {
28
30
  'natvie-version'?: string
29
31
  'react-sdk-version'?: string
30
32
  'core-sdk-version'?: string
33
+ physicalMetrics?: PhysicalMetricsValueShape
31
34
  }
32
35
 
33
- innerDepth: number
34
- outerDepth: number
36
+ xrInnerDepth: number
37
+ xrOuterDepth: number
35
38
  }
36
39
 
37
40
  interface HTMLElement {
38
- offsetBack: number
39
- clientDepth: number
40
- getBoundingClientCube: () => CubeInfo | undefined
41
+ xrOffsetBack: number
42
+ xrClientDepth: number
41
43
  }
42
44
  }
43
45
 
@@ -80,6 +80,11 @@ export interface SpatializedElementProperties {
80
80
  enableRotateEndGesture: boolean
81
81
  enableMagnifyGesture: boolean
82
82
  enableMagnifyEndGesture: boolean
83
+ /**
84
+ * Optional world-space axis for spatial rotate gesture. Omitted or zero vector
85
+ * means unconstrained rotation (platform default).
86
+ */
87
+ rotateConstrainedToAxis?: Vec3
83
88
  }
84
89
 
85
90
  export interface Spatialized2DElementProperties
@@ -115,6 +120,16 @@ export interface SpatialSceneCreationOptions {
115
120
  baseplateVisibility?: BaseplateVisibilityType
116
121
  }
117
122
 
123
+ export type SpatialEntityEventType =
124
+ | 'spatialtap'
125
+ | 'spatialdragstart'
126
+ | 'spatialdrag'
127
+ | 'spatialdragend'
128
+ | 'spatialrotate'
129
+ | 'spatialrotateend'
130
+ | 'spatialmagnify'
131
+ | 'spatialmagnifyend'
132
+
118
133
  export const BaseplateVisibilityValues = [
119
134
  'automatic',
120
135
  'visible',
@@ -186,8 +201,6 @@ export interface SpatialEntityProperties {
186
201
  scale: Vec3
187
202
  }
188
203
 
189
- export type SpatialEntityEventType = 'spatialtap' //| 'drag' | 'rotate' | 'scale'
190
-
191
204
  export type SpatialGeometryType =
192
205
  | 'BoxGeometry'
193
206
  | 'PlaneGeometry'
@@ -344,12 +357,14 @@ export class CubeInfo {
344
357
 
345
358
  export interface SpatialTapEventDetail {
346
359
  location3D: Point3D
360
+ globalLocation3D?: Point3D
347
361
  }
348
362
 
349
363
  export type SpatialTapEvent = CustomEvent<SpatialTapEventDetail>
350
364
 
351
365
  export interface SpatialDragStartEventDetail {
352
366
  startLocation3D: Point3D
367
+ globalLocation3D?: Point3D
353
368
  }
354
369
 
355
370
  export interface SpatialDragEventDetail {
@@ -384,3 +399,15 @@ export type SpatialMagnifyEvent = CustomEvent<SpatialMagnifyEventDetail>
384
399
  export type SpatialMagnifyEndEvent = CustomEvent<SpatialMagnifyEndEventDetail>
385
400
 
386
401
  export type SpatialEntityOrReality = SpatialEntity | SpatializedDynamic3DElement
402
+
403
+ export interface AttachmentEntityOptions {
404
+ parentEntityId: string
405
+ position?: [number, number, number]
406
+ size: { width: number; height: number }
407
+ ownerViewId: string
408
+ }
409
+
410
+ export interface AttachmentEntityUpdateOptions {
411
+ position?: [number, number, number]
412
+ size?: { width: number; height: number }
413
+ }