File headers: use SPDX license identifiers
[blender-addons.git] / io_scene_fbx / json2fbx.py
blob5e8d177e72428c7864875f7b845b8da9ecdcea12
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: GPL-2.0-or-later
4 # <pep8 compliant>
6 # Script copyright (C) 2014 Blender Foundation
8 """
9 Usage
10 =====
12 json2fbx [FILES]...
14 This script will write a binary FBX file for each JSON argument given.
17 Input
18 ======
20 The JSON data is formatted into a list of nested lists of 4 items:
22 ``[id, [data, ...], "data_types", [subtree, ...]]``
24 Where each list may be empty, and the items in
25 the subtree are formatted the same way.
27 data_types is a string, aligned with data that spesifies a type
28 for each property.
30 The types are as follows:
32 * 'Y': - INT16
33 * 'C': - BOOL
34 * 'I': - INT32
35 * 'F': - FLOAT32
36 * 'D': - FLOAT64
37 * 'L': - INT64
38 * 'R': - BYTES
39 * 'S': - STRING
40 * 'f': - FLOAT32_ARRAY
41 * 'i': - INT32_ARRAY
42 * 'd': - FLOAT64_ARRAY
43 * 'l': - INT64_ARRAY
44 * 'b': - BOOL ARRAY
45 * 'c': - BYTE ARRAY
47 Note that key:value pairs aren't used since the id's are not
48 ensured to be unique.
49 """
52 def elem_empty(elem, name):
53 import encode_bin
54 sub_elem = encode_bin.FBXElem(name)
55 if elem is not None:
56 elem.elems.append(sub_elem)
57 return sub_elem
60 def parse_json_rec(fbx_root, json_node):
61 name, data, data_types, children = json_node
62 ver = 0
64 assert(len(data_types) == len(data))
66 e = elem_empty(fbx_root, name.encode())
67 for d, dt in zip(data, data_types):
68 if dt == "C":
69 e.add_bool(d)
70 elif dt == "Y":
71 e.add_int16(d)
72 elif dt == "I":
73 e.add_int32(d)
74 elif dt == "L":
75 e.add_int64(d)
76 elif dt == "F":
77 e.add_float32(d)
78 elif dt == "D":
79 e.add_float64(d)
80 elif dt == "R":
81 d = eval('b"""' + d + '"""')
82 e.add_bytes(d)
83 elif dt == "S":
84 d = d.encode().replace(b"::", b"\x00\x01")
85 e.add_string(d)
86 elif dt == "i":
87 e.add_int32_array(d)
88 elif dt == "l":
89 e.add_int64_array(d)
90 elif dt == "f":
91 e.add_float32_array(d)
92 elif dt == "d":
93 e.add_float64_array(d)
94 elif dt == "b":
95 e.add_bool_array(d)
96 elif dt == "c":
97 e.add_byte_array(d)
99 if name == "FBXVersion":
100 assert(data_types == "I")
101 ver = int(data[0])
103 for child in children:
104 _ver = parse_json_rec(e, child)
105 if _ver:
106 ver = _ver
108 return ver
111 def parse_json(json_root):
112 root = elem_empty(None, b"")
113 ver = 0
115 for n in json_root:
116 _ver = parse_json_rec(root, n)
117 if _ver:
118 ver = _ver
120 return root, ver
123 def json2fbx(fn):
124 import os
125 import json
127 import encode_bin
129 fn_fbx = "%s.fbx" % os.path.splitext(fn)[0]
130 print("Writing: %r " % fn_fbx, end="")
131 json_root = []
132 with open(fn) as f_json:
133 json_root = json.load(f_json)
134 fbx_root, fbx_version = parse_json(json_root)
135 print("(Version %d) ..." % fbx_version)
136 encode_bin.write(fn_fbx, fbx_root, fbx_version)
139 # ----------------------------------------------------------------------------
140 # Command Line
142 def main():
143 import sys
145 if "--help" in sys.argv:
146 print(__doc__)
147 return
149 for arg in sys.argv[1:]:
150 try:
151 json2fbx(arg)
152 except:
153 print("Failed to convert %r, error:" % arg)
155 import traceback
156 traceback.print_exc()
159 if __name__ == "__main__":
160 main()