UNPKG

@threlte/core

Version:

A 3D framework for the web, built on top of Svelte and Three.js

86 lines (85 loc) 2.56 kB
import { getContext, setContext } from 'svelte'; export const shallowEqualArrays = (arrA, arrB) => { if (arrA === arrB) return true; if (!arrA || !arrB) return false; const len = arrA.length; if (arrB.length !== len) return false; for (let i = 0; i < len; i++) if (arrA[i] !== arrB[i]) return false; return true; }; /** * ### `createCacheContext` * * Every Threlte application has its own cache. This prevents models from being * shared between applications because e.g. THREE.Mesh objects cannot be mounted * in multiple scenes. */ export const createCacheContext = () => { const items = []; const remember = (callback, keys) => { for (let i = 0; i < items.length; i++) { const entry = items[i]; if (shallowEqualArrays(keys, entry.keys)) { if (entry.promise) return entry.promise; } } // If no match was found, create a new entry const entry = { promise: callback(), keys }; // Add the entry to the cache items.push(entry); // Return the promise return entry.promise; }; const clear = (keys) => { for (let i = 0; i < items.length; i++) { const entry = items[i]; if (shallowEqualArrays(keys, entry.keys)) { items.splice(i, 1); return; } } }; const context = { items, remember, clear }; setContext('threlte-cache', context); return context; }; /** * ### `useCache` * * This hook is used to access the cache. It returns a `remember` function that * can be used to cache a promise based on the provided keys. The `remember` * function will return the cached value if the promise has already been * resolved and the keys match. * * @example * ```ts * const { remember } = useCache() * * const asyncWritable = remember(async () => { * const loader = new GLTFLoader() * const { scene } = await loader.loadAsync('/path/to/model.glb') * return scene * }) * ``` * * The model will only be loaded once, even if `remember` is invoked multiple * times with the same keys. * * The `clear` function can be used to clear the cache for a specific set of keys. */ export const useCache = () => { const cache = getContext('threlte-cache'); if (!cache) { throw new Error('No cache found. The cache can only be used in a child component to <Canvas>.'); } return cache; };