@threlte/core
Version:
A 3D framework for the web, built on top of Svelte and Three.js
107 lines (106 loc) • 3.03 kB
JavaScript
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
}
};
}