diff --git a/npm/README.md b/npm/README.md index 20e8cce..5c379cc 100644 --- a/npm/README.md +++ b/npm/README.md @@ -11,7 +11,7 @@ This package contains three versions of `FBX2glTF`, compiled for three platforms and located in three eponymous directories: - bin/Darwin/FBX2glTF - bin/Linux/FBX2glTF - - bin/Windows/FBX2glTF.exe + - bin/Windows_NT/FBX2glTF.exe # Usage diff --git a/npm/bin/Windows/.keep b/npm/bin/Windows_NT/.keep similarity index 100% rename from npm/bin/Windows/.keep rename to npm/bin/Windows_NT/.keep diff --git a/npm/bin/fbx2glb.bat b/npm/bin/fbx2glb.bat deleted file mode 100644 index 827b6cb..0000000 --- a/npm/bin/fbx2glb.bat +++ /dev/null @@ -1 +0,0 @@ -%~dp0\Windows\FBX2glTF --binary %1 %2 diff --git a/npm/bin/fbx2glb.sh b/npm/bin/fbx2glb.sh deleted file mode 100755 index 9d2bbe4..0000000 --- a/npm/bin/fbx2glb.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -# -# fbx2glb.sh -# -# TODO: Pass command line switches through to binary. - -set -e - -BINDIR=`dirname $0` -BINDIR=`cd ${BINDIR} ; pwd` - -SYSTEM=`uname -s` -FBX2GLTF="${BINDIR}/${SYSTEM}/FBX2glTF" - -if [ ! -f "${FBX2GLTF}" ]; then - echo "Unable to find 'FBX2glTF' binary: ${FBX2GLTF}" - exit 1 -fi - -if [ "$#" != 2 ]; then - echo "Usage: " - exit 1 -fi - -fullpath() { - OLDPWD=$PWD - cd "$(dirname "$1")" - FULLPATH="$PWD/$(basename "$1")" - cd "$OLDPWD" - echo "$FULLPATH" -} - -INFILE=$(fullpath $1) -OUTFILE=$(fullpath $(basename $2 ".glb")) - -# construct a safe work dir -SCRIPT_BASE=`basename $0` -TEMP_DIR=`mktemp -d "/tmp/${SCRIPT_BASE}.XXXX"` -trap "rm -rf ${TEMP_DIR}" EXIT -cd ${TEMP_DIR} - -# some hard-coded defaults for now -"${FBX2GLTF}" --binary --flip-v --input "${INFILE}" --output "${OUTFILE}" diff --git a/npm/index.js b/npm/index.js index fa8fc73..96d17f8 100644 --- a/npm/index.js +++ b/npm/index.js @@ -1,6 +1,8 @@ const childProcess = require('child_process'); +const fs = require('fs'); const os = require('os'); const path = require('path'); +const rimraf = require('rimraf'); const binaries = { 'darwin': `bin/darwin/Fbx2Gtlf`, @@ -8,36 +10,70 @@ const binaries = { 'win32': `bin\windows\Fbx2Gtlf.exe`, }; -function fbx2glb(srcFile, destFile, cwd) { +/** + * Converts an FBX to a GTLF or GLB file. + * @param string srcFile path to the source file. + * @param string destFile path to the destination file. + * This must end in `.glb` or `.gltf` (case matters). + * @param string[] [opts] options to pass to the converter tool. + * @return Promise a promise that yields the full path to the converted + * file, an error on conversion failure. + */ +function convert(srcFile, destFile, opts) { return new Promise((resolve, reject) => { - let script = os.type() === 'Windows_NT' ? 'fbx2glb.bat' : 'fbx2glb.sh'; - let child; try { - let opts = {}; - cwd && (opts.cwd = cwd); - child = childProcess.spawn( - path.join(__dirname, 'bin', script), - [ srcFile, destFile ], - opts - ); + let tool = path.join(__dirname, 'bin', os.type(), 'FBX2glTF'); + if (!fs.existsSync(tool)) { + throw new Error(`Unsupported OS: ${os.type()}`); + } + + let destExt; + if (destFile.endsWith('.glb')) { + destExt = '.glb'; + opts.includes('--binary') || opts.push('--binary'); + } else if (destFile.endsWith('.gltf')) { + destExt = '.gltf'; + } else { + throw new Error(`Unsupported file extension: ${destFile}`); + } + + let srcPath = fs.realpathSync(srcFile); + let destDir = fs.realpathSync(path.dirname(destFile)); + let destPath = path.join(destDir, path.basename(destFile, destExt)); + + let args = opts.slice(0); + args.push('--input', srcPath, '--output', destPath); + let child = childProcess.spawn(tool, args); + + let output = ''; + child.stdout.on('data', (data) => output += data); + child.stderr.on('data', (data) => output += data); + child.on('error', reject); + child.on('close', code => { + // the FBX SDK may create an .fbm dir during conversion; delete! + let fbmCruft = srcPath.replace(/.fbx$/i, '.fbm'); + // don't stick a fork in things if this fails, just log a warning + const onError = error => + error && console.warn(`Failed to delete ${fbmCruft}: ${error}`); + try { + fs.existsSync(fbmCruft) && rimraf(fbmCruft, {}, onError); + } catch (error) { + onError(error); + } + + // non-zero exit code is failure + if (code != 0) { + reject(new Error(`Script ${script} output:\n` + + (output.length ? output : ""))); + } else { + resolve(destPath + destExt); + } + }); + } catch (error) { reject(error); - return; } - let output = ''; - child.stdout.on('data', (data) => output += data); - child.stderr.on('data', (data) => output += data); - child.on('error', reject); - child.on('close', code => { - // non-zero exit code is failure - if (code != 0) { - reject(new Error(`Script ${script} output:\n` + - (output.length ? output : ""))); - } else { - resolve(destFile); - } - }); }); } -module.exports = fbx2glb; +module.exports = convert; diff --git a/npm/package.json b/npm/package.json index fdbbfe2..b0ca66d 100644 --- a/npm/package.json +++ b/npm/package.json @@ -23,5 +23,8 @@ "README.md", "bin", "index.js" - ] + ], + "dependencies": { + "rimraf": "^2.6.2" + } } diff --git a/npm/yarn.lock b/npm/yarn.lock new file mode 100644 index 0000000..c30aedc --- /dev/null +++ b/npm/yarn.lock @@ -0,0 +1,70 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +glob@^7.0.5: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +rimraf@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"