x3d-tidy
Version:
X3D Converter, Beautifier and Minimizer
98 lines (77 loc) • 2.66 kB
JavaScript
;
const
X3D = require ("x_ite-node"),
Traverse = require ("x3d-traverse") (X3D);
module .exports = function inferProfileAndComponents (scene)
{
const
browser = scene .getBrowser (),
usedComponents = getUsedComponents (scene),
profileAndComponents = getProfileAndComponentsFromUsedComponents (browser, usedComponents);
setProfile (scene, profileAndComponents .profile);
setComponents (scene, profileAndComponents .components);
}
function getUsedComponents (scene)
{
const components = new Map ();
for (const object of scene .traverse (Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES | Traverse .PROTOTYPE_INSTANCES))
{
if (!(object instanceof X3D .SFNode))
continue;
const
node = object .getValue (),
componentInfo = node .getComponentInfo ();
if (components .get (componentInfo .name) ?? 0 < componentInfo .level)
components .set (componentInfo .name, componentInfo .level);
}
return components;
}
function getProfileAndComponentsFromUsedComponents (browser, usedComponents)
{
const profiles = ["Interchange", "Interactive", "Immersive", "Full"] .map (name =>
{
return { profile: browser .getProfile (name), components: new Map (usedComponents) };
});
profiles .forEach (({ profile, components }) =>
{
for (const component of profile .components)
{
const level = components .get (component .name);
if (level === undefined)
continue;
if (level > component .level)
continue;
components .delete (component .name);
}
});
const { object } = profiles .reduce ((min, object) =>
{
const count = new Set ([
... [... object .profile .components] .map (component => component .name),
... object .components .keys ()
]) .size;
return min .count < count ? min : {
count,
object,
};
},
{ count: Number .POSITIVE_INFINITY });
return {
profile: object .profile,
components: Array .from (object .components .keys ())
.sort ()
.map (name => browser .getComponent (name, object .components .get (name))),
};
}
function setProfile (scene, profile)
{
scene .setProfile (profile);
}
function setComponents (scene, components)
{
const oldComponents = Array .from (scene .getComponents ());
for (const component of oldComponents)
scene .removeComponent (component .name);
for (const component of components)
scene .addComponent (component);
}