fbx-parser
Version:
This parser will parse FBX text files and convert them into a JavaScript-Object structure.
137 lines (136 loc) • 5.32 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseText = void 0;
/**
* Returns a list of FBXNodes
* @param ascii the FBX ascii file content
*/
function parseText(ascii) {
var lines = ascii.split('\n');
var rootNode = {
name: '',
props: [],
nodes: [],
};
var currentNode = rootNode;
var path = [currentNode];
var state = 0 /* expectingNodeOrClose */;
for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
var line = lines_1[_i];
line = line.trim();
// Empty Line
if (line.length === 0)
continue;
// Comment Line
if (line[0] === ';')
continue;
// Depending on State (expecting sub-node or node close, expecting property list continuation-if line ends with a comma)
if (state === 0 /* expectingNodeOrClose */) {
// Node Close
if (line[0] === '}') {
// Can't close when in root node
if (path.length === 1)
throw 'FBX syntax error';
path.pop();
currentNode = path[path.length - 1];
}
else {
// find colon after the the node name
var firstCol = line.indexOf(':');
var nodeName = line.substring(0, firstCol);
nodeName = nodeName.trim();
// check end of line
var expectingSubnodes = line[line.length - 1] === '{';
var propertyString = line.substring(firstCol + 1, line.length - (expectingSubnodes ? 1 : 0));
var propertyStringList = propertyString.split(',');
var properties = [];
for (var _a = 0, propertyStringList_1 = propertyStringList; _a < propertyStringList_1.length; _a++) {
var propertyString_1 = propertyStringList_1[_a];
var trimmed = propertyString_1.trim();
if (trimmed === '')
continue;
var value = convertProperty(trimmed);
if (typeof value === 'undefined')
continue;
properties.push(value);
}
if (propertyStringList[propertyStringList.length - 1] === '')
state = 1 /* expectingPropertyListContinuation */;
var newNode = {
name: nodeName,
props: properties,
nodes: [],
};
currentNode.nodes.push(newNode);
if (expectingSubnodes || state === 1 /* expectingPropertyListContinuation */) {
path.push(newNode);
currentNode = newNode;
}
}
}
else if (state === 1 /* expectingPropertyListContinuation */) {
// check end of line
var expectingSubnodes = line[line.length - 1] === '{';
var propertyString = line.substring(0, line.length - (expectingSubnodes ? 1 : 0));
var propertyStringList = propertyString.split(',');
var properties = [];
for (var _b = 0, propertyStringList_2 = propertyStringList; _b < propertyStringList_2.length; _b++) {
var propertyString_2 = propertyStringList_2[_b];
var trimmed = propertyString_2.trim();
if (trimmed === '' || trimmed === '}')
continue;
var value = convertProperty(trimmed);
if (typeof value === 'undefined')
continue;
properties.push(value);
}
currentNode.props = currentNode.props.concat(properties);
if (propertyStringList[propertyStringList.length - 1] !== '')
state = 0 /* expectingNodeOrClose */;
if (!expectingSubnodes && state === 0 /* expectingNodeOrClose */) {
path.pop();
currentNode = path[path.length - 1];
}
}
}
// nodes with name a seem to actually just be an array prop and handled like a prop in binary
function correctArrays(node) {
if (node.nodes.length === 1 && node.props.length === 0 && node.nodes[0].name === 'a') {
node.props = [node.nodes[0].props];
node.nodes = [];
}
else {
for (var _i = 0, _a = node.nodes; _i < _a.length; _i++) {
var childNode = _a[_i];
correctArrays(childNode);
}
}
}
correctArrays(rootNode);
return rootNode.nodes;
}
exports.parseText = parseText;
/**
* Auto detects and converts the property type
* @param prop
*/
function convertProperty(prop) {
if (prop[0] == '*')
return undefined; // e.g. array size
if (prop[0] == '"')
return prop.substr(1, prop.length - 2);
if (prop == 'T')
return true;
if (prop == 'F')
return false;
if (prop == 'Y')
return true;
if (prop == 'N')
return false;
if (prop.indexOf('.') != -1)
return parseFloat(prop);
var n = BigInt(prop);
if (n < Number.MIN_SAFE_INTEGER || n > Number.MAX_SAFE_INTEGER)
return n;
return Number(n);
}