@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
JavaScript
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