@threlte/extras
Version:
Utilities, abstractions and plugins for your Threlte apps
58 lines (57 loc) • 2.43 kB
JavaScript
import { currentWritable, useDOM } from '@threlte/core';
import { getContext, setContext } from 'svelte';
import { Raycaster, Vector2 } from 'three';
import { getDefaultComputeFunction } from './defaults.svelte.js';
const contextKey = Symbol('interactivity-context');
export const getInteractivityContext = () => {
return getContext(contextKey);
};
export const setInteractivityContext = (options) => {
const target = currentWritable(options?.target ?? useDOM().dom);
const context = {
enabled: currentWritable(options?.enabled ?? true),
pointer: currentWritable(new Vector2()),
pointerOverTarget: currentWritable(false),
lastEvent: undefined,
raycaster: new Raycaster(),
initialClick: [0, 0],
initialClickTime: 0,
initialHits: [],
hovered: new Map(),
interactiveObjects: [],
target,
handlers: new WeakMap(),
compute: options?.compute ?? getDefaultComputeFunction(target),
filter: options?.filter,
clickDistanceThreshold: options?.clickDistanceThreshold ?? 8,
clickTimeThreshold: options?.clickTimeThreshold ?? Number.POSITIVE_INFINITY,
eventOptions: options?.eventOptions,
addInteractiveObject: (object, events) => {
// Always update handlers so re-registration picks up new callbacks,
// even if the object is already in the list.
context.handlers.set(object, events);
if (context.interactiveObjects.indexOf(object) === -1) {
context.interactiveObjects.push(object);
}
},
removeInteractiveObject: (object) => {
const index = context.interactiveObjects.indexOf(object);
// Guard against double-removal: indexOf returns -1 when the object
// isn't in the list, and splice(-1, 1) would silently remove the
// last element — corrupting an unrelated registration.
if (index === -1)
return;
context.interactiveObjects.splice(index, 1);
context.handlers.delete(object);
}
};
setContext(contextKey, context);
return context;
};
export const useInteractivity = () => {
const context = getInteractivityContext();
if (!context) {
throw new Error('No interactivity context found. Did you forget to implement interactivity()?');
}
return context;
};