diff --git a/packages/fiber/src/core/events.ts b/packages/fiber/src/core/events.ts index d64a3a4377..554f9897ce 100644 --- a/packages/fiber/src/core/events.ts +++ b/packages/fiber/src/core/events.ts @@ -245,7 +245,17 @@ export function createEvents(store: RootStore) { if (intersections.length) { const localState = { stopped: false } for (const hit of intersections) { - const state = getRootState(hit.object) + let state = getRootState(hit.object) + + if (!state) + hit.object.traverseAncestors((obj) => { + const _state = getRootState(obj) + if (_state) { + state = _state + return false + } + }) + if (state) { const { raycaster, pointer, camera, internal } = state const unprojectedPoint = new THREE.Vector3(pointer.x, pointer.y, 0).unproject(camera) diff --git a/packages/fiber/src/core/utils.tsx b/packages/fiber/src/core/utils.tsx index 3ff69262fa..d72fefb2b1 100644 --- a/packages/fiber/src/core/utils.tsx +++ b/packages/fiber/src/core/utils.tsx @@ -372,8 +372,10 @@ export function applyProps(object: Instance['object'], props: Instan // Don't mutate reserved keys if (RESERVED_PROPS.includes(prop)) continue + const isEvent = /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(prop) + // Deal with pointer events, including removing them if undefined - if (instance && /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(prop)) { + if (instance && isEvent) { if (typeof value === 'function') instance.handlers[prop as keyof EventHandlers] = value as any else delete instance.handlers[prop as keyof EventHandlers] instance.eventCount = Object.keys(instance.handlers).length @@ -429,7 +431,8 @@ export function applyProps(object: Instance['object'], props: Instan } // Else, just overwrite the value else { - root[key] = value + // Don't write events to the object + if (!isEvent) root[key] = value // Auto-convert sRGB textures, for now ... // https://github.com/pmndrs/react-three-fiber/issues/344 @@ -447,17 +450,12 @@ export function applyProps(object: Instance['object'], props: Instan } } - if ( - instance?.parent && - rootState?.internal && - instance.object instanceof THREE.Object3D && - prevHandlers !== instance.eventCount - ) { + if (instance && rootState?.internal && isObject3D(instance.object) && prevHandlers !== instance.eventCount) { // Pre-emptively remove the instance from the interaction manager const index = rootState.internal.interaction.indexOf(instance.object) if (index > -1) rootState.internal.interaction.splice(index, 1) // Add the instance to the interaction manager only when it has handlers - if (instance.eventCount && instance.object.raycast !== null && instance.object instanceof THREE.Object3D) { + if (instance.eventCount && instance.object.raycast !== null && isObject3D(instance.object)) { rootState.internal.interaction.push(instance.object) } }