Skip to content

Commit c692a68

Browse files
authored
Cursor pos snippets (#540)
* cursor pos in the UI * raycast snippet
1 parent 85de9af commit c692a68

File tree

2 files changed

+127
-7
lines changed

2 files changed

+127
-7
lines changed

content/creator/sdk7/interactivity/raycasting.md

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,18 @@ raycastSystem.registerLocalDirectionRaycast(
194194
```
195195

196196
{{< hint warning >}}
197-
**📔 Note**: You can get a raycast result from hitting an entity on a different scene. This may be especially useful when creating portable experiences or smart wearables, that can react to the surroundings.
198-
199-
However, note that currently you can only obtain raycast responses when the collision is with conent in a scene done with SDK7. Older SDK6 scenes won't return any hit result.
197+
**📔 Note**: You can get a raycast result from hitting an entity on a different scene.
200198
{{< /hint >}}
201199

200+
## Handle hit entities
201+
202+
When you get a raycast result that hit an entity, you can use the `entityId` to interact with the entity and its components. An entity is [nothing more than a number]({{< ref "/content/creator/sdk7/architecture/entities-components.md#overview" >}}), so the `entityId` value itself can be interpreted as an `Entity` type.
203+
204+
```ts
205+
const hitEntity = result.entityId as Entity
206+
const transform = Transform.get(entity)
207+
console.log(transform.position)
208+
```
202209

203210
## Collision layers
204211

@@ -384,6 +391,74 @@ raycastSystem.registerGlobalDirectionRaycast(
384391
**📔 Note**: Keep in mind that in 3rd person the cursor could in the future not behave the same as in 1st person. It's recommended to only use this if the player is in 1st person.
385392
{{< /hint >}}
386393

394+
## Raycast from the cursor position
395+
396+
You can also trace a ray from the player's cursor position into the 3D world. This can be used to drag objects around, shooters, etc.
397+
398+
```ts
399+
import { engine, Entity, InputAction, inputSystem, PointerEventType, RaycastQueryType, raycastSystem, TextShape, Transform } from '@dcl/sdk/ecs'
400+
import { EntityNames } from '../assets/scene/entity-names'
401+
import { PrimaryPointerInfo } from '@dcl/sdk/ecs'
402+
403+
let cooldown = 1
404+
let rayFrequency = 0.1
405+
let mousePressed = false
406+
407+
export function main() {
408+
engine.addSystem(rayCastSystem)
409+
}
410+
411+
const rayCastSystem = (t: number) => {
412+
413+
if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)) {
414+
mousePressed = true
415+
}
416+
417+
if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_UP)) {
418+
mousePressed = false
419+
}
420+
421+
if (!mousePressed) {
422+
cooldown = 0
423+
raycastSystem.removeRaycasterEntity(engine.CameraEntity)
424+
return
425+
}
426+
427+
cooldown += t
428+
if (cooldown > rayFrequency) return
429+
cooldown = 0
430+
431+
const pointerInfo = PrimaryPointerInfo.getOrCreateMutable(engine.RootEntity)
432+
let dir = pointerInfo.worldRayDirection
433+
434+
raycastSystem.registerGlobalDirectionRaycast(
435+
{
436+
entity: engine.CameraEntity,
437+
opts: {
438+
queryType: RaycastQueryType.RQT_HIT_FIRST,
439+
direction: dir,
440+
},
441+
},
442+
function (raycastResult) {
443+
let result = raycastResult.hits[0]
444+
445+
// do something in the hit position
446+
if (result && result.position) {
447+
console.log("x:", result.position.x, ", y:", result.position.y, ", z:", result.position.z)
448+
}
449+
450+
// do something with the hit entity
451+
const entity = result.entityId as Entity
452+
if (entity) {
453+
console.log("entity: ", entity)
454+
}
455+
}
456+
)
457+
}
458+
459+
```
460+
461+
387462
## Advanced syntax
388463

389464
### Create a raycast component

content/creator/sdk7/interactivity/user-data.md

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,17 +435,62 @@ The `primaryPointerInfo` component returns an object with the following properti
435435
- `pointerType`: 0 for `none`, 1 for `mouse`
436436

437437

438-
You can use the `worldRayDirection` to set the `direction` field of a raycast to know if an entity is in the cursor's line of sight. See [Raycasting]({{< ref "/content/creator/sdk7/interactivity/raycasting.md" >}}) for more details.
439-
440-
441438
{{< hint info >}}
442439
**💡 Tip**: To react to simple hover events on UI elements, you may find it easier to use the `onMouseEnter` and `onMouseLeave` events, see [UI Button Events]({{< ref "/content/creator/sdk7/2d-ui/ui_button_events.md#hover-feedback" >}}).
443440
{{< /hint >}}
444441

445442

443+
The `primaryPointerInfo` component is read-only, you can't force the player to change the cursor position.
446444

447445

448-
The `primaryPointerInfo` component is read-only, you can't force the player to change the cursor position.
446+
The following example shows how to display the cursor position on a UI element.
447+
448+
449+
_**ui.tsx file:**_
450+
```tsx
451+
import { UiEntity, ReactEcs } from '@dcl/sdk/react-ecs'
452+
import { Color4 } from '@dcl/sdk/math'
453+
import {cursorXpos, cursorYpos} from './index'
454+
455+
export const uiMenu = () => (
456+
<UiEntity
457+
uiTransform={{
458+
width: '100%',
459+
height: '100px',
460+
justifyContent: 'center',
461+
alignItems: 'center',
462+
}}
463+
uiText={{ value: `Cursor pos: `+ cursorXpos + `,` + cursorYpos, fontSize: 40 }}
464+
uiBackground={{ color: Color4.create(0.5, 0.8, 0.1, 0.6) }}
465+
/>
466+
)
467+
```
468+
469+
_**index.ts file:**_
470+
```ts
471+
import { engine } from '@dcl/sdk/ecs'
472+
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
473+
import { uiMenu } from './ui'
474+
475+
export function main() {
476+
ReactEcsRenderer.setUiRenderer(uiMenu)
477+
}
478+
479+
export let cursorXpos: number | undefined = undefined
480+
export let cursorYpos: number | undefined = undefined
481+
482+
function CursorSystem() {
483+
const pointerInfo = PrimaryPointerInfo.get(engine.RootEntity)
484+
console.log(pointerInfo)
485+
486+
cursorXpos = pointerInfo.screenCoordinates?.x
487+
cursorYpos = pointerInfo.screenCoordinates?.y
488+
}
489+
490+
engine.addSystem(CursorSystem)
491+
```
492+
493+
You can use the `worldRayDirection` to set the `direction` field of a raycast to know if an entity is in the cursor's line of sight. See [Raycasting]({{< ref "/content/creator/sdk7/interactivity/raycasting.md" >}}) for more details.
449494

450495

451496

0 commit comments

Comments
 (0)