UNPKG

threepipe

Version:

A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.

62 lines (58 loc) 2.48 kB
import {IPassID, IPipelinePass} from './Pass' import {includesAll} from 'ts-browser-helpers' export function sortPasses(ps: IPipelinePass<IPassID>[]) { const pipeline: IPassID[] = [] const dict: Record<IPassID, {after: IPassID[], before: IPassID[], dependencies: Set<IPassID>}> = {} for (const pass of ps) { if (!pass.passId) continue dict[pass.passId] = { after: pass.after ?? [], before: pass.before ?? [], dependencies: new Set(pass.required ?? []), } } for (const [passId, pass] of Object.entries(dict)) { const optional = new Set([...pass.after, ...pass.before]) pass.dependencies.forEach(v => optional.has(v) && optional.delete(v)) optional.forEach(value => { const dPass = dict[value] if (!dPass) return if (dPass.dependencies.has(passId)) { console.error('cyclic', passId, value) throw 'Cyclic dependency' } pass.dependencies.add(value) }) } // eslint-disable-next-line no-constant-condition while (true) { let updated = false const entries = [...Object.entries(dict)] for (const [passId, pass] of entries) { if (pipeline.includes(passId)) continue if (includesAll(pipeline, pass.dependencies.values())) { const afterIndex = Math.max(-1, ...pass.after.map(v => pipeline.indexOf(v))) const beforeIndex = Math.min(pipeline.length, ...pass.before.map(v => { const k = pipeline.indexOf(v) return k < 0 ? pipeline.length : k })) if (afterIndex >= beforeIndex) { console.error(pass, ps, pipeline, afterIndex, beforeIndex) throw 'Not possible' } pipeline.splice(pass.after.length > 0 ? afterIndex + 1 : beforeIndex, 0, passId) // console.log(pipeline, passId, afterIndex, beforeIndex) updated = true delete dict[passId] } } if (Object.keys(dict).length < 1) break if (!updated) { console.error(entries, dict, pipeline) throw 'Not possible 2' // when some dependency(required) doesnt exist. todo: show better error. break } } // console.log('Refreshed Pipeline:', pipeline) return pipeline }