@dcl/playground-assets 7.0.5-3640831568.commit-60f39b0 → 7.0.5-3649654995.commit-ad4efbc
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/dist/alpha.d.ts +5181 -0
- package/dist/beta.d.ts +5181 -0
- package/dist/index.bundled.d.ts +5181 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +40563 -0
- package/dist/index.js.map +1 -0
- package/dist/index.min.js +1 -0
- package/dist/index.min.js.map +1 -0
- package/dist/playground/sdk/apis.d.ts +666 -0
- package/dist/playground/sdk/dcl-sdk.package.json +29 -0
- package/dist/playground/snippets/billboard.ts +121 -0
- package/dist/playground/snippets/cube-spawner.ts +50 -0
- package/dist/playground/snippets/info.json +1 -0
- package/dist/playground/snippets/material.ts +57 -0
- package/dist/playground/snippets/mesh.ts +70 -0
- package/dist/playground/snippets/pointer-events.ts +62 -0
- package/dist/playground/snippets/raycast-hit-many.ts +78 -0
- package/dist/playground/snippets/raycast-hit.ts +75 -0
- package/dist/playground/snippets/ui.tsx +143 -0
- package/dist/playground-assets.d.ts +5193 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/package.json +7 -3
- package/api-extractor.json +0 -357
- package/src/index.ts +0 -20
- package/tsconfig.json +0 -20
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
engine,
|
|
4
|
+
Material,
|
|
5
|
+
Transform,
|
|
6
|
+
MeshRenderer,
|
|
7
|
+
Billboard,
|
|
8
|
+
BillboardMode,
|
|
9
|
+
TextShape,
|
|
10
|
+
Schemas
|
|
11
|
+
} from '@dcl/sdk/ecs'
|
|
12
|
+
import { Vector3, Color3, Color4 } from '@dcl/sdk/math'
|
|
13
|
+
|
|
14
|
+
function createPlaneTexture(x: number, y: number, z: number): Entity {
|
|
15
|
+
const meshEntity = engine.addEntity()
|
|
16
|
+
|
|
17
|
+
Material.create(meshEntity, {
|
|
18
|
+
material: {
|
|
19
|
+
$case: 'pbr',
|
|
20
|
+
pbr: {
|
|
21
|
+
texture: {
|
|
22
|
+
tex: {
|
|
23
|
+
$case: 'texture',
|
|
24
|
+
texture: { src: 'models/polaroid2.png' }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
Transform.create(meshEntity, {
|
|
31
|
+
position: { x, y, z },
|
|
32
|
+
scale: Vector3.create(2, 2, 2)
|
|
33
|
+
})
|
|
34
|
+
MeshRenderer.create(meshEntity, {
|
|
35
|
+
mesh: {
|
|
36
|
+
$case: 'plane',
|
|
37
|
+
plane: {
|
|
38
|
+
uvs: [...Array.from({ length: 40 }, () => 0), 0, 1, 1, 1, 1, 0, 0, 0]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
return meshEntity
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createBillboards() {
|
|
46
|
+
const plane1 = createPlaneTexture(8, 3, 1)
|
|
47
|
+
const plane2 = createPlaneTexture(12, 3, 1)
|
|
48
|
+
createPlaneTexture(4, 3, 1)
|
|
49
|
+
|
|
50
|
+
const plane5 = createPlaneTexture(8, 3, 8)
|
|
51
|
+
const plane4 = createPlaneTexture(12, 3, 8)
|
|
52
|
+
createPlaneTexture(4, 3, 8)
|
|
53
|
+
|
|
54
|
+
Billboard.create(plane1, {
|
|
55
|
+
billboardMode: BillboardMode.BM_Y_AXE
|
|
56
|
+
})
|
|
57
|
+
Billboard.create(plane2)
|
|
58
|
+
Billboard.create(plane4, {
|
|
59
|
+
oppositeDirection: true,
|
|
60
|
+
billboardMode: BillboardMode.BM_ALL_AXES
|
|
61
|
+
})
|
|
62
|
+
Billboard.create(plane5, {
|
|
63
|
+
oppositeDirection: true,
|
|
64
|
+
billboardMode: BillboardMode.BM_Y_AXE
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function createTextShape(text: string, position: Vector3, textColor: Color4) {
|
|
69
|
+
const entity = engine.addEntity()
|
|
70
|
+
Transform.create(entity, { position })
|
|
71
|
+
return TextShape.create(entity, {
|
|
72
|
+
text,
|
|
73
|
+
fontSize: 3,
|
|
74
|
+
outlineWidth: 0.1,
|
|
75
|
+
outlineColor: Color3.Black(),
|
|
76
|
+
textColor
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function createTextShapes() {
|
|
81
|
+
const regularColor = Color4.create(1, 0.2, 0.8, 0.8)
|
|
82
|
+
const oppositeColor = Color4.create(0.8, 0.2, 1, 0.8)
|
|
83
|
+
|
|
84
|
+
createTextShape(
|
|
85
|
+
'Regular, only Y-rotation',
|
|
86
|
+
Vector3.create(8, 1, 1),
|
|
87
|
+
regularColor
|
|
88
|
+
)
|
|
89
|
+
createTextShape('Regular', Vector3.create(12, 1, 1), regularColor)
|
|
90
|
+
createTextShape('Without billboard', Vector3.create(4, 1, 1), regularColor)
|
|
91
|
+
createTextShape('Opposite, only Y', Vector3.create(8, 1, 8), oppositeColor)
|
|
92
|
+
createTextShape('Opposite', Vector3.create(12, 1, 8), oppositeColor)
|
|
93
|
+
createTextShape('Without billboard', Vector3.create(4, 1, 8), oppositeColor)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
createBillboards()
|
|
97
|
+
createTextShapes()
|
|
98
|
+
|
|
99
|
+
const BouncingBillboard = engine.defineComponent(
|
|
100
|
+
{
|
|
101
|
+
t: Schemas.Number,
|
|
102
|
+
originalPosition: Schemas.Vector3
|
|
103
|
+
},
|
|
104
|
+
123123
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
engine.addSystem((dt: number) => {
|
|
108
|
+
for (const [entity] of engine.getEntitiesWith(Billboard, Transform)) {
|
|
109
|
+
if (BouncingBillboard.getOrNull(entity) === null) {
|
|
110
|
+
BouncingBillboard.create(entity, {
|
|
111
|
+
originalPosition: Transform.get(entity).position
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const bounce = BouncingBillboard.getMutable(entity)
|
|
116
|
+
bounce.t += dt
|
|
117
|
+
|
|
118
|
+
Transform.getMutable(entity).position.y =
|
|
119
|
+
bounce.originalPosition.y + 0.05 * Math.sin(10 * bounce.t)
|
|
120
|
+
}
|
|
121
|
+
})
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
engine,
|
|
4
|
+
pointerEventsSystem,
|
|
5
|
+
Transform,
|
|
6
|
+
MeshRenderer,
|
|
7
|
+
MeshCollider,
|
|
8
|
+
InputAction
|
|
9
|
+
} from '@dcl/sdk/ecs'
|
|
10
|
+
import { Quaternion, Vector3 } from '@dcl/sdk/math'
|
|
11
|
+
|
|
12
|
+
// Cube factory
|
|
13
|
+
function createCube(x: number, y: number, z: number): Entity {
|
|
14
|
+
const meshEntity = engine.addEntity()
|
|
15
|
+
Transform.create(meshEntity, { position: { x, y, z } })
|
|
16
|
+
MeshRenderer.create(meshEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
|
|
17
|
+
MeshCollider.create(meshEntity, { mesh: { $case: 'box', box: {} } })
|
|
18
|
+
|
|
19
|
+
return meshEntity
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Systems
|
|
23
|
+
function circularSystem(dt: number) {
|
|
24
|
+
const entitiesWithMeshRenderer = engine.getEntitiesWith(
|
|
25
|
+
MeshRenderer,
|
|
26
|
+
Transform
|
|
27
|
+
)
|
|
28
|
+
for (const [entity, _meshRenderer, _transform] of entitiesWithMeshRenderer) {
|
|
29
|
+
const mutableTransform = Transform.getMutable(entity)
|
|
30
|
+
|
|
31
|
+
mutableTransform.rotation = Quaternion.multiply(
|
|
32
|
+
mutableTransform.rotation,
|
|
33
|
+
Quaternion.fromAngleAxis(dt * 10, Vector3.Up())
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Init
|
|
39
|
+
const initEntity = createCube(8, 1, 8)
|
|
40
|
+
pointerEventsSystem.onPointerDown(
|
|
41
|
+
initEntity,
|
|
42
|
+
() => {
|
|
43
|
+
createCube(1 + Math.random() * 8, Math.random() * 8, 1 + Math.random() * 8)
|
|
44
|
+
},
|
|
45
|
+
{ button: InputAction.IA_PRIMARY, hoverText: 'Press E to spawn' }
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
engine.addSystem(circularSystem)
|
|
49
|
+
|
|
50
|
+
export {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"name":"Billboard","category":"sample","path":"billboard.ts"},{"name":"Cube Spawner","category":"sample","path":"cube-spawner.ts"},{"name":"Material","category":"component","path":"material.ts"},{"name":"Mesh","category":"component","path":"mesh.ts"},{"name":"Pointer Events","category":"sample","path":"pointer-events.ts"},{"name":"Raycast Hit","category":"component","path":"raycast-hit.ts"},{"name":"Raycast Hit many","category":"sample","path":"raycast-hit-many.ts"},{"name":"Container","category":"ui","path":"ui.tsx"}]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
engine,
|
|
4
|
+
Transform,
|
|
5
|
+
MeshRenderer,
|
|
6
|
+
Material,
|
|
7
|
+
MaterialTransparencyMode
|
|
8
|
+
} from '@dcl/sdk/ecs'
|
|
9
|
+
|
|
10
|
+
function createSphere(x: number, y: number, z: number): Entity {
|
|
11
|
+
const meshEntity = engine.addEntity()
|
|
12
|
+
Transform.create(meshEntity, { position: { x, y, z } })
|
|
13
|
+
MeshRenderer.create(meshEntity, { mesh: { $case: 'sphere', sphere: {} } })
|
|
14
|
+
return meshEntity
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Material.create(createSphere(15, 1, 15), {
|
|
18
|
+
material: {
|
|
19
|
+
$case: 'pbr',
|
|
20
|
+
pbr: {
|
|
21
|
+
albedoColor: { r: 0, g: 0, b: 1 },
|
|
22
|
+
reflectivityColor: { r: 0.5, g: 0.5, b: 0.5 },
|
|
23
|
+
metallic: 0.8,
|
|
24
|
+
roughness: 0.1
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
Material.create(createSphere(13, 1, 15), {
|
|
30
|
+
material: {
|
|
31
|
+
$case: 'pbr',
|
|
32
|
+
pbr: {
|
|
33
|
+
albedoColor: { r: 1, g: 1, b: 0 },
|
|
34
|
+
reflectivityColor: { r: 0.5, g: 0.5, b: 0.5 },
|
|
35
|
+
metallic: 0.1,
|
|
36
|
+
roughness: 0.8,
|
|
37
|
+
|
|
38
|
+
alphaTest: 0.2,
|
|
39
|
+
transparencyMode: MaterialTransparencyMode.MTM_ALPHA_TEST
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
Material.create(createSphere(11, 1, 15), {
|
|
45
|
+
material: {
|
|
46
|
+
$case: 'pbr',
|
|
47
|
+
pbr: {
|
|
48
|
+
albedoColor: { r: 0, g: 0, b: 1 },
|
|
49
|
+
reflectivityColor: { r: 0.5, g: 0.5, b: 0.5 },
|
|
50
|
+
metallic: 0.1,
|
|
51
|
+
roughness: 0.1
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// add textures
|
|
57
|
+
export {}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { engine, Transform, MeshRenderer, MeshCollider } from '@dcl/sdk/ecs'
|
|
2
|
+
|
|
3
|
+
enum Mesh {
|
|
4
|
+
BOX,
|
|
5
|
+
CYLINDER,
|
|
6
|
+
SPHERE,
|
|
7
|
+
CONE
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function createMesh(
|
|
11
|
+
x: number,
|
|
12
|
+
y: number,
|
|
13
|
+
z: number,
|
|
14
|
+
mesh: Mesh,
|
|
15
|
+
withCollider: boolean = false
|
|
16
|
+
) {
|
|
17
|
+
const meshEntity = engine.addEntity()
|
|
18
|
+
Transform.create(meshEntity, { position: { x, y, z } })
|
|
19
|
+
|
|
20
|
+
switch (mesh) {
|
|
21
|
+
case Mesh.BOX:
|
|
22
|
+
MeshRenderer.create(meshEntity, {
|
|
23
|
+
mesh: { $case: 'box', box: { uvs: [] } }
|
|
24
|
+
})
|
|
25
|
+
if (withCollider)
|
|
26
|
+
MeshCollider.create(meshEntity, { mesh: { $case: 'box', box: {} } })
|
|
27
|
+
break
|
|
28
|
+
case Mesh.SPHERE:
|
|
29
|
+
MeshRenderer.create(meshEntity, { mesh: { $case: 'sphere', sphere: {} } })
|
|
30
|
+
if (withCollider)
|
|
31
|
+
MeshCollider.create(meshEntity, {
|
|
32
|
+
mesh: { $case: 'sphere', sphere: {} }
|
|
33
|
+
})
|
|
34
|
+
break
|
|
35
|
+
case Mesh.CONE:
|
|
36
|
+
case Mesh.CYLINDER:
|
|
37
|
+
MeshRenderer.create(meshEntity, {
|
|
38
|
+
mesh: {
|
|
39
|
+
$case: 'cylinder',
|
|
40
|
+
cylinder: {
|
|
41
|
+
radiusBottom: 1,
|
|
42
|
+
radiusTop: mesh === Mesh.CONE ? 0 : 1
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
if (withCollider)
|
|
47
|
+
MeshCollider.create(meshEntity, {
|
|
48
|
+
mesh: {
|
|
49
|
+
$case: 'cylinder',
|
|
50
|
+
cylinder: {
|
|
51
|
+
radiusBottom: 1,
|
|
52
|
+
radiusTop: mesh === Mesh.CONE ? 0 : 1
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
break
|
|
57
|
+
}
|
|
58
|
+
return meshEntity
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
createMesh(15, 1, 15, Mesh.BOX)
|
|
62
|
+
createMesh(12, 1, 15, Mesh.CONE)
|
|
63
|
+
createMesh(9, 1, 15, Mesh.SPHERE)
|
|
64
|
+
createMesh(6, 1, 15, Mesh.CYLINDER)
|
|
65
|
+
createMesh(15, 1, 1, Mesh.BOX, true)
|
|
66
|
+
createMesh(12, 1, 1, Mesh.CONE, true)
|
|
67
|
+
createMesh(9, 1, 1, Mesh.SPHERE, true)
|
|
68
|
+
createMesh(6, 1, 1, Mesh.CYLINDER, true)
|
|
69
|
+
|
|
70
|
+
export {}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
engine,
|
|
4
|
+
Transform,
|
|
5
|
+
MeshRenderer,
|
|
6
|
+
MeshCollider,
|
|
7
|
+
InputAction,
|
|
8
|
+
PBPointerHoverFeedback_Entry,
|
|
9
|
+
PointerHoverFeedback,
|
|
10
|
+
PointerEventType
|
|
11
|
+
} from '@dcl/sdk/ecs'
|
|
12
|
+
|
|
13
|
+
// Cube factory
|
|
14
|
+
function createCube(
|
|
15
|
+
x: number,
|
|
16
|
+
y: number,
|
|
17
|
+
z: number,
|
|
18
|
+
pointerEvents: PBPointerHoverFeedback_Entry[]
|
|
19
|
+
): Entity {
|
|
20
|
+
const meshEntity = engine.addEntity()
|
|
21
|
+
Transform.create(meshEntity, { position: { x, y, z } })
|
|
22
|
+
MeshRenderer.create(meshEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
|
|
23
|
+
MeshCollider.create(meshEntity, { mesh: { $case: 'box', box: {} } })
|
|
24
|
+
PointerHoverFeedback.create(meshEntity, { pointerEvents })
|
|
25
|
+
return meshEntity
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
createCube(15, 1, 15, [
|
|
29
|
+
{
|
|
30
|
+
eventType: PointerEventType.PET_DOWN,
|
|
31
|
+
eventInfo: {
|
|
32
|
+
button: InputAction.IA_PRIMARY,
|
|
33
|
+
hoverText: 'PrimaryDown',
|
|
34
|
+
maxDistance: 5,
|
|
35
|
+
showFeedback: true
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
])
|
|
39
|
+
|
|
40
|
+
createCube(13, 1, 15, [
|
|
41
|
+
{
|
|
42
|
+
eventType: PointerEventType.PET_UP,
|
|
43
|
+
eventInfo: {
|
|
44
|
+
button: InputAction.IA_SECONDARY,
|
|
45
|
+
hoverText: 'Secondary Up',
|
|
46
|
+
maxDistance: 5,
|
|
47
|
+
showFeedback: true
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
])
|
|
51
|
+
|
|
52
|
+
createCube(11, 1, 15, [
|
|
53
|
+
{
|
|
54
|
+
eventType: PointerEventType.PET_HOVER_ENTER,
|
|
55
|
+
eventInfo: {
|
|
56
|
+
button: InputAction.IA_ANY,
|
|
57
|
+
hoverText: 'Infinity Hover',
|
|
58
|
+
maxDistance: 10000000,
|
|
59
|
+
showFeedback: true
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
])
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
engine,
|
|
3
|
+
Transform,
|
|
4
|
+
MeshRenderer,
|
|
5
|
+
MeshCollider,
|
|
6
|
+
InputAction,
|
|
7
|
+
pointerEventsSystem,
|
|
8
|
+
Raycast,
|
|
9
|
+
RaycastQueryType,
|
|
10
|
+
RaycastResult
|
|
11
|
+
} from '@dcl/sdk/ecs'
|
|
12
|
+
import { Vector3 } from '@dcl/sdk/math'
|
|
13
|
+
|
|
14
|
+
function createCube(
|
|
15
|
+
x: number,
|
|
16
|
+
y: number,
|
|
17
|
+
z: number,
|
|
18
|
+
scaleMultiplier: number = 1
|
|
19
|
+
) {
|
|
20
|
+
const cubeEntity = engine.addEntity()
|
|
21
|
+
|
|
22
|
+
Transform.create(cubeEntity, {
|
|
23
|
+
position: { x, y, z },
|
|
24
|
+
scale: { x: scaleMultiplier, y: scaleMultiplier, z: scaleMultiplier }
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
MeshRenderer.create(cubeEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
|
|
28
|
+
MeshCollider.create(cubeEntity, { mesh: { $case: 'box', box: {} } })
|
|
29
|
+
|
|
30
|
+
return cubeEntity
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Create cube to hit
|
|
34
|
+
const cubeEntity = createCube(8, 1, 8)
|
|
35
|
+
const _cubeEntity2 = createCube(8, 1, 13)
|
|
36
|
+
const raycastEntity = engine.addEntity()
|
|
37
|
+
|
|
38
|
+
// Add OnPointerDown component to cube entity to trigger ray casting on interaction
|
|
39
|
+
pointerEventsSystem.onPointerDown(
|
|
40
|
+
cubeEntity,
|
|
41
|
+
() => {
|
|
42
|
+
Raycast.createOrReplace(raycastEntity, {
|
|
43
|
+
origin: Vector3.create(8, 1, 0.1),
|
|
44
|
+
direction: Vector3.create(0, 0, 1),
|
|
45
|
+
maxDistance: 16,
|
|
46
|
+
queryType: RaycastQueryType.RQT_QUERY_ALL
|
|
47
|
+
})
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
button: InputAction.IA_POINTER,
|
|
51
|
+
hoverText: 'CAST RAY'
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
// System to detect new raycast responses and instantiate a cube where the ray hits
|
|
56
|
+
let lastRaycastTimestamp = -1
|
|
57
|
+
engine.addSystem(() => {
|
|
58
|
+
for (const [_entity, result] of engine.getEntitiesWith(RaycastResult)) {
|
|
59
|
+
if (result.hits?.length === 0 || result.timestamp <= lastRaycastTimestamp)
|
|
60
|
+
continue
|
|
61
|
+
lastRaycastTimestamp = result.timestamp
|
|
62
|
+
|
|
63
|
+
if (result.hits[0] && result.hits[0].position) {
|
|
64
|
+
createCube(
|
|
65
|
+
result.hits[0].position.x,
|
|
66
|
+
result.hits[0].position.y,
|
|
67
|
+
result.hits[0].position.z,
|
|
68
|
+
0.3
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log(
|
|
73
|
+
`Hits (this should be '2' the first time): '${result.hits.length}'`
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
export {}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
engine,
|
|
3
|
+
Transform,
|
|
4
|
+
MeshRenderer,
|
|
5
|
+
MeshCollider,
|
|
6
|
+
InputAction,
|
|
7
|
+
pointerEventsSystem,
|
|
8
|
+
Raycast,
|
|
9
|
+
RaycastQueryType,
|
|
10
|
+
RaycastResult
|
|
11
|
+
} from '@dcl/sdk/ecs'
|
|
12
|
+
import { Vector3 } from '@dcl/sdk/math'
|
|
13
|
+
|
|
14
|
+
function createCube(
|
|
15
|
+
x: number,
|
|
16
|
+
y: number,
|
|
17
|
+
z: number,
|
|
18
|
+
scaleMultiplier: number = 1
|
|
19
|
+
) {
|
|
20
|
+
const cubeEntity = engine.addEntity()
|
|
21
|
+
|
|
22
|
+
Transform.create(cubeEntity, {
|
|
23
|
+
position: { x, y, z },
|
|
24
|
+
scale: { x: scaleMultiplier, y: scaleMultiplier, z: scaleMultiplier }
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
MeshRenderer.create(cubeEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
|
|
28
|
+
MeshCollider.create(cubeEntity, { mesh: { $case: 'box', box: {} } })
|
|
29
|
+
|
|
30
|
+
return cubeEntity
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Create cube to hit
|
|
34
|
+
const cubeEntity = createCube(8, 1, 8)
|
|
35
|
+
const raycastEntity = engine.addEntity()
|
|
36
|
+
|
|
37
|
+
// Add OnPointerDown component to cube entity to trigger ray casting on interaction
|
|
38
|
+
pointerEventsSystem.onPointerDown(
|
|
39
|
+
cubeEntity,
|
|
40
|
+
() => {
|
|
41
|
+
Raycast.createOrReplace(raycastEntity, {
|
|
42
|
+
origin: Vector3.create(8, 1, 0.1),
|
|
43
|
+
direction: Vector3.create(0, 0, 1),
|
|
44
|
+
maxDistance: 16,
|
|
45
|
+
queryType: RaycastQueryType.RQT_HIT_FIRST
|
|
46
|
+
})
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
button: InputAction.IA_POINTER,
|
|
50
|
+
hoverText: 'CAST RAY'
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
// System to detect new raycast responses and instantiate a cube where the ray hits
|
|
55
|
+
let lastRaycastTimestamp = -1
|
|
56
|
+
engine.addSystem(() => {
|
|
57
|
+
for (const [_entity, result] of engine.getEntitiesWith(RaycastResult)) {
|
|
58
|
+
if (result.hits?.length === 0 || result.timestamp <= lastRaycastTimestamp)
|
|
59
|
+
continue
|
|
60
|
+
lastRaycastTimestamp = result.timestamp
|
|
61
|
+
|
|
62
|
+
if (result.hits[0] && result.hits[0].position) {
|
|
63
|
+
createCube(
|
|
64
|
+
result.hits[0].position.x,
|
|
65
|
+
result.hits[0].position.y,
|
|
66
|
+
result.hits[0].position.z,
|
|
67
|
+
0.3
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log(`Hits (this should be '1'): '${result.hits.length}'`)
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
export {}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
engine,
|
|
4
|
+
Transform,
|
|
5
|
+
MeshRenderer,
|
|
6
|
+
MeshCollider,
|
|
7
|
+
InputAction,
|
|
8
|
+
inputSystem,
|
|
9
|
+
PointerHoverFeedback,
|
|
10
|
+
YGAlign,
|
|
11
|
+
YGDisplay,
|
|
12
|
+
YGJustify,
|
|
13
|
+
PointerEventType
|
|
14
|
+
} from '@dcl/sdk/ecs'
|
|
15
|
+
import { Vector3, Color4, Quaternion } from '@dcl/sdk/math'
|
|
16
|
+
import ReactEcs, { UiEntity, ReactEcsRenderer } from '@dcl/sdk/react-ecs'
|
|
17
|
+
|
|
18
|
+
let counter = 0
|
|
19
|
+
|
|
20
|
+
export const uiComponent = () => (
|
|
21
|
+
<UiEntity
|
|
22
|
+
uiTransform={{
|
|
23
|
+
width: 700,
|
|
24
|
+
height: 400,
|
|
25
|
+
margin: { top: '35px', left: '500px' }
|
|
26
|
+
}}
|
|
27
|
+
uiBackground={{ backgroundColor: Color4.create(0.5, 0.8, 0.1, 0.6) }}
|
|
28
|
+
>
|
|
29
|
+
<UiEntity
|
|
30
|
+
uiTransform={{
|
|
31
|
+
width: '100%',
|
|
32
|
+
height: '20%',
|
|
33
|
+
justifyContent: YGJustify.YGJ_CENTER,
|
|
34
|
+
alignItems: YGAlign.YGA_CENTER,
|
|
35
|
+
display: YGDisplay.YGD_FLEX
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<UiEntity
|
|
39
|
+
uiText={{ value: 'SDK 7', fontSize: 80 }}
|
|
40
|
+
uiBackground={{ backgroundColor: Color4.fromHexString('#fbf0f0') }}
|
|
41
|
+
/>
|
|
42
|
+
</UiEntity>
|
|
43
|
+
<UiEntity
|
|
44
|
+
uiTransform={{
|
|
45
|
+
width: '100%',
|
|
46
|
+
height: '20%',
|
|
47
|
+
justifyContent: YGJustify.YGJ_CENTER,
|
|
48
|
+
alignItems: YGAlign.YGA_CENTER,
|
|
49
|
+
display: YGDisplay.YGD_FLEX
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
<UiEntity
|
|
53
|
+
uiText={{ value: `Counter: ${counter}`, fontSize: 60 }}
|
|
54
|
+
uiBackground={{ backgroundColor: Color4.fromHexString('#fbf0f0') }}
|
|
55
|
+
/>
|
|
56
|
+
</UiEntity>
|
|
57
|
+
<UiEntity
|
|
58
|
+
uiTransform={{
|
|
59
|
+
width: '100%',
|
|
60
|
+
height: '100px',
|
|
61
|
+
justifyContent: YGJustify.YGJ_CENTER,
|
|
62
|
+
alignItems: YGAlign.YGA_CENTER,
|
|
63
|
+
display: YGDisplay.YGD_FLEX
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<UiEntity
|
|
67
|
+
uiText={{ value: `Player: ${getPlayerPosition()}`, fontSize: 40 }}
|
|
68
|
+
uiBackground={{ backgroundColor: Color4.fromHexString('#fbf0f0') }}
|
|
69
|
+
/>
|
|
70
|
+
</UiEntity>
|
|
71
|
+
</UiEntity>
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
function getPlayerPosition() {
|
|
75
|
+
const playerPosition = Transform.getOrNull(engine.PlayerEntity)
|
|
76
|
+
if (!playerPosition) return ''
|
|
77
|
+
const { x, y, z } = playerPosition.position
|
|
78
|
+
return `{x: ${x.toFixed(2)}, y: ${y.toFixed(2)}, z: ${z.toFixed(2)} }`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
ReactEcsRenderer.setUiRenderer(uiComponent)
|
|
82
|
+
|
|
83
|
+
// Cube factory
|
|
84
|
+
function createCube(x: number, y: number, z: number, spawner = true): Entity {
|
|
85
|
+
const meshEntity = engine.addEntity()
|
|
86
|
+
Transform.create(meshEntity, { position: { x, y, z } })
|
|
87
|
+
MeshRenderer.create(meshEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
|
|
88
|
+
MeshCollider.create(meshEntity, { mesh: { $case: 'box', box: {} } })
|
|
89
|
+
if (spawner) {
|
|
90
|
+
PointerHoverFeedback.create(meshEntity, {
|
|
91
|
+
pointerEvents: [
|
|
92
|
+
{
|
|
93
|
+
eventType: PointerEventType.PET_DOWN,
|
|
94
|
+
eventInfo: {
|
|
95
|
+
button: InputAction.IA_PRIMARY,
|
|
96
|
+
hoverText: 'Press E to spawn',
|
|
97
|
+
maxDistance: 100,
|
|
98
|
+
showFeedback: true
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
return meshEntity
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Systems
|
|
108
|
+
function circularSystem(dt: number) {
|
|
109
|
+
const entitiesWithMeshRenderer = engine.getEntitiesWith(
|
|
110
|
+
MeshRenderer,
|
|
111
|
+
Transform
|
|
112
|
+
)
|
|
113
|
+
for (const [entity, _meshRenderer, _transform] of entitiesWithMeshRenderer) {
|
|
114
|
+
const mutableTransform = Transform.getMutable(entity)
|
|
115
|
+
|
|
116
|
+
mutableTransform.rotation = Quaternion.multiply(
|
|
117
|
+
mutableTransform.rotation,
|
|
118
|
+
Quaternion.fromAngleAxis(dt * 10, Vector3.Up())
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function spawnerSystem() {
|
|
124
|
+
const clickedCubes = engine.getEntitiesWith(PointerHoverFeedback)
|
|
125
|
+
for (const [entity] of clickedCubes) {
|
|
126
|
+
if (
|
|
127
|
+
inputSystem.isTriggered(
|
|
128
|
+
InputAction.IA_PRIMARY,
|
|
129
|
+
PointerEventType.PET_DOWN,
|
|
130
|
+
entity
|
|
131
|
+
)
|
|
132
|
+
) {
|
|
133
|
+
counter++
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Init
|
|
139
|
+
createCube(8, 1, 8)
|
|
140
|
+
engine.addSystem(circularSystem)
|
|
141
|
+
engine.addSystem(spawnerSystem)
|
|
142
|
+
|
|
143
|
+
export {}
|