@webspatial/core-sdk 1.0.4 → 1.1.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.
- package/CHANGELOG.md +8 -0
- package/README.md +112 -81
- package/dist/iife/index.d.ts +683 -561
- package/dist/iife/index.global.js +3 -4
- package/dist/iife/index.global.js.map +1 -1
- package/dist/index.d.ts +683 -561
- package/dist/index.js +2193 -1291
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
- package/src/JSBCommand.ts +631 -0
- package/src/Spatial.ts +68 -0
- package/src/SpatialObject.ts +46 -0
- package/src/SpatialScene.ts +75 -0
- package/src/SpatialSession.ts +187 -0
- package/src/SpatialWebEvent.ts +23 -0
- package/src/SpatialWebEventCreator.ts +12 -0
- package/src/Spatialized2DElement.ts +51 -0
- package/src/SpatializedDynamic3DElement.ts +30 -0
- package/src/SpatializedElement.ts +331 -0
- package/src/SpatializedElementCreator.ts +45 -0
- package/src/SpatializedStatic3DElement.ts +111 -0
- package/src/WebMsgCommand.ts +88 -0
- package/src/index.ts +23 -1
- package/src/platform-adapter/CommandResultUtils.ts +22 -0
- package/src/platform-adapter/android/AndroidPlatform.ts +133 -0
- package/src/platform-adapter/index.ts +21 -0
- package/src/platform-adapter/interface.ts +36 -0
- package/src/platform-adapter/ssr/SSRPlatform.ts +43 -0
- package/src/platform-adapter/vision-os/VisionOSPlatform.ts +77 -0
- package/src/reality/component/ModelComponent.ts +11 -0
- package/src/reality/component/SpatialComponent.ts +17 -0
- package/src/reality/component/index.ts +2 -0
- package/src/reality/entity/SpatialEntity.ts +259 -0
- package/src/reality/entity/SpatialModelEntity.ts +15 -0
- package/src/reality/entity/index.ts +2 -0
- package/src/reality/geometry/SpatialBoxGeometry.ts +12 -0
- package/src/reality/geometry/SpatialConeGeometry.ts +15 -0
- package/src/reality/geometry/SpatialCylinderGeometry.ts +15 -0
- package/src/reality/geometry/SpatialGeometry.ts +12 -0
- package/src/reality/geometry/SpatialPlaneGeometry.ts +15 -0
- package/src/reality/geometry/SpatialSphereGeometry.ts +15 -0
- package/src/reality/geometry/index.ts +6 -0
- package/src/reality/index.ts +5 -0
- package/src/reality/material/SpatialMaterial.ts +14 -0
- package/src/reality/material/SpatialUnlitMaterial.ts +16 -0
- package/src/reality/material/index.ts +2 -0
- package/src/reality/realityCreator.ts +94 -0
- package/src/reality/resource/SpatialModelAsset.ts +11 -0
- package/src/reality/resource/index.ts +1 -0
- package/src/scene-polyfill.test.ts +376 -0
- package/src/scene-polyfill.ts +379 -0
- package/src/spatial-window-polyfill.ts +182 -0
- package/src/ssr-polyfill.ts +3 -0
- package/src/types/global.d.ts +33 -1
- package/src/types/internal.ts +13 -0
- package/src/types/types.ts +380 -0
- package/src/utils.ts +61 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +8 -0
- package/src/core/Spatial.ts +0 -50
- package/src/core/SpatialEntity.ts +0 -147
- package/src/core/SpatialHelper.ts +0 -230
- package/src/core/SpatialObject.ts +0 -26
- package/src/core/SpatialSession.ts +0 -457
- package/src/core/SpatialTransform.ts +0 -26
- package/src/core/SpatialWindowContainer.ts +0 -59
- package/src/core/component/EventSpatialComponent.ts +0 -32
- package/src/core/component/SpatialComponent.ts +0 -26
- package/src/core/component/SpatialInputComponent.ts +0 -24
- package/src/core/component/SpatialModel3DComponent.ts +0 -223
- package/src/core/component/SpatialModelComponent.ts +0 -39
- package/src/core/component/SpatialViewComponent.ts +0 -32
- package/src/core/component/SpatialWindowComponent.ts +0 -177
- package/src/core/component/index.ts +0 -14
- package/src/core/index.ts +0 -10
- package/src/core/private/WebSpatial.ts +0 -383
- package/src/core/private/remote-command/RemoteCommand.ts +0 -15
- package/src/core/private/remote-command/index.ts +0 -1
- package/src/core/resource/SpatialMeshResource.ts +0 -6
- package/src/core/resource/SpatialPhysicallyBasedMaterialResource.ts +0 -42
- package/src/core/resource/index.ts +0 -2
- package/src/core/types.ts +0 -32
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { PlatformAbility, CommandResult } from '../interface'
|
|
2
|
+
import {
|
|
3
|
+
CommandResultFailure,
|
|
4
|
+
CommandResultSuccess,
|
|
5
|
+
} from '../CommandResultUtils'
|
|
6
|
+
import { CheckWebViewCanCreateCommand } from '../../JSBCommand'
|
|
7
|
+
import { SpatialWebEvent } from '../../SpatialWebEvent'
|
|
8
|
+
|
|
9
|
+
interface JSBResponse {
|
|
10
|
+
success: boolean
|
|
11
|
+
data: any
|
|
12
|
+
}
|
|
13
|
+
type JSBError = {
|
|
14
|
+
code: string
|
|
15
|
+
message: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let creatingElementCount = 0
|
|
19
|
+
|
|
20
|
+
let requestId = 0
|
|
21
|
+
|
|
22
|
+
const MAX_ID = 100000
|
|
23
|
+
|
|
24
|
+
function nextRequestId() {
|
|
25
|
+
requestId = (requestId + 1) % MAX_ID
|
|
26
|
+
return `rId_${requestId}`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class AndroidPlatform implements PlatformAbility {
|
|
30
|
+
async callJSB(cmd: string, msg: string): Promise<CommandResult> {
|
|
31
|
+
// android JS Bridge interface only support sync invoking
|
|
32
|
+
// in order to implement promise API, register every request by requestId and remove when resolve/reject.
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
try {
|
|
35
|
+
const rId = nextRequestId()
|
|
36
|
+
|
|
37
|
+
SpatialWebEvent.addEventReceiver(rId, (result: JSBResponse) => {
|
|
38
|
+
SpatialWebEvent.removeEventReceiver(rId)
|
|
39
|
+
if (result.success) {
|
|
40
|
+
resolve(CommandResultSuccess(result.data))
|
|
41
|
+
} else {
|
|
42
|
+
const { code, message } = result.data as JSBError
|
|
43
|
+
resolve(CommandResultFailure(code, message))
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const ans = window.webspatialBridge.postMessage(rId, cmd, msg)
|
|
48
|
+
if (ans !== '') {
|
|
49
|
+
SpatialWebEvent.removeEventReceiver(rId)
|
|
50
|
+
// sync call
|
|
51
|
+
const result = JSON.parse(ans) as JSBResponse
|
|
52
|
+
if (result.success) {
|
|
53
|
+
resolve(CommandResultSuccess(result.data))
|
|
54
|
+
} else {
|
|
55
|
+
const { code, message } = result.data as JSBError
|
|
56
|
+
resolve(CommandResultFailure(code, message))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
} catch (error: unknown) {
|
|
60
|
+
console.error(
|
|
61
|
+
`AndroidPlatform cmd: ${cmd}, msg: ${msg} error: ${error}`,
|
|
62
|
+
)
|
|
63
|
+
const { code, message } = error as JSBError
|
|
64
|
+
resolve(CommandResultFailure(code, message))
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async callWebSpatialProtocol(
|
|
70
|
+
command: string,
|
|
71
|
+
query?: string,
|
|
72
|
+
target?: string,
|
|
73
|
+
features?: string,
|
|
74
|
+
): Promise<CommandResult> {
|
|
75
|
+
// Waiting for request to create spatial div
|
|
76
|
+
await new Promise(resolve => setTimeout(resolve, 16 * creatingElementCount))
|
|
77
|
+
// Count the current total number of created spatial div queues
|
|
78
|
+
creatingElementCount++
|
|
79
|
+
// Create a spatial div through JSB polling request
|
|
80
|
+
let canCreate = await new CheckWebViewCanCreateCommand().execute()
|
|
81
|
+
while (!canCreate.data.can) {
|
|
82
|
+
await new Promise(resolve => setTimeout(resolve, 16))
|
|
83
|
+
canCreate = await new CheckWebViewCanCreateCommand().execute()
|
|
84
|
+
}
|
|
85
|
+
// Request successful, call window.open
|
|
86
|
+
const { windowProxy } = this.openWindow(command, query, target, features)
|
|
87
|
+
// Polling waiting for windowProxy to convert into a real window object
|
|
88
|
+
while (!windowProxy?.open) {
|
|
89
|
+
await new Promise(resolve => setTimeout(resolve, 16))
|
|
90
|
+
}
|
|
91
|
+
// Make the page renderable through window.open
|
|
92
|
+
windowProxy?.open('about:blank', '_self')
|
|
93
|
+
// Polling to check if SpatialId injection is successful
|
|
94
|
+
while (!windowProxy?.__SpatialId) {
|
|
95
|
+
await new Promise(resolve => setTimeout(resolve, 16))
|
|
96
|
+
}
|
|
97
|
+
let spatialId = windowProxy?.__SpatialId
|
|
98
|
+
creatingElementCount--
|
|
99
|
+
return Promise.resolve(
|
|
100
|
+
CommandResultSuccess({ windowProxy: windowProxy, id: spatialId }),
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
callWebSpatialProtocolSync(
|
|
105
|
+
command: string,
|
|
106
|
+
query?: string,
|
|
107
|
+
target?: string,
|
|
108
|
+
features?: string,
|
|
109
|
+
): CommandResult {
|
|
110
|
+
const { spatialId: id = '', windowProxy } = this.openWindow(
|
|
111
|
+
command,
|
|
112
|
+
query,
|
|
113
|
+
target,
|
|
114
|
+
features,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return CommandResultSuccess({ windowProxy, id })
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private openWindow(
|
|
121
|
+
command: string,
|
|
122
|
+
query?: string,
|
|
123
|
+
target?: string,
|
|
124
|
+
features?: string,
|
|
125
|
+
) {
|
|
126
|
+
const windowProxy = window.open(
|
|
127
|
+
`webspatial://${command}?${query || ''}`,
|
|
128
|
+
target,
|
|
129
|
+
features,
|
|
130
|
+
)
|
|
131
|
+
return { spatialId: '', windowProxy }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { isSSREnv } from '../ssr-polyfill'
|
|
2
|
+
import { PlatformAbility } from './interface'
|
|
3
|
+
import { SSRPlatform } from './ssr/SSRPlatform'
|
|
4
|
+
|
|
5
|
+
export function createPlatform(): PlatformAbility {
|
|
6
|
+
if (isSSREnv()) {
|
|
7
|
+
return new SSRPlatform()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (
|
|
11
|
+
window.navigator.userAgent.includes('Android') ||
|
|
12
|
+
window.navigator.userAgent.includes('Linux')
|
|
13
|
+
) {
|
|
14
|
+
const AndroidPlatform = require('./android/AndroidPlatform').AndroidPlatform
|
|
15
|
+
return new AndroidPlatform()
|
|
16
|
+
} else {
|
|
17
|
+
const VisionOSPlatform =
|
|
18
|
+
require('./vision-os/VisionOSPlatform').VisionOSPlatform
|
|
19
|
+
return new VisionOSPlatform()
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface CommandResult {
|
|
2
|
+
success: boolean
|
|
3
|
+
data: any
|
|
4
|
+
errorCode: string | undefined
|
|
5
|
+
errorMessage: string | undefined
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface WebSpatialProtocolResult extends CommandResult {
|
|
9
|
+
success: boolean
|
|
10
|
+
data:
|
|
11
|
+
| {
|
|
12
|
+
windowProxy: WindowProxy
|
|
13
|
+
id: string
|
|
14
|
+
}
|
|
15
|
+
| undefined
|
|
16
|
+
errorCode: string | undefined
|
|
17
|
+
errorMessage: string | undefined
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface PlatformAbility {
|
|
21
|
+
callJSB(cmd: string, msg: string): Promise<CommandResult>
|
|
22
|
+
callWebSpatialProtocol(
|
|
23
|
+
schema: string,
|
|
24
|
+
query?: string,
|
|
25
|
+
target?: string,
|
|
26
|
+
features?: string,
|
|
27
|
+
): Promise<WebSpatialProtocolResult>
|
|
28
|
+
|
|
29
|
+
callWebSpatialProtocolSync(
|
|
30
|
+
schema: string,
|
|
31
|
+
query?: string,
|
|
32
|
+
target?: string,
|
|
33
|
+
features?: string,
|
|
34
|
+
resultCallback?: (result: CommandResult) => void,
|
|
35
|
+
): WebSpatialProtocolResult
|
|
36
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CommandResult,
|
|
3
|
+
PlatformAbility,
|
|
4
|
+
WebSpatialProtocolResult,
|
|
5
|
+
} from '../interface'
|
|
6
|
+
|
|
7
|
+
export class SSRPlatform implements PlatformAbility {
|
|
8
|
+
callJSB(cmd: string, msg: string): Promise<CommandResult> {
|
|
9
|
+
return Promise.resolve({
|
|
10
|
+
success: true,
|
|
11
|
+
data: undefined,
|
|
12
|
+
errorCode: undefined,
|
|
13
|
+
errorMessage: undefined,
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
callWebSpatialProtocol(
|
|
17
|
+
schema: string,
|
|
18
|
+
query?: string,
|
|
19
|
+
target?: string,
|
|
20
|
+
features?: string,
|
|
21
|
+
): Promise<WebSpatialProtocolResult> {
|
|
22
|
+
return Promise.resolve({
|
|
23
|
+
success: true,
|
|
24
|
+
data: undefined,
|
|
25
|
+
errorCode: undefined,
|
|
26
|
+
errorMessage: undefined,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
callWebSpatialProtocolSync(
|
|
30
|
+
schema: string,
|
|
31
|
+
query?: string,
|
|
32
|
+
target?: string,
|
|
33
|
+
features?: string,
|
|
34
|
+
resultCallback?: (result: CommandResult) => void,
|
|
35
|
+
): WebSpatialProtocolResult {
|
|
36
|
+
return {
|
|
37
|
+
success: true,
|
|
38
|
+
data: undefined,
|
|
39
|
+
errorCode: undefined,
|
|
40
|
+
errorMessage: undefined,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { PlatformAbility, CommandResult } from '../interface'
|
|
2
|
+
import {
|
|
3
|
+
CommandResultFailure,
|
|
4
|
+
CommandResultSuccess,
|
|
5
|
+
} from '../CommandResultUtils'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
type JSBError = {
|
|
9
|
+
message: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class VisionOSPlatform implements PlatformAbility {
|
|
13
|
+
async callJSB(cmd: string, msg: string): Promise<CommandResult> {
|
|
14
|
+
try {
|
|
15
|
+
const result = await window.webkit.messageHandlers.bridge.postMessage(
|
|
16
|
+
`${cmd}::${msg}`,
|
|
17
|
+
)
|
|
18
|
+
return CommandResultSuccess(result)
|
|
19
|
+
} catch (error: unknown) {
|
|
20
|
+
// console.error(`VisionOSPlatform cmd: ${cmd}, msg: ${msg} error: ${error}`)
|
|
21
|
+
const { code, message } = JSON.parse((error as JSBError).message)
|
|
22
|
+
return CommandResultFailure(code, message)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
callWebSpatialProtocol(
|
|
27
|
+
command: string,
|
|
28
|
+
query?: string,
|
|
29
|
+
target?: string,
|
|
30
|
+
features?: string,
|
|
31
|
+
): Promise<CommandResult> {
|
|
32
|
+
const { spatialId: id, windowProxy } = this.openWindow(
|
|
33
|
+
command,
|
|
34
|
+
query,
|
|
35
|
+
target,
|
|
36
|
+
features,
|
|
37
|
+
)
|
|
38
|
+
return Promise.resolve(
|
|
39
|
+
CommandResultSuccess({ windowProxy: windowProxy, id }),
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
callWebSpatialProtocolSync(
|
|
44
|
+
command: string,
|
|
45
|
+
query?: string,
|
|
46
|
+
target?: string,
|
|
47
|
+
features?: string,
|
|
48
|
+
): CommandResult {
|
|
49
|
+
const { spatialId: id = '', windowProxy } = this.openWindow(
|
|
50
|
+
command,
|
|
51
|
+
query,
|
|
52
|
+
target,
|
|
53
|
+
features,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return CommandResultSuccess({ windowProxy, id })
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private openWindow(
|
|
60
|
+
command: string,
|
|
61
|
+
query?: string,
|
|
62
|
+
target?: string,
|
|
63
|
+
features?: string,
|
|
64
|
+
) {
|
|
65
|
+
const windowProxy = window.open(
|
|
66
|
+
`webspatial://${command}?${query || ''}`,
|
|
67
|
+
target,
|
|
68
|
+
features,
|
|
69
|
+
)
|
|
70
|
+
const ua = windowProxy?.navigator.userAgent
|
|
71
|
+
const spatialId = ua?.match(
|
|
72
|
+
/\b([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})\b/gi,
|
|
73
|
+
)?.[0]
|
|
74
|
+
|
|
75
|
+
return { spatialId, windowProxy }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ModelComponentOptions } from '../../types/types'
|
|
2
|
+
import { SpatialComponent } from './SpatialComponent'
|
|
3
|
+
|
|
4
|
+
export class ModelComponent extends SpatialComponent {
|
|
5
|
+
constructor(
|
|
6
|
+
id: string,
|
|
7
|
+
public options: ModelComponentOptions,
|
|
8
|
+
) {
|
|
9
|
+
super(id)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SpatialObject } from '../../SpatialObject'
|
|
2
|
+
import { SpatialWebEvent } from '../../SpatialWebEvent'
|
|
3
|
+
import { ObjectDestroyMsg, SpatialWebMsgType } from '../../WebMsgCommand'
|
|
4
|
+
|
|
5
|
+
export class SpatialComponent extends SpatialObject {
|
|
6
|
+
constructor(id: string) {
|
|
7
|
+
super(id)
|
|
8
|
+
SpatialWebEvent.addEventReceiver(id, this.onReceiveEvent)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
private onReceiveEvent = (data: ObjectDestroyMsg) => {
|
|
12
|
+
const { type } = data
|
|
13
|
+
if (type === SpatialWebMsgType.objectdestroy) {
|
|
14
|
+
this.isDestroyed = true
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConvertFromEntityToEntityCommand,
|
|
3
|
+
ConvertFromEntityToSceneCommand,
|
|
4
|
+
ConvertFromSceneToEntityCommand,
|
|
5
|
+
SetParentForEntityCommand,
|
|
6
|
+
} from './../../JSBCommand'
|
|
7
|
+
import {
|
|
8
|
+
SpatialEntityEventType,
|
|
9
|
+
SpatialEntityOrReality,
|
|
10
|
+
SpatialEntityUserData,
|
|
11
|
+
Vec3,
|
|
12
|
+
} from '../../types/types'
|
|
13
|
+
import {
|
|
14
|
+
AddComponentToEntityCommand,
|
|
15
|
+
AddEntityToEntityCommand,
|
|
16
|
+
RemoveEntityFromParentCommand,
|
|
17
|
+
UpdateEntityEventCommand,
|
|
18
|
+
UpdateEntityPropertiesCommand,
|
|
19
|
+
} from '../../JSBCommand'
|
|
20
|
+
import { SpatialObject } from '../../SpatialObject'
|
|
21
|
+
import { SpatialEntityProperties } from '../../types/types'
|
|
22
|
+
import { SpatialComponent } from '../component/SpatialComponent'
|
|
23
|
+
import { SpatialWebEvent } from '../../SpatialWebEvent'
|
|
24
|
+
import { createSpatialEvent } from '../../SpatialWebEventCreator'
|
|
25
|
+
import {
|
|
26
|
+
CubeInfoMsg,
|
|
27
|
+
ObjectDestroyMsg,
|
|
28
|
+
SpatialDragEndMsg,
|
|
29
|
+
SpatialDragMsg,
|
|
30
|
+
SpatialMagnifyMsg,
|
|
31
|
+
SpatialRotateEndMsg,
|
|
32
|
+
SpatialRotateMsg,
|
|
33
|
+
SpatialTapMsg,
|
|
34
|
+
SpatialWebMsgType,
|
|
35
|
+
TransformMsg,
|
|
36
|
+
} from '../../WebMsgCommand'
|
|
37
|
+
|
|
38
|
+
export class SpatialEntity extends SpatialObject {
|
|
39
|
+
position: Vec3 = { x: 0, y: 0, z: 0 }
|
|
40
|
+
rotation: Vec3 = { x: 0, y: 0, z: 0 }
|
|
41
|
+
scale: Vec3 = { x: 1, y: 1, z: 1 }
|
|
42
|
+
|
|
43
|
+
events: Record<string, (data: any) => void> = {}
|
|
44
|
+
children: SpatialEntity[] = []
|
|
45
|
+
parent: SpatialEntityOrReality | null = null
|
|
46
|
+
constructor(
|
|
47
|
+
id: string,
|
|
48
|
+
public userData?: SpatialEntityUserData,
|
|
49
|
+
) {
|
|
50
|
+
super(id)
|
|
51
|
+
SpatialWebEvent.addEventReceiver(id, this.onReceiveEvent)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async addComponent(component: SpatialComponent) {
|
|
55
|
+
return new AddComponentToEntityCommand(this, component).execute()
|
|
56
|
+
}
|
|
57
|
+
async setPosition(position: Vec3) {
|
|
58
|
+
return this.updateTransform({ position })
|
|
59
|
+
}
|
|
60
|
+
async setRotation(rotation: Vec3) {
|
|
61
|
+
return this.updateTransform({ rotation })
|
|
62
|
+
}
|
|
63
|
+
async setScale(scale: Vec3) {
|
|
64
|
+
return this.updateTransform({ scale })
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async addEntity(ent: SpatialEntity) {
|
|
68
|
+
const ans = await new SetParentForEntityCommand(ent.id, this.id).execute()
|
|
69
|
+
this.children.push(ent)
|
|
70
|
+
ent.parent = this
|
|
71
|
+
return ans
|
|
72
|
+
}
|
|
73
|
+
async removeFromParent() {
|
|
74
|
+
const ans = await new SetParentForEntityCommand(
|
|
75
|
+
this.id,
|
|
76
|
+
undefined,
|
|
77
|
+
).execute()
|
|
78
|
+
if (this.parent) {
|
|
79
|
+
this.parent.children = this.parent.children.filter(
|
|
80
|
+
child => child.id !== this.id,
|
|
81
|
+
)
|
|
82
|
+
this.parent = null
|
|
83
|
+
}
|
|
84
|
+
return ans
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async updateTransform(properties: Partial<SpatialEntityProperties>) {
|
|
88
|
+
this.position = properties.position ?? this.position
|
|
89
|
+
this.rotation = properties.rotation ?? this.rotation
|
|
90
|
+
this.scale = properties.scale ?? this.scale
|
|
91
|
+
return new UpdateEntityPropertiesCommand(this, properties).execute()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async addEvent(type: SpatialEntityEventType, callback: (data: any) => void) {
|
|
95
|
+
if (this.events[type]) {
|
|
96
|
+
// replace if exist
|
|
97
|
+
this.events[type] = callback
|
|
98
|
+
} else {
|
|
99
|
+
try {
|
|
100
|
+
await this.updateEntityEvent(type, true)
|
|
101
|
+
this.events[type] = callback
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('addEvent failed', type)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async removeEvent(eventName: SpatialEntityEventType) {
|
|
109
|
+
if (this.events[eventName]) {
|
|
110
|
+
delete this.events[eventName]
|
|
111
|
+
try {
|
|
112
|
+
await this.updateEntityEvent(eventName, false)
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error('removeEvent failed', eventName)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async updateEntityEvent(
|
|
120
|
+
eventName: SpatialEntityEventType,
|
|
121
|
+
isEnable: boolean,
|
|
122
|
+
) {
|
|
123
|
+
return new UpdateEntityEventCommand(this, eventName, isEnable).execute()
|
|
124
|
+
}
|
|
125
|
+
private onReceiveEvent = (
|
|
126
|
+
data: // | CubeInfoMsg
|
|
127
|
+
// | TransformMsg
|
|
128
|
+
| SpatialTapMsg
|
|
129
|
+
// | SpatialDragMsg
|
|
130
|
+
// | SpatialDragEndMsg
|
|
131
|
+
// | SpatialRotateMsg
|
|
132
|
+
// | SpatialRotateEndMsg
|
|
133
|
+
| ObjectDestroyMsg,
|
|
134
|
+
) => {
|
|
135
|
+
// console.log('SpatialEntityEvent', data)
|
|
136
|
+
const { type } = data
|
|
137
|
+
if (type === SpatialWebMsgType.objectdestroy) {
|
|
138
|
+
this.isDestroyed = true
|
|
139
|
+
}
|
|
140
|
+
// tap
|
|
141
|
+
else if (type === SpatialWebMsgType.spatialtap) {
|
|
142
|
+
const evt = createSpatialEvent(
|
|
143
|
+
SpatialWebMsgType.spatialtap,
|
|
144
|
+
(data as SpatialTapMsg).detail,
|
|
145
|
+
)
|
|
146
|
+
this.dispatchEvent(evt)
|
|
147
|
+
} else if (type === SpatialWebMsgType.spatialdragstart) {
|
|
148
|
+
const evt = createSpatialEvent(
|
|
149
|
+
SpatialWebMsgType.spatialdragstart,
|
|
150
|
+
(data as SpatialDragMsg).detail,
|
|
151
|
+
)
|
|
152
|
+
this.dispatchEvent(evt)
|
|
153
|
+
} else if (type === SpatialWebMsgType.spatialdrag) {
|
|
154
|
+
const evt = createSpatialEvent(
|
|
155
|
+
SpatialWebMsgType.spatialdrag,
|
|
156
|
+
(data as SpatialDragMsg).detail,
|
|
157
|
+
)
|
|
158
|
+
this.dispatchEvent(evt)
|
|
159
|
+
} else if (type === SpatialWebMsgType.spatialdragend) {
|
|
160
|
+
const evt = createSpatialEvent(
|
|
161
|
+
SpatialWebMsgType.spatialdragend,
|
|
162
|
+
(data as SpatialDragEndMsg).detail,
|
|
163
|
+
)
|
|
164
|
+
this.dispatchEvent(evt)
|
|
165
|
+
}
|
|
166
|
+
// rotate
|
|
167
|
+
else if (type === SpatialWebMsgType.spatialrotatestart) {
|
|
168
|
+
const evt = createSpatialEvent(
|
|
169
|
+
SpatialWebMsgType.spatialrotatestart,
|
|
170
|
+
(data as SpatialRotateMsg).detail,
|
|
171
|
+
)
|
|
172
|
+
this.dispatchEvent(evt)
|
|
173
|
+
} else if (type === SpatialWebMsgType.spatialrotate) {
|
|
174
|
+
const evt = createSpatialEvent(
|
|
175
|
+
SpatialWebMsgType.spatialrotate,
|
|
176
|
+
(data as SpatialRotateMsg).detail,
|
|
177
|
+
)
|
|
178
|
+
this.dispatchEvent(evt)
|
|
179
|
+
} else if (type === SpatialWebMsgType.spatialrotateend) {
|
|
180
|
+
const evt = createSpatialEvent(
|
|
181
|
+
SpatialWebMsgType.spatialrotateend,
|
|
182
|
+
(data as SpatialRotateEndMsg).detail,
|
|
183
|
+
)
|
|
184
|
+
this.dispatchEvent(evt)
|
|
185
|
+
}
|
|
186
|
+
// magnify
|
|
187
|
+
else if (type === SpatialWebMsgType.spatialmagnifystart) {
|
|
188
|
+
const evt = createSpatialEvent(
|
|
189
|
+
SpatialWebMsgType.spatialmagnifystart,
|
|
190
|
+
(data as SpatialMagnifyMsg).detail,
|
|
191
|
+
)
|
|
192
|
+
this.dispatchEvent(evt)
|
|
193
|
+
} else if (type === SpatialWebMsgType.spatialmagnify) {
|
|
194
|
+
const evt = createSpatialEvent(
|
|
195
|
+
SpatialWebMsgType.spatialmagnify,
|
|
196
|
+
(data as SpatialMagnifyMsg).detail,
|
|
197
|
+
)
|
|
198
|
+
this.dispatchEvent(evt)
|
|
199
|
+
} else if (type === SpatialWebMsgType.spatialmagnifyend) {
|
|
200
|
+
const evt = createSpatialEvent(
|
|
201
|
+
SpatialWebMsgType.spatialmagnifyend,
|
|
202
|
+
(data as SpatialMagnifyMsg).detail,
|
|
203
|
+
)
|
|
204
|
+
this.dispatchEvent(evt)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
dispatchEvent(evt: CustomEvent) {
|
|
209
|
+
// Set origin once at the first dispatch in the bubbling chain
|
|
210
|
+
if (!(evt as any).__origin) {
|
|
211
|
+
Object.defineProperty(evt, '__origin', { value: this, enumerable: false })
|
|
212
|
+
}
|
|
213
|
+
this.events[evt.type]?.(evt)
|
|
214
|
+
if (evt.bubbles && !evt.cancelBubble) {
|
|
215
|
+
if (this.parent && this.parent instanceof SpatialEntity) {
|
|
216
|
+
this.parent.dispatchEvent(evt)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
protected onDestroy(): void {
|
|
222
|
+
SpatialWebEvent.removeEventReceiver(this.id)
|
|
223
|
+
// handle children
|
|
224
|
+
this.children.forEach(child => {
|
|
225
|
+
child.parent = null
|
|
226
|
+
})
|
|
227
|
+
this.children = []
|
|
228
|
+
// handle parent
|
|
229
|
+
if (this.parent) {
|
|
230
|
+
this.parent.children = this.parent.children.filter(
|
|
231
|
+
child => child.id !== this.id,
|
|
232
|
+
)
|
|
233
|
+
this.parent = null
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// onUpdate(properties: SpatialEntityProperties) {
|
|
237
|
+
// this.position = properties.position
|
|
238
|
+
// this.rotation = properties.rotation
|
|
239
|
+
// this.scale = properties.scale
|
|
240
|
+
// }
|
|
241
|
+
async convertFromEntityToEntity(
|
|
242
|
+
fromEntityId: string,
|
|
243
|
+
toEntityId: string,
|
|
244
|
+
position: Vec3,
|
|
245
|
+
) {
|
|
246
|
+
return new ConvertFromEntityToEntityCommand(
|
|
247
|
+
fromEntityId,
|
|
248
|
+
toEntityId,
|
|
249
|
+
position,
|
|
250
|
+
).execute()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async convertFromEntityToScene(fromEntityId: string, position: Vec3) {
|
|
254
|
+
return new ConvertFromEntityToSceneCommand(fromEntityId, position).execute()
|
|
255
|
+
}
|
|
256
|
+
async convertFromSceneToEntity(entityId: string, position: Vec3) {
|
|
257
|
+
return new ConvertFromSceneToEntityCommand(entityId, position).execute()
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SpatialEntityUserData,
|
|
3
|
+
SpatialModelEntityCreationOptions,
|
|
4
|
+
} from '../../types/types'
|
|
5
|
+
import { SpatialEntity } from './SpatialEntity'
|
|
6
|
+
|
|
7
|
+
export class SpatialModelEntity extends SpatialEntity {
|
|
8
|
+
constructor(
|
|
9
|
+
public id: string,
|
|
10
|
+
public options?: SpatialModelEntityCreationOptions,
|
|
11
|
+
public userData?: SpatialEntityUserData,
|
|
12
|
+
) {
|
|
13
|
+
super(id, userData)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SpatialBoxGeometryOptions, SpatialGeometryType } from '../../types/types'
|
|
2
|
+
import { SpatialGeometry } from './SpatialGeometry'
|
|
3
|
+
|
|
4
|
+
export class SpatialBoxGeometry extends SpatialGeometry {
|
|
5
|
+
static type: SpatialGeometryType = 'BoxGeometry'
|
|
6
|
+
constructor(
|
|
7
|
+
public id: string,
|
|
8
|
+
public options: SpatialBoxGeometryOptions,
|
|
9
|
+
) {
|
|
10
|
+
super(id, options)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SpatialGeometryType,
|
|
3
|
+
SpatialConeGeometryOptions,
|
|
4
|
+
} from '../../types/types'
|
|
5
|
+
import { SpatialGeometry } from './SpatialGeometry'
|
|
6
|
+
|
|
7
|
+
export class SpatialConeGeometry extends SpatialGeometry {
|
|
8
|
+
static type: SpatialGeometryType = 'ConeGeometry'
|
|
9
|
+
constructor(
|
|
10
|
+
public id: string,
|
|
11
|
+
public options: SpatialConeGeometryOptions,
|
|
12
|
+
) {
|
|
13
|
+
super(id, options)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SpatialGeometryType,
|
|
3
|
+
SpatialCylinderGeometryOptions,
|
|
4
|
+
} from '../../types/types'
|
|
5
|
+
import { SpatialGeometry } from './SpatialGeometry'
|
|
6
|
+
|
|
7
|
+
export class SpatialCylinderGeometry extends SpatialGeometry {
|
|
8
|
+
static type: SpatialGeometryType = 'CylinderGeometry'
|
|
9
|
+
constructor(
|
|
10
|
+
public id: string,
|
|
11
|
+
public options: SpatialCylinderGeometryOptions,
|
|
12
|
+
) {
|
|
13
|
+
super(id, options)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SpatialObject } from '../../SpatialObject'
|
|
2
|
+
import { SpatialGeometryOptions, SpatialGeometryType } from '../../types/types'
|
|
3
|
+
|
|
4
|
+
export class SpatialGeometry extends SpatialObject {
|
|
5
|
+
static type: SpatialGeometryType
|
|
6
|
+
constructor(
|
|
7
|
+
public id: string,
|
|
8
|
+
public options: SpatialGeometryOptions,
|
|
9
|
+
) {
|
|
10
|
+
super(id)
|
|
11
|
+
}
|
|
12
|
+
}
|