UNPKG

@threlte/core

Version:

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

107 lines (106 loc) 3.03 kB
import { onDestroy } from 'svelte'; import { readable, writable } from 'svelte/store'; import { useScheduler } from '../context/fragments/scheduler.svelte'; import { DAG } from '../frame-scheduling'; import { browser } from '../utilities'; export function useTask(keyOrFn, fnOrOptions, options) { if (!browser) { return { task: undefined, start: () => undefined, stop: () => undefined, started: readable(false) }; } let key; let fn; let opts; if (DAG.isKey(keyOrFn)) { key = keyOrFn; fn = fnOrOptions; opts = options; } else { key = Symbol('useTask'); fn = keyOrFn; opts = fnOrOptions; } const schedulerCtx = useScheduler(); let stage = schedulerCtx.mainStage; if (opts) { if (opts.stage) { if (DAG.isValue(opts.stage)) { stage = opts.stage; } else { const maybeStage = schedulerCtx.scheduler.getStage(opts.stage); if (!maybeStage) { throw new Error(`No stage found with key ${opts.stage.toString()}`); } stage = maybeStage; } } else if (opts.after) { if (Array.isArray(opts.after)) { for (let index = 0; index < opts.after.length; index++) { const element = opts.after[index]; if (DAG.isValue(element)) { stage = element.stage; break; } } } else if (DAG.isValue(opts.after)) { stage = opts.after.stage; } } else if (opts.before) { if (Array.isArray(opts.before)) { for (let index = 0; index < opts.before.length; index++) { const element = opts.before[index]; if (DAG.isValue(element)) { stage = element.stage; break; } } } else if (DAG.isValue(opts.before)) { stage = opts.before.stage; } } } const started = writable(false); const task = stage.createTask(key, fn, opts); const start = () => { started.set(true); if (opts?.autoInvalidate ?? true) { schedulerCtx.autoInvalidations.add(fn); } task.start(); }; const stop = () => { started.set(false); if (opts?.autoInvalidate ?? true) { schedulerCtx.autoInvalidations.delete(fn); } task.stop(); }; if (opts?.autoStart ?? true) { start(); } else { stop(); } onDestroy(() => { stop(); stage.removeTask(key); }); return { task, start, stop, started: { subscribe: started.subscribe } }; }