Skip to content

Commit 7071be0

Browse files
committed
fix: add pointerEvents prop to control raycasting behavior
- Add pointerEvents prop that when set to false prevents Object3D from being raycast, but it can still propagate events from descendants - Type isInstance helper with generic parameter for better type safety
1 parent 10399b3 commit 7071be0

4 files changed

Lines changed: 25 additions & 18 deletions

File tree

src/create-events.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,16 @@ function raycast<TNativeEvent extends MouseEvent | WheelEvent>(
108108
context.raycaster.setFromCamera(context.pointer, context.camera)
109109

110110
const nodeSet = new Set<Object3D>()
111+
const visitedSet = new Set<Object3D>()
111112
const stack = [...registry]
112113

113114
// Collect all unique descendants of registry
114115
for (const object of stack) {
115-
if (nodeSet.has(object)) continue
116-
nodeSet.add(object)
116+
if (visitedSet.has(object)) continue
117+
visitedSet.add(object)
118+
if (isInstance(object) && object[$S3C].props?.pointerEvents !== false) {
119+
nodeSet.add(object)
120+
}
117121
stack.push(...object.children)
118122
}
119123

src/props.ts

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,21 +86,19 @@ export function manageProps<T extends object>(object: Accessor<T>, props: any) {
8686
/**********************************************************************************/
8787

8888
export function applyProps<T>(object: T, props: any) {
89-
createRenderEffect(() => {
90-
const keys = Object.keys(props)
91-
for (const key of keys) {
92-
// An array of sub-property-keys:
93-
// p.ex in <T.Mesh position={} position-x={}/> position's subKeys will be ['position-x']
94-
const subKeys = keys.filter(_key => key !== _key && _key.includes(key))
95-
createRenderEffect(() => {
96-
applyProp(object, key, props[key])
97-
// If property updates, apply its sub-properties immediately after.
98-
for (const subKey of subKeys) {
99-
applyProp(object, subKey, props[subKey])
100-
}
101-
})
102-
}
103-
})
89+
const keys = Object.keys(props)
90+
for (const key of keys) {
91+
// An array of sub-property-keys:
92+
// p.ex in <T.Mesh position={} position-x={}/> position's subKeys will be ['position-x']
93+
const subKeys = keys.filter(_key => key !== _key && _key.includes(key))
94+
createRenderEffect(() => {
95+
applyProp(object, key, props[key])
96+
// If property updates, apply its sub-properties immediately after.
97+
for (const subKey of subKeys) {
98+
applyProp(object, subKey, props[subKey])
99+
}
100+
})
101+
}
104102
}
105103

106104
/**********************************************************************************/

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ export type ClassProps<T> = Partial<
169169
) => () => void)
170170
children?: JSX.Element
171171
onUpdate: (self: Instance<InstanceFromConstructor<T>>) => void
172+
/**
173+
* Prevents the Object3D from being cast by the ray.
174+
* Object3D can still receive events via propagation from its descendants.
175+
*/
176+
pointerEvents: boolean
172177
} & EventHandlers
173178
>
174179
>

src/utils/is-instance.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Instance } from "src/types.ts"
22
import { $S3C } from "../constants.ts"
33

4-
export const isInstance = (element: any): element is Instance =>
4+
export const isInstance = <T extends object>(element: T): element is Instance<T> =>
55
typeof element === "object" && $S3C in element

0 commit comments

Comments
 (0)