"use strict"; // entityImport.js // // Created by Thijs Wenker on 06/19/2017. // Copyright 2017 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // /* global module */ // @module entityImport var ZERO_UUID = '{00000000-0000-0000-0000-000000000000}'; var SANETIZE_PROPERTIES = ['childEntities', 'parentID', 'id']; var copyObject = function(original) { // JSON.stringify -> JSON.parse trick to create a fresh copy of JSON data var copy = JSON.parse(JSON.stringify(original)); return copy; }; // Creates an entity and returns a mixed object of the creation properties and the assigned entityID var createEntity = function(entityProperties, parent, overrideProperties, defaultProperties) { var newEntityProperties = copyObject(entityProperties); if (overrideProperties !== undefined) { Object.keys(overrideProperties).forEach(function(key) { newEntityProperties[key] = overrideProperties[key]; }); } if (parent.rotation !== undefined) { if (newEntityProperties.rotation !== undefined) { newEntityProperties.rotation = Quat.multiply(parent.rotation, newEntityProperties.rotation); } else { newEntityProperties.rotation = parent.rotation; } } if (parent.position !== undefined) { var localPosition = (parent.rotation !== undefined) ? Vec3.multiplyQbyV(parent.rotation, newEntityProperties.position) : newEntityProperties.position; newEntityProperties.position = Vec3.sum(localPosition, parent.position); } if (parent.id !== undefined) { newEntityProperties.parentID = parent.id; } // Finally fill in the default properties for the options that haven't been set if (defaultProperties !== undefined) { Object.keys(defaultProperties).forEach(function(key) { if (newEntityProperties[key] === undefined) { newEntityProperties[key] = defaultProperties[key]; print(JSON.stringify(newEntityProperties)); //print('newEntityProperties["' + key + '"] = ' + defaultProperties[key]) } }); } newEntityProperties.id = Entities.addEntity(newEntityProperties); return newEntityProperties; }; var createEntitiesFromTree = function(entityTree, parent, overrideProperties, defaultProperties) { if (parent === undefined) { parent = {}; } if (parent.overrideProperties !== undefined) { overrideProperties = parent.overrideProperties; } if (parent.defaultProperties !== undefined) { defaultProperties = parent.defaultProperties; } var createdTree = []; entityTree.forEach(function(entityProperties) { var sanetizedProperties = {}; Object.keys(entityProperties).forEach(function(propertyKey) { if (!entityProperties.hasOwnProperty(propertyKey) || SANETIZE_PROPERTIES.indexOf(propertyKey) !== -1) { return true; } sanetizedProperties[propertyKey] = entityProperties[propertyKey]; }); // Allow for non-entity parent objects, this allows us to offset groups of entities to a specific position/rotation var parentProperties = sanetizedProperties; if (entityProperties.type !== undefined) { parentProperties = createEntity(sanetizedProperties, parent, overrideProperties, defaultProperties); } if (entityProperties.childEntities !== undefined) { parentProperties.childEntities = createEntitiesFromTree(entityProperties.childEntities, parentProperties, overrideProperties, defaultProperties); } createdTree.push(parentProperties); }); return createdTree; }; var entityListToTree = function(entitiesList) { function entityListToTreeRecursive(properties) { properties.childEntities = []; entitiesList.forEach(function(entityProperties) { if (properties.id === entityProperties.parentID) { properties.childEntities.push(entityListToTreeRecursive(entityProperties)); } }); return properties; } var entityTree = []; entitiesList.forEach(function(entityProperties) { if (entityProperties.parentID === undefined || entityProperties.parentID === ZERO_UUID) { entityTree.push(entityListToTreeRecursive(entityProperties)); } }); return entityTree; }; var importEntitiesJSON = function(importLink, parentProperties, overrideProperties, defaultProperties) { if (parentProperties === undefined) { parentProperties = {}; } if (overrideProperties !== undefined) { parentProperties.overrideProperties = overrideProperties; } if (defaultProperties !== undefined) { parentProperties.defaultProperties = defaultProperties; } try { print("importLink = " + importLink); var importJSON = Script.require(importLink); //print(JSON.stringify(importJSON)); parentProperties.childEntities = entityListToTree(importJSON.Entities); return parentProperties; } catch (e) { debug('Failed importing entities JSON because: ' + JSON.stringify(e)); } return null; }; module.exports = { importEntitiesJSON: importEntitiesJSON, createEntitiesFromTree: createEntitiesFromTree, entityImport: function(entityJSON, parentProperties, overrideProperties, defaultProperties) { var entitySet = importEntitiesJSON(entityJSON, parentProperties, overrideProperties, defaultProperties); return createEntitiesFromTree([ entitySet ]); } }; // @function - debug logging function debug() { print('EntityImportModule | ' + [].slice.call(arguments).join(' ')); }