diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b312839..00000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index babde30d..fb2ce849 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,11 +1,14 @@ Change Log ========== -### 2.2.0 - 2019-??-?? +### 2.?.? - 2019-??-?? + +* Fixed writing duplicate resource that are referenced multiple times. [#483](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/483) + +### 2.1.4 - 2019-10-04 * Added removal of unused materials, nodes and meshes. [#465](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/465) * Added `keepUnusedElements` flag to keep unused materials, nodes and meshes. [#465](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/465) -* Fixed writing duplicate resource that are referenced multiple times. [#483](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/483) ### 2.1.3 - 2019-03-21 diff --git a/bin/gltf-pipeline.js b/bin/gltf-pipeline.js index f4b5ed51..58efe493 100644 --- a/bin/gltf-pipeline.js +++ b/bin/gltf-pipeline.js @@ -187,7 +187,7 @@ const run = inputIsBinary ? (outputIsBinary ? processGlb : glbToGltf) : (outputI function saveSeparateResources(separateResources) { const resourcePromises = []; for (const relativePath in separateResources) { - if (separateResources.hasOwnProperty(relativePath)) { + if (Object.prototype.hasOwnProperty.call(separateResources, relativePath)) { const resource = separateResources[relativePath]; const resourcePath = path.join(outputDirectory, relativePath); resourcePromises.push(fsExtra.outputFile(resourcePath, resource)); diff --git a/gulpfile.js b/gulpfile.js index 13f0e860..d13e21e9 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -150,7 +150,7 @@ function amdify(source, subDependencyMapping) { const subdependencyMapping = {}; const removeRequireMapping = []; for (requireVariable in requireMapping) { - if (requireMapping.hasOwnProperty(requireVariable)) { + if (Object.prototype.hasOwnProperty.call(requireMapping, requireVariable)) { requirePath = requireMapping[requireVariable]; const findSubdependencyString = 'var\\s+(.+?)\\s*?=\\s*?' + requireVariable + '\\.(.+?);\n'; const findSubdependencyRegex = new RegExp(findSubdependencyString, 'g'); @@ -178,35 +178,27 @@ function amdify(source, subDependencyMapping) { } // join sub-dependencies with requireMapping for (const subdependencyVariable in subdependencyMapping) { - if (subdependencyMapping.hasOwnProperty(subdependencyVariable)) { + if (Object.prototype.hasOwnProperty.call(subdependencyMapping, subdependencyVariable)) { requireMapping[subdependencyVariable] = subdependencyMapping[subdependencyVariable]; } } // amdify source - // indent - outputSource = outputSource.replace(/\n/g, '\n '); + outputSource = outputSource.replace(/'use strict';/g, ''); + // wrap define header - const variables = []; - const paths = []; + const lines = []; for (const variable in requireMapping) { - if (requireMapping.hasOwnProperty(variable)) { - variables.push(variable); - paths.push(requireMapping[variable]); + if (Object.prototype.hasOwnProperty.call(requireMapping, variable)) { + lines.push('import ' + variable + ' from \'' + requireMapping[variable] + '\''); } } - let defineHeader = 'define([], function() {\n '; - if (paths.length > 0) { - const definePathsHeader = '\'' + paths.join('\',\n \'') + '\''; - const defineVariablesHeader = variables.join(',\n '); - defineHeader = - 'define([\n' + - ' ' + definePathsHeader + '\n' + - ' ], function(\n' + - ' ' + defineVariablesHeader + ') {\n '; + let defineHeader = ''; + if (lines.length > 0) { + defineHeader = lines.join('\n') + '\n'; } - let defineFooter = '\n});\n'; + let defineFooter = '\n'; if (defined(returnValue)) { - defineFooter = '\n return ' + returnValue + ';' + defineFooter; + defineFooter = '\nexport default ' + returnValue + ';\n'; } outputSource = defineHeader + outputSource + defineFooter; // remove repeat newlines diff --git a/lib/ForEach.js b/lib/ForEach.js index c2953b3a..b29e6871 100644 --- a/lib/ForEach.js +++ b/lib/ForEach.js @@ -23,7 +23,7 @@ function ForEach() { ForEach.objectLegacy = function(objects, handler) { if (defined(objects)) { for (const objectId in objects) { - if (objects.hasOwnProperty(objectId)) { + if (Object.prototype.hasOwnProperty.call(objects, objectId)) { const object = objects[objectId]; const value = handler(object, objectId); @@ -190,7 +190,7 @@ ForEach.compressedImage = function(image, handler) { if (defined(image.extras)) { const compressedImages = image.extras.compressedImage3DTiles; for (const type in compressedImages) { - if (compressedImages.hasOwnProperty(type)) { + if (Object.prototype.hasOwnProperty.call(compressedImages, type)) { const compressedImage = compressedImages[type]; const value = handler(compressedImage, type); @@ -213,7 +213,7 @@ ForEach.materialValue = function(material, handler) { } for (const name in values) { - if (values.hasOwnProperty(name)) { + if (Object.prototype.hasOwnProperty.call(values, name)) { const value = handler(values[name], name); if (defined(value)) { @@ -245,7 +245,7 @@ ForEach.meshPrimitive = function(mesh, handler) { ForEach.meshPrimitiveAttribute = function(primitive, handler) { const attributes = primitive.attributes; for (const semantic in attributes) { - if (attributes.hasOwnProperty(semantic)) { + if (Object.prototype.hasOwnProperty.call(attributes, semantic)) { const value = handler(attributes[semantic], semantic); if (defined(value)) { @@ -271,7 +271,7 @@ ForEach.meshPrimitiveTarget = function(primitive, handler) { ForEach.meshPrimitiveTargetAttribute = function(target, handler) { for (const semantic in target) { - if (target.hasOwnProperty(semantic)) { + if (Object.prototype.hasOwnProperty.call(target, semantic)) { const accessorId = target[semantic]; const value = handler(accessorId, semantic); @@ -366,7 +366,7 @@ ForEach.skinJoint = function(skin, handler) { ForEach.techniqueAttribute = function(technique, handler) { const attributes = technique.attributes; for (const attributeName in attributes) { - if (attributes.hasOwnProperty(attributeName)) { + if (Object.prototype.hasOwnProperty.call(attributes, attributeName)) { const value = handler(attributes[attributeName], attributeName); if (defined(value)) { @@ -379,7 +379,7 @@ ForEach.techniqueAttribute = function(technique, handler) { ForEach.techniqueUniform = function(technique, handler) { const uniforms = technique.uniforms; for (const uniformName in uniforms) { - if (uniforms.hasOwnProperty(uniformName)) { + if (Object.prototype.hasOwnProperty.call(uniforms, uniformName)) { const value = handler(uniforms[uniformName], uniformName); if (defined(value)) { @@ -392,7 +392,7 @@ ForEach.techniqueUniform = function(technique, handler) { ForEach.techniqueParameter = function(technique, handler) { const parameters = technique.parameters; for (const parameterName in parameters) { - if (parameters.hasOwnProperty(parameterName)) { + if (Object.prototype.hasOwnProperty.call(parameters, parameterName)) { const value = handler(parameters[parameterName], parameterName); if (defined(value)) { diff --git a/lib/getImageExtension.js b/lib/getImageExtension.js index 8b41527c..e7629fbd 100644 --- a/lib/getImageExtension.js +++ b/lib/getImageExtension.js @@ -30,6 +30,8 @@ function getImageExtension(data) { return '.ktx'; } else if (header.equals(Buffer.from([0x48, 0x78]))) { return '.crn'; + } else if (header.equals(Buffer.from([0x73, 0x42]))) { + return '.basis'; } else if (webpHeaderRIFFChars.equals(Buffer.from([0x52, 0x49, 0x46, 0x46])) && webpHeaderWEBPChars.equals(Buffer.from([0x57, 0x45, 0x42, 0x50]))) { // See https://developers.google.com/speed/webp/docs/riff_container#webp_file_header return '.webp'; diff --git a/lib/mergeBuffers.js b/lib/mergeBuffers.js index 7b739f97..5d9e1b74 100644 --- a/lib/mergeBuffers.js +++ b/lib/mergeBuffers.js @@ -78,7 +78,7 @@ function mergeBuffers(gltf, defaultName) { gltf.buffers = new Array(buffersLength); for (const mergedName in buffersToMerge) { - if (buffersToMerge.hasOwnProperty(mergedName)) { + if (Object.prototype.hasOwnProperty.call(buffersToMerge, mergedName)) { const buffers = buffersToMerge[mergedName].buffers; const byteLength = buffersToMerge[mergedName].byteLength; const index = buffersToMerge[mergedName].index; diff --git a/lib/removeExtension.js b/lib/removeExtension.js index 750f54c9..8c34e459 100644 --- a/lib/removeExtension.js +++ b/lib/removeExtension.js @@ -55,7 +55,7 @@ function removeExtensionAndTraverse(object, extension) { } } for (const key in object) { - if (object.hasOwnProperty(key)) { + if (Object.prototype.hasOwnProperty.call(object, key)) { removeExtensionAndTraverse(object[key], extension); } } diff --git a/lib/replaceWithDecompressedPrimitive.js b/lib/replaceWithDecompressedPrimitive.js index 66c9dda4..e95dff61 100644 --- a/lib/replaceWithDecompressedPrimitive.js +++ b/lib/replaceWithDecompressedPrimitive.js @@ -44,7 +44,7 @@ function replaceWithDecompressedPrimitive(gltf, primitive, dracoEncodedBuffer, u const dracoAttributes = primitive.extensions.KHR_draco_mesh_compression.attributes; for (const semantic in dracoAttributes) { - if (dracoAttributes.hasOwnProperty(semantic)) { + if (Object.prototype.hasOwnProperty.call(dracoAttributes, semantic)) { const attributeAccessor = gltf.accessors[primitive.attributes[semantic]]; attributeAccessor.count = dracoEncodedBuffer.numberOfPoints; diff --git a/lib/splitPrimitives.js b/lib/splitPrimitives.js index 676c38da..fc6b01eb 100644 --- a/lib/splitPrimitives.js +++ b/lib/splitPrimitives.js @@ -64,7 +64,7 @@ function splitPrimitives(gltf) { }); for (hash in primitivesWithSharedAttributes) { - if (primitivesWithSharedAttributes.hasOwnProperty(hash)) { + if (Object.prototype.hasOwnProperty.call(primitivesWithSharedAttributes, hash)) { primitives = primitivesWithSharedAttributes[hash]; primitivesLength = primitives.length; if (primitivesLength === 1) { @@ -81,7 +81,7 @@ function splitPrimitives(gltf) { if (primitivesSplit) { for (hash in duplicatePrimitives) { - if (duplicatePrimitives.hasOwnProperty(hash)) { + if (Object.prototype.hasOwnProperty.call(duplicatePrimitives, hash)) { const primitiveToCopy = hashPrimitives[hash]; primitives = duplicatePrimitives[hash]; primitivesLength = primitives.length; @@ -148,7 +148,7 @@ function createNewAttribute(gltf, accessorId, semantic, attributeData, mappedInd function remapData(dataArray, newDataArray, mappedIndices, numberOfComponents) { for (const index in mappedIndices) { - if (mappedIndices.hasOwnProperty(index)) { + if (Object.prototype.hasOwnProperty.call(mappedIndices, index)) { const mappedIndex = mappedIndices[index]; for (let i = 0; i < numberOfComponents; ++i) { newDataArray[mappedIndex * numberOfComponents + i] = dataArray[index * numberOfComponents + i]; diff --git a/lib/updateVersion.js b/lib/updateVersion.js index 37089570..2e772f68 100644 --- a/lib/updateVersion.js +++ b/lib/updateVersion.js @@ -55,13 +55,13 @@ function updateVersion(gltf, options) { version = defaultValue(version, gltf.asset.version).toString(); // Invalid version - if (!updateFunctions.hasOwnProperty(version)) { + if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) { // Try truncating trailing version numbers, could be a number as well if it is 0.8 if (defined(version)) { version = version.substring(0, 3); } // Default to 1.0 if it cannot be determined - if (!updateFunctions.hasOwnProperty(version)) { + if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) { version = '1.0'; } } @@ -82,7 +82,7 @@ function updateVersion(gltf, options) { function updateInstanceTechniques(gltf) { const materials = gltf.materials; for (const materialId in materials) { - if (materials.hasOwnProperty(materialId)) { + if (Object.prototype.hasOwnProperty.call(materials, materialId)) { const material = materials[materialId]; const instanceTechnique = material.instanceTechnique; if (defined(instanceTechnique)) { @@ -97,7 +97,7 @@ function updateInstanceTechniques(gltf) { function setPrimitiveModes(gltf) { const meshes = gltf.meshes; for (const meshId in meshes) { - if (meshes.hasOwnProperty(meshId)) { + if (Object.prototype.hasOwnProperty.call(meshes, meshId)) { const mesh = meshes[meshId]; const primitives = mesh.primitives; if (defined(primitives)) { @@ -118,7 +118,7 @@ function updateNodes(gltf) { const axis = new Cartesian3(); const quat = new Quaternion(); for (const nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { + if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) { const node = nodes[nodeId]; if (defined(node.rotation)) { const rotation = node.rotation; @@ -146,7 +146,7 @@ function updateAnimations(gltf) { const axis = new Cartesian3(); const quat = new Quaternion(); for (const animationId in animations) { - if (animations.hasOwnProperty(animationId)) { + if (Object.prototype.hasOwnProperty.call(animations, animationId)) { const animation = animations[animationId]; const channels = animation.channels; const parameters = animation.parameters; @@ -189,12 +189,12 @@ function updateAnimations(gltf) { function removeTechniquePasses(gltf) { const techniques = gltf.techniques; for (const techniqueId in techniques) { - if (techniques.hasOwnProperty(techniqueId)) { + if (Object.prototype.hasOwnProperty.call(techniques, techniqueId)) { const technique = techniques[techniqueId]; const passes = technique.passes; if (defined(passes)) { const passName = defaultValue(technique.pass, 'defaultPass'); - if (passes.hasOwnProperty(passName)) { + if (Object.prototype.hasOwnProperty.call(passes, passName)) { const pass = passes[passName]; const instanceProgram = pass.instanceProgram; technique.attributes = defaultValue(technique.attributes, instanceProgram.attributes); @@ -261,13 +261,13 @@ function glTF08to10(gltf) { function removeAnimationSamplersIndirection(gltf) { const animations = gltf.animations; for (const animationId in animations) { - if (animations.hasOwnProperty(animationId)) { + if (Object.prototype.hasOwnProperty.call(animations, animationId)) { const animation = animations[animationId]; const parameters = animation.parameters; if (defined(parameters)) { const samplers = animation.samplers; for (const samplerId in samplers) { - if (samplers.hasOwnProperty(samplerId)) { + if (Object.prototype.hasOwnProperty.call(samplers, samplerId)) { const sampler = samplers[samplerId]; sampler.input = parameters[sampler.input]; sampler.output = parameters[sampler.output]; @@ -282,7 +282,7 @@ function removeAnimationSamplersIndirection(gltf) { function objectToArray(object, mapping) { const array = []; for (const id in object) { - if (object.hasOwnProperty(id)) { + if (Object.prototype.hasOwnProperty.call(object, id)) { const value = object[id]; mapping[id] = array.length; array.push(value); @@ -320,7 +320,7 @@ function objectsToArrays(gltf) { const jointNameToId = {}; const nodes = gltf.nodes; for (const id in nodes) { - if (nodes.hasOwnProperty(id)) { + if (Object.prototype.hasOwnProperty.call(nodes, id)) { jointName = nodes[id].jointName; if (defined(jointName)) { jointNameToId[jointName] = id; @@ -330,7 +330,7 @@ function objectsToArrays(gltf) { // Convert top level objects to arrays for (const topLevelId in gltf) { - if (gltf.hasOwnProperty(topLevelId) && defined(globalMapping[topLevelId])) { + if (Object.prototype.hasOwnProperty.call(gltf, topLevelId) && defined(globalMapping[topLevelId])) { const objectMapping = {}; const object = gltf[topLevelId]; gltf[topLevelId] = objectToArray(object, objectMapping); @@ -340,7 +340,7 @@ function objectsToArrays(gltf) { // Remap joint names to array indexes for (jointName in jointNameToId) { - if (jointNameToId.hasOwnProperty(jointName)) { + if (Object.prototype.hasOwnProperty.call(jointNameToId, jointName)) { jointNameToId[jointName] = globalMapping.nodes[jointNameToId[jointName]]; } } @@ -570,7 +570,7 @@ function removeAnimationSamplerNames(gltf) { function removeEmptyArrays(gltf) { for (const topLevelId in gltf) { - if (gltf.hasOwnProperty(topLevelId)) { + if (Object.prototype.hasOwnProperty.call(gltf, topLevelId)) { const array = gltf[topLevelId]; if (isArray(array) && array.length === 0) { delete gltf[topLevelId]; @@ -691,7 +691,7 @@ function underscoreApplicationSpecificSemantics(gltf) { } }); for (const semantic in mappedSemantics) { - if (mappedSemantics.hasOwnProperty(semantic)) { + if (Object.prototype.hasOwnProperty.call(mappedSemantics, semantic)) { const mappedSemantic = mappedSemantics[semantic]; const accessorId = primitive.attributes[semantic]; if (defined(accessorId)) { @@ -774,7 +774,7 @@ function moveByteStrideToBufferView(gltf) { // Split accessors with different byte strides for (const bufferViewId in bufferViewMap) { - if (bufferViewMap.hasOwnProperty(bufferViewId)) { + if (Object.prototype.hasOwnProperty.call(bufferViewMap, bufferViewId)) { bufferView = bufferViews[bufferViewId]; const accessors = bufferViewMap[bufferViewId]; accessors.sort(function(a, b) { diff --git a/lib/writeResources.js b/lib/writeResources.js index 9750c401..e492b001 100644 --- a/lib/writeResources.js +++ b/lib/writeResources.js @@ -17,6 +17,9 @@ mime.define({'image/crn': ['crn']}, true); // .glsl shaders are text/plain type mime.define({'text/plain': ['glsl']}, true); +// .basis is not a supported mime type, so add it +mime.define({'image/basis': ['basis']}, true); + module.exports = writeResources; /** @@ -188,9 +191,10 @@ function getRelativePath(gltf, object, index, extension, options) { relativePath = name + extension; // Check if a file of the same name already exists, and if so, append a number - const number = 1; + let number = 1; while (defined(options.separateResources[relativePath])) { relativePath = name + '_' + number + extension; + number++; } return relativePath; } diff --git a/package.json b/package.json index f9d6120f..52aaf4b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gltf-pipeline", - "version": "2.1.3", + "version": "2.1.4", "description": "Content pipeline tools for optimizing glTF assets.", "license": "Apache-2.0", "contributors": [ @@ -26,27 +26,27 @@ "node": ">=6.0.0" }, "dependencies": { - "bluebird": "^3.5.3", - "cesium": "^1.54.0", + "bluebird": "^3.5.5", + "cesium": "^1.58.1", "draco3d": "^1.3.4", - "fs-extra": "^8.0.0", - "mime": "^2.4.0", - "object-hash": "^1.3.1", + "fs-extra": "^8.0.1", + "mime": "^2.4.4", + "object-hash": "^2.0.0", "uuid": "^3.3.2", - "yargs": "^13.2.0" + "yargs": "^14.0.0" }, "devDependencies": { - "cloc": "^2.4.0", - "coveralls": "^3.0.2", + "cloc": "^2.5.0", + "coveralls": "^3.0.4", "dependency-tree": "^7.0.2", - "eslint": "^5.13.0", + "eslint": "^6.0.0", "eslint-config-cesium": "^7.0.0", - "gulp": "^4.0.0", - "jasmine": "^3.3.1", + "gulp": "^4.0.2", + "jasmine": "^3.4.0", "jasmine-spec-reporter": "^4.2.1", - "jsdoc": "^3.5.5", - "nyc": "^14.0.0", - "open": "^6.0.0", + "jsdoc": "^3.6.2", + "nyc": "^14.1.1", + "open": "^6.3.0", "requirejs": "^2.3.6" }, "scripts": { diff --git a/specs/lib/getImageExtensionSpec.js b/specs/lib/getImageExtensionSpec.js index 563851cc..68572de5 100644 --- a/specs/lib/getImageExtensionSpec.js +++ b/specs/lib/getImageExtensionSpec.js @@ -11,6 +11,7 @@ const jpgData = dataUriToBuffer('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABI const bmpData = dataUriToBuffer('data:image/bmp;base64,Qk1mAAAAAAAAADYAAAAoAAAABAAAAAQAAAABABgAAAAAADAAAAATCwAAEwsAAAAAAAAAAAAA////////////////////////////////////////////////////////////////'); const ktxData = dataUriToBuffer('data:image/ktx:base64,q0tUWCAxMbsNChoKAQIDBAEUAAABAAAACBkAAFiAAAAIGQAABAAAAAQAAAAAAAAAAAAAAAEAAAABAAAAIAAAABsAAABLVFhPcmllbnRhdGlvbgBTPXIsVD1kLFI9aQAAQAAAAP////////////////////////////////////////////////////////////////////////////////////8='); const crnData = dataUriToBuffer('data:image/crn:base64,SHgAUktGAAAAlds6AAQABAMBAAAAAAAAAAAAAAAAAAAAAABSAAAXAAEAAGkAAAwAAQAAAAAAAAAAAAAAAAAAAAAAHQAAdQAAAJIAAACTAAAAlACCYIAAAAAAABkwBAmCAAAAAAAAbRYAAGZggAAAAAAAGNAAAAZgAAAAAAAAEAAzAAAAAAAAAIABmAAAAAAAAAQAAAA='); +const basisData = dataUriToBuffer('data:image/basis;base64,c0ITAE0AAA9wAAAAqewBAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAQBkAAAAKAAAAQCMAAAABQAAkQAAACsAAABNAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAvAAAAAEAAACPUwHABAAAAAAAAAICmAgAAAAAAEASBAATAAAAAAAAiABgAgAAAAAAABFUVVVVBQDBRAAAAAAAAPJfLQCYAAAAAAAAQAgAEwACAAAAAIgBwAQAAAAAAAACCAAA'); const textData = dataUriToBuffer('data:text/plain;charset=utf-8,randomtext'); describe('getImageExtension', () => { @@ -21,6 +22,7 @@ describe('getImageExtension', () => { expect(getImageExtension(bmpData)).toBe('.bmp'); expect(getImageExtension(ktxData)).toBe('.ktx'); expect(getImageExtension(crnData)).toBe('.crn'); + expect(getImageExtension(basisData)).toBe('.basis'); }); it('throws error if buffer does not contain image data', () => {