@threlte/core
Version:
A 3D framework for the web, built on top of Svelte and Three.js
58 lines (57 loc) • 2.09 kB
JavaScript
import { getContext, onDestroy, setContext } from 'svelte';
import { currentWritable } from '../../utilities/index.js';
import { Scheduler } from '../../frame-scheduling/index.js';
export const createSchedulerContext = (options) => {
const scheduler = new Scheduler();
const mainStage = scheduler.createStage(Symbol('threlte-main-stage'));
const context = {
scheduler,
frameInvalidated: true,
autoInvalidations: new Set(),
shouldAdvance: false,
advance: () => {
context.shouldAdvance = true;
},
autoRender: currentWritable(options.autoRender ?? true),
renderMode: currentWritable(options.renderMode ?? 'on-demand'),
invalidate() {
context.frameInvalidated = true;
},
mainStage,
shouldRender: () => {
return (context.renderMode.current === 'always' ||
(context.renderMode.current === 'on-demand' &&
(context.frameInvalidated || context.autoInvalidations.size > 0)) ||
(context.renderMode.current === 'manual' && context.shouldAdvance));
},
renderStage: scheduler.createStage(Symbol('threlte-render-stage'), {
after: mainStage,
callback(_, runTasks) {
if (context.shouldRender())
runTasks();
}
}),
resetFrameInvalidation() {
context.frameInvalidated = false;
context.shouldAdvance = false;
}
};
$effect(() => {
context.autoRender.set(options.autoRender ?? true);
});
$effect(() => {
context.renderMode.set(options.renderMode ?? 'on-demand');
});
onDestroy(() => {
context.scheduler.dispose();
});
setContext('threlte-scheduler-context', context);
return context;
};
export const useScheduler = () => {
const context = getContext('threlte-scheduler-context');
if (!context) {
throw new Error('useScheduler can only be used in a child component to <Canvas>.');
}
return context;
};