159 lines
3.3 KiB
Python
159 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
# Script copyright (C) 2014 Blender Foundation
|
|
|
|
"""
|
|
Usage
|
|
=====
|
|
|
|
json2fbx [FILES]...
|
|
|
|
This script will write a binary FBX file for each JSON argument given.
|
|
|
|
|
|
Input
|
|
======
|
|
|
|
The JSON data is formatted into a list of nested lists of 4 items:
|
|
|
|
``[id, [data, ...], "data_types", [subtree, ...]]``
|
|
|
|
Where each list may be empty, and the items in
|
|
the subtree are formatted the same way.
|
|
|
|
data_types is a string, aligned with data that spesifies a type
|
|
for each property.
|
|
|
|
The types are as follows:
|
|
|
|
* 'Y': - INT16
|
|
* 'C': - BOOL
|
|
* 'I': - INT32
|
|
* 'F': - FLOAT32
|
|
* 'D': - FLOAT64
|
|
* 'L': - INT64
|
|
* 'R': - BYTES
|
|
* 'S': - STRING
|
|
* 'f': - FLOAT32_ARRAY
|
|
* 'i': - INT32_ARRAY
|
|
* 'd': - FLOAT64_ARRAY
|
|
* 'l': - INT64_ARRAY
|
|
* 'b': - BOOL ARRAY
|
|
* 'c': - BYTE ARRAY
|
|
|
|
Note that key:value pairs aren't used since the id's are not
|
|
ensured to be unique.
|
|
"""
|
|
|
|
|
|
def elem_empty(elem, name):
|
|
import encode_bin
|
|
sub_elem = encode_bin.FBXElem(name)
|
|
if elem is not None:
|
|
elem.elems.append(sub_elem)
|
|
return sub_elem
|
|
|
|
|
|
def parse_json_rec(fbx_root, json_node):
|
|
name, data, data_types, children = json_node
|
|
ver = 0
|
|
|
|
assert(len(data_types) == len(data))
|
|
|
|
e = elem_empty(fbx_root, name.encode())
|
|
for d, dt in zip(data, data_types):
|
|
if dt == "C":
|
|
e.add_bool(d)
|
|
elif dt == "Y":
|
|
e.add_int16(d)
|
|
elif dt == "I":
|
|
e.add_int32(d)
|
|
elif dt == "L":
|
|
e.add_int64(d)
|
|
elif dt == "F":
|
|
e.add_float32(d)
|
|
elif dt == "D":
|
|
e.add_float64(d)
|
|
elif dt == "R":
|
|
d = eval('b"""' + d + '"""')
|
|
e.add_bytes(d)
|
|
elif dt == "S":
|
|
d = d.encode().replace(b"::", b"\x00\x01")
|
|
e.add_string(d)
|
|
elif dt == "i":
|
|
e.add_int32_array(d)
|
|
elif dt == "l":
|
|
e.add_int64_array(d)
|
|
elif dt == "f":
|
|
e.add_float32_array(d)
|
|
elif dt == "d":
|
|
e.add_float64_array(d)
|
|
elif dt == "b":
|
|
e.add_bool_array(d)
|
|
elif dt == "c":
|
|
e.add_byte_array(d)
|
|
|
|
if name == "FBXVersion":
|
|
assert(data_types == "I")
|
|
ver = int(data[0])
|
|
|
|
for child in children:
|
|
_ver = parse_json_rec(e, child)
|
|
if _ver:
|
|
ver = _ver
|
|
|
|
return ver
|
|
|
|
|
|
def parse_json(json_root):
|
|
root = elem_empty(None, b"")
|
|
ver = 0
|
|
|
|
for n in json_root:
|
|
_ver = parse_json_rec(root, n)
|
|
if _ver:
|
|
ver = _ver
|
|
|
|
return root, ver
|
|
|
|
|
|
def json2fbx(fn):
|
|
import os
|
|
import json
|
|
|
|
import encode_bin
|
|
|
|
fn_fbx = "%s.fbx" % os.path.splitext(fn)[0]
|
|
print("Writing: %r " % fn_fbx, end="")
|
|
json_root = []
|
|
with open(fn) as f_json:
|
|
json_root = json.load(f_json)
|
|
fbx_root, fbx_version = parse_json(json_root)
|
|
print("(Version %d) ..." % fbx_version)
|
|
encode_bin.write(fn_fbx, fbx_root, fbx_version)
|
|
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Command Line
|
|
|
|
def main():
|
|
import sys
|
|
|
|
if "--help" in sys.argv:
|
|
print(__doc__)
|
|
return
|
|
|
|
for arg in sys.argv[1:]:
|
|
try:
|
|
json2fbx(arg)
|
|
except:
|
|
print("Failed to convert %r, error:" % arg)
|
|
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|