UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

153 lines 6.04 kB
import { debugExtension } from "../engine_default_parameters.js"; import { getParam } from "../engine_utils.js"; const debug = getParam("debugresolvedependencies"); const rootExtensionPrefix = ["/extensions/", "extensions/"]; const defaultDependencies = [ { prefix: "/nodes/", dependencyName: "node" }, { prefix: "/meshes/", dependencyName: "mesh" }, { prefix: "/materials/", dependencyName: "material" }, { prefix: "/textures/", dependencyName: "texture" }, { prefix: "/animations/", dependencyName: "animation" }, // legacy support { prefix: "nodes/", dependencyName: "node" }, { prefix: "meshes/", dependencyName: "mesh" }, { prefix: "materials/", dependencyName: "material" }, { prefix: "textures/", dependencyName: "texture" }, { prefix: "animations/", dependencyName: "animation" }, ]; export async function resolveReferences(parser, obj) { if (debug) console.log(parser, obj); const arr = []; internalResolve(defaultDependencies, parser, obj, arr); const res = await Promise.all(arr); if (typeof obj === "string" && res.length === 1) { return res[0]; } return res; } /** * Utility method to check if two materials were created from the same glTF material */ export function compareAssociation(obj1, obj2) { if (!obj1 || !obj2) return false; if (obj1["needle:identifier"] != undefined && obj2["needle:identifier"] != undefined) return obj1["needle:identifier"] === obj2["needle:identifier"]; return false; } /** * Setting * @hidden */ export function maskGltfAssociation(obj, identifier) { // Mark an object with an identifier to check if two objects were created from the same source obj["needle:identifier"] = identifier; } function internalResolve(paths, parser, obj, promises) { if (typeof obj === "object" && obj !== undefined && obj !== null) { for (const key of Object.keys(obj)) { const val = obj[key]; // handle json pointer in string variable if (typeof val === "string") { const ext = resolveExtension(parser, val); if (ext !== null && ext !== undefined) { if (typeof ext.then === "function") promises.push(ext.then(res => obj[key] = res)); else obj[key] = ext; } else { // e.g. prefix = "/materials/"; const res = tryResolveDependency(paths, parser, val); if (res) { promises.push(res.then(res => { obj[key] = res; return res; })); continue; } } } // handle json pointers in arrays else if (Array.isArray(val)) { for (let i = 0; i < val.length; i++) { const entry = val[i]; const ext = resolveExtension(parser, entry); if (ext !== null) { if (typeof ext.then === "function") promises.push(ext.then(res => val[i] = res)); else val[i] = ext; continue; } for (const dep of paths) { const index = tryGetIndex(dep.prefix, entry); if (index >= 0) { if (debug) console.log(dep, index, dep.dependencyName); promises.push(parser.getDependency(dep.dependencyName, index).then(res => val[i] = res)); break; } } // recurse if (typeof entry === "object") { internalResolve(paths, parser, entry, promises); } } } // recurse else if (typeof val === "object") { internalResolve(paths, parser, val, promises); } } } else if (typeof obj === "string") { const res = tryResolveDependency(paths, parser, obj); if (res) promises.push(res); } } function resolveExtension(parser, str) { if (parser && parser.plugins && typeof str === "string") { for (const prefix of rootExtensionPrefix) { if (str.startsWith(prefix)) { let name = str.substring(prefix.length); const endIndex = name.indexOf("/"); if (endIndex >= 0) name = name.substring(0, endIndex); const ext = parser.plugins[name]; if (debugExtension) console.log(name, ext); if (typeof ext?.resolve === "function") { const path = str.substring(prefix.length + name.length + 1); return ext.resolve(parser, path); } break; } } } return null; } function tryResolveDependency(paths, parser, str) { for (const dep of paths) { const index = tryGetIndex(dep.prefix, str); if (index >= 0) { if (debug) console.warn("GET DEPENDENCY", dep, index, dep.dependencyName); return parser.getDependency(dep.dependencyName, index); } } return null; } function tryGetIndex(prefix, str) { if (typeof str === "string" && str.startsWith(prefix)) { const part = str.substring(prefix.length); const index = Number.parseInt(part); if (index >= 0) { return index; } } return -1; } //# sourceMappingURL=extension_utils.js.map