blender2lua_export.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. bl_info = {
  2. "name": "Blender to Lua",
  3. "author": "Niels Nesse",
  4. "blender": (2, 69, 0),
  5. "location": "File > Import-Export",
  6. "description": "Write blend data to a LUA script + a binary blob",
  7. "warning": "",
  8. "wiki_url": "",
  9. "tracker_url": "",
  10. "support": 'COMMUNITY',
  11. "category": "Import-Export"}
  12. import bpy
  13. import mathutils
  14. import array
  15. import bmesh
  16. import math
  17. from bpy.props import (StringProperty)
  18. from bpy_extras.io_utils import (ExportHelper)
  19. #
  20. # The blender to lua exporter generates a pair of files, a LUA fragment with the extension '.b2l'
  21. # and a binary file with the extension '.b2l.bin'. The LUA fragment returns the file's
  22. # scene graph as a single LUA table which references blocks of data in the binary file.
  23. # Only integers, strings, and boolean values are stored in the LUA tables while matrix
  24. # transforms and bulk vertex and animation data are stored in the binary file
  25. #
  26. # Each section below describes the structure of a type of table returned by the LUA
  27. # fragment. Each table field is described with it's data type and the following
  28. # convensions are followed:
  29. #
  30. # - Identifiers named "X_table" refer to instances of table type X.
  31. #
  32. # - Field names ending in "_offset" are byte offsets into the binary file.
  33. # The field's type is described in terms of C data types and
  34. # fields in the containing table.
  35. #
  36. # - The end of some table descriptions contain a line with the format "Y, Y, ...". This
  37. # indicates that the table also contains a sequence of values of type 'Y' in addition
  38. # to the specified named values.
  39. #
  40. # root_table:
  41. #
  42. # scenes : {[scene_name] = scene_table, ...}
  43. #
  44. # meshes : {[mesh_name] = mesh_table, ...}
  45. #
  46. # objects : {[object_name] = object_table, ...}
  47. #
  48. # armatures : {[armature_name] = armature_table, ...}
  49. #
  50. # scene_table:
  51. #
  52. # frame_start : integer
  53. #
  54. # First frame of animation
  55. #
  56. # frame_end : integer
  57. #
  58. # Last frame of animation
  59. #
  60. # frame_step : float
  61. #
  62. # Number of frames per "step"
  63. #
  64. # objects : { object_name, object_name, ... }
  65. #
  66. # List of objects belonging to the scene
  67. #
  68. # object_table:
  69. #
  70. # type : string
  71. #
  72. # Type of data this object refers to. One of 'MESH', 'CURVE', 'SURFACE', 'META',
  73. # 'FONT', 'ARMATURE', 'LATTICE', 'EMPTY', 'CAMERA', 'LAMP', 'SPEAKER'
  74. #
  75. # data : string
  76. #
  77. # Name of data this object refers to. The data can be located by indexing the
  78. # appropriate sub-table of the root table. For instance if 'type' is
  79. # 'ARMATURE' then the data can be found in 'root_table.armatures[data]'.
  80. #
  81. # parent : string
  82. #
  83. # Name of the parent object
  84. #
  85. # parent_type : string
  86. #
  87. # One of 'OBJECT', 'BONE', 'VERTEX', or 'VERTEX_3'.
  88. #
  89. # - If the value is 'OBJECT' then this object's transform is relative to it's
  90. # parent's object transform.
  91. #
  92. # - If the value is 'BONE' then this object's transform is relative to the
  93. # transform of the bone 'parent_bone' in the parent object.
  94. #
  95. # - If the value is 'VERTEX' then this object's transform is relative to the
  96. # vertex number 'parent_vertex' in the parent object.
  97. #
  98. # - If the value is 'VERTEX_3' then this object's transform is relative to
  99. # and oritened by the vertex triple 'parent_verticies' in the parent
  100. # object. TODO: Need to investigate the exact formula used in this case
  101. #
  102. # parent_bone : string (optional)
  103. #
  104. # Bone the the parent object that this object is parented to. See 'parent_type'
  105. #
  106. # parent_vertex : integer (optional)
  107. #
  108. # Index of the vertex in the parent object that this object is parented to. See
  109. # 'parent_type'.
  110. #
  111. # parent_verticies : {integer, integer, integer} (optional)
  112. #
  113. # Three vertex indicies into the parent object's mesh that define
  114. # the local space that this object is parented to. See 'parent_type'.
  115. #
  116. # num_frames : integer
  117. #
  118. # Number of animation frames stored in transform arrays (see below). This
  119. # value will be set to 1 if the object is not animated.
  120. #
  121. # armature_deform : string (optional)
  122. #
  123. # If set then the object is deformed by the armature named 'armature_deform'
  124. #
  125. # object_transform_array_offset : integer
  126. #
  127. # float object_transform_array[num_frames][4][4]
  128. #
  129. # Array of transforms for this object relative to the parent object space.
  130. #
  131. # vertex_groups : {group_name, group_name, ... } (optional)
  132. #
  133. # Names of the vertex groups for this object.
  134. #
  135. # vertex_group_transform_array_offset: integer (optional)
  136. #
  137. # float vertex_group_transform_array[num_frames][#vertex_groups][4][4]
  138. #
  139. # Tranforms to be applied to each vertex group in object space, according
  140. # to the weights stored in the associated mesh.
  141. #
  142. # nla_tracks : {nla_track_table, nla_track_table, ...} (optional)
  143. #
  144. # Array of NLA tracks in bottom up order
  145. #
  146. # nla_track_table:
  147. #
  148. # name : string
  149. #
  150. # Name of NLA track
  151. #
  152. # nla_strip_table, nla_strip_table, ...
  153. #
  154. # nls_strip_table:
  155. #
  156. # name : string
  157. #
  158. # Name of NLA strip
  159. #
  160. # action : string
  161. #
  162. # Name of action referenced by this strip
  163. #
  164. # frame_start : integer
  165. #
  166. # First frame of strip
  167. #
  168. # frame_end : integer
  169. #
  170. # Last frame of strip
  171. #
  172. # mesh_table:
  173. #
  174. # num_triangles : integer
  175. #
  176. # Number of triangles in mesh
  177. #
  178. # num_vertices : integer
  179. #
  180. # Number of verticies in mesh
  181. #
  182. # uv_layers : { [uv_layer_name] = uv_layer_table, ...}
  183. #
  184. # The UV layers for this mesh
  185. #
  186. # num_vertex_weights : integer
  187. #
  188. # Total number of vertex weights stored in mesh data
  189. #
  190. # submeshes : { submesh_table, submesh_table, ... }
  191. #
  192. # index_array_offset : uint16_t index_array[num_triangles][3]
  193. #
  194. # Vertex array indicies for mesh triangles
  195. #
  196. # vertex_co_array_offset : float coord_array[num_verticies][3]
  197. #
  198. # Vertex coordinates
  199. #
  200. # vertex_normal_array_offset : float normal_array[num_verticies][3]
  201. #
  202. # Vertex normals
  203. #
  204. # weights_per_vertex : integer
  205. #
  206. # Number of weights stored for each vertex. This will be 0
  207. # if no verticies are assigned to any groups
  208. #
  209. # weights_array_offset : (optional)
  210. #
  211. # struct weight_element {
  212. # int16_t group_index;
  213. # int16_t weight;
  214. # }
  215. #
  216. # struct weight_element weights_array[num_verticies][weights_per_vertex];
  217. #
  218. # Weighted vertex group assignments for each vertex. Weights are expressed as 15-bit
  219. # signed fixed point values so that 2^14 = 1.0f. Elements are pre-sorted in reverse
  220. # weight order so that the largest weights appear first. If a vertex belongs to fewer than
  221. # 'weights_per_vertex' groups then the array is padded with elements with 'group_index'
  222. # set to -1 and `weight` set to zero.
  223. #
  224. # uv_layer_table:
  225. #
  226. # uv_array_offset: float uv[num_verticies][2]
  227. #
  228. # UV coordinate arrays
  229. #
  230. # tangent_array_offset: struct { float tangent[3]; float bitangent_sign; } tangent[num_verticies];
  231. #
  232. # Defines the tangent space for this UV mapping. The bitangent vector is given by:
  233. #
  234. # cross(tangent, normal) * bitangent_sign
  235. #
  236. # submesh_table:
  237. #
  238. # material_name : string
  239. #
  240. # Name of the material for this submesh. B2L does not store any material
  241. # data directly but submeshes with the same material name should have the same
  242. # material properties.
  243. #
  244. # triangle_no : integer
  245. #
  246. # First triangle in 'index_array' of this submesh
  247. #
  248. # triangle_count : integer
  249. #
  250. # Number of triangles in this submesh
  251. #
  252. # armature_table:
  253. #
  254. # tail_array_offset : integer
  255. #
  256. # float tail_array[#armature_table][3]
  257. #
  258. # Array of bone tail positions in object local
  259. #
  260. # transform_array_offset : integer
  261. #
  262. # float transform_array[#armature_table][4][4]
  263. #
  264. # Array of bone transforms in object local space. Stored as 4x4 column
  265. # major order matricies. Position (0,0,0) in bone space is the location
  266. # of the head of the bone
  267. #
  268. # bone_table, bone_table, ...
  269. #
  270. # bone_table:
  271. #
  272. # name : string
  273. #
  274. # Name of the bone
  275. #
  276. # parent : string
  277. #
  278. # Name of parent bone or nil if the bone has no parent
  279. #
  280. class export_B2L(bpy.types.Operator, ExportHelper):
  281. """Save a B2L File"""
  282. bl_idname = "export_scene.b2l"
  283. bl_label = 'Export B2L'
  284. bl_options = {'PRESET'}
  285. filename_ext = ".b2l"
  286. filter_glob = StringProperty(default="*.B2L", options={'HIDDEN'})
  287. check_extension = True
  288. def execute(self, context):
  289. keywords = self.as_keywords(ignore=("filter_glob", "check_existing"))
  290. return save_b2l(self, context, **keywords)
  291. def menu_func_export(self, context):
  292. self.layout.operator(export_B2L.bl_idname, text="Blender to Lua (.b2l)")
  293. def register():
  294. bpy.utils.register_module(__name__)
  295. bpy.types.INFO_MT_file_export.append(menu_func_export)
  296. def unregister():
  297. bpy.utils.unregister_module(__name__)
  298. bpy.types.INFO_MT_file_export.remove(menu_func_export)
  299. def mesh_triangulate(me):
  300. bm = bmesh.new()
  301. bm.from_mesh(me)
  302. bmesh.ops.triangulate(bm, faces=bm.faces)
  303. bm.to_mesh(me)
  304. bm.free()
  305. return
  306. def lua_string(s):
  307. return "'%s'" % s.replace("'","\\'")
  308. def lua_vec3(v):
  309. return "{%f,%f,%f}" % v.to_tuple()
  310. def lua_vec4(v):
  311. return "{%f,%f,%f,%f}" % v.to_tuple()
  312. def lua_mat4(m):
  313. return "{%s,%s,%s,%s}" % tuple(lua_vec4(m[i]) for i in range(4))
  314. def lua_array3f(a):
  315. return "{%f,%f,%f}" % (a[0],a[1],a[2])
  316. def lua_array4f(a):
  317. return "{%f,%f,%f,%f}" % (a[0],a[1],a[2],a[3])
  318. def write_mesh(write, blob_file, materials, name, mesh):
  319. mesh = mesh.copy() #Make a copy of the mesh so we can alter it
  320. mesh_triangulate(mesh)
  321. mesh.calc_normals_split()
  322. num_uv_layers = len(mesh.uv_layers)
  323. smooth_groups, num_groups = mesh.calc_smooth_groups()
  324. if len(mesh.polygons) == 0:
  325. return
  326. vertex_dict = {} #Dictionary to identify when a vertex is shared by multiple triangles
  327. loop_to_vertex_num = [None] * len(mesh.loops) #Vertex index in output array for a loop
  328. index_array = array.array('H') #Vertex index triplets for mesh triangles
  329. vertex_co_array = array.array('f') #Vertex coordinates
  330. vertex_normal_array = array.array('f') #Vertex normals
  331. weights_array = array.array('h') # Vertex weights
  332. vertex_count = 0
  333. submeshes = {}
  334. weights_per_vert = 0
  335. vertex_list = []
  336. vertex_list_mesh_loop = []
  337. for polygon_index, polygon in enumerate(mesh.polygons):
  338. if polygon.material_index not in submeshes:
  339. submeshes[polygon.material_index] = [polygon]
  340. else:
  341. submeshes[polygon.material_index].append(polygon)
  342. for loop_index in polygon.loop_indices:
  343. vertex_key_l = [mesh.loops[loop_index].vertex_index, smooth_groups[polygon_index], polygon.material_index]
  344. for uv_layer in mesh.uv_layers:
  345. vertex_key_l.extend(uv_layer.data[loop_index].uv)
  346. vertex_key = tuple(vertex_key_l)
  347. if vertex_key in vertex_dict:
  348. vertex_num = vertex_dict[vertex_key]
  349. else:
  350. mesh_loop = mesh.loops[loop_index]
  351. vertex = mesh.vertices[mesh_loop.vertex_index]
  352. vertex_dict[vertex_key] = vertex_count
  353. vertex_num = vertex_count
  354. vertex_count = vertex_count + 1
  355. vertex_co_array.extend(vertex.undeformed_co)
  356. vertex_normal_array.extend(mesh_loop.normal)
  357. groups_copy = []
  358. for elem in vertex.groups:
  359. temp = (elem.group, elem.weight)
  360. groups_copy.append(temp)
  361. groups_sorted = sorted(groups_copy, key = lambda x: x[1], reverse = True)
  362. vertex_list_mesh_loop.append(loop_index)
  363. vertex_list.append(groups_sorted)
  364. weights_per_vert = max(weights_per_vert, len(groups_sorted))
  365. loop_to_vertex_num[loop_index] = vertex_num
  366. if weights_per_vert > 0:
  367. for vertex in vertex_list:
  368. for i, elem in enumerate(vertex):
  369. weights_array.append(elem[0])
  370. weights_array.append(int(elem[1] * 128 * 64))
  371. for i in range(len(vertex), weights_per_vert):
  372. weights_array.append(-1)
  373. weights_array.append(0)
  374. write("\t['%s'] = {\n" % name)
  375. write("\t\tnum_triangles = %d,\n" % len(mesh.polygons))
  376. write("\t\tnum_verticies = %d,\n" % vertex_count)
  377. write("\t\tuv_layers = {\n")
  378. for uv_layer in mesh.uv_layers:
  379. tangent_array = array.array('f') #Vertex tangent and bitangent
  380. uv_array = array.array('f') #Vertex normals
  381. mesh.calc_tangents(uv_layer.name)
  382. write("\t\t\t[%s] = {\n" % lua_string(uv_layer.name))
  383. for loop_index in vertex_list_mesh_loop:
  384. mesh_loop = mesh.loops[loop_index]
  385. tangent_array.extend(mesh_loop.tangent)
  386. tangent_array.append(mesh_loop.bitangent_sign)
  387. uv_array.extend(uv_layer.data[loop_index].uv)
  388. write("\t\t\t\tuv_array_offset = %d,\n" % blob_file.tell())
  389. uv_array.tofile(blob_file)
  390. write("\t\t\t\ttangent_array_offset = %d,\n" % blob_file.tell())
  391. tangent_array.tofile(blob_file)
  392. write("\t\t\t},\n")
  393. mesh.free_tangents()
  394. write("\t\t},\n");
  395. write("\t\tweights_per_vertex = %d,\n" % weights_per_vert);
  396. write("\t\tsubmeshes = {\n")
  397. triangle_no = 0
  398. for material_index, submesh in submeshes.items():
  399. write("\t\t\t{\n")
  400. write("\t\t\t\tmaterial_name = %s,\n" % (lua_string(materials[material_index].name)))
  401. write("\t\t\t\ttriangle_no = %d,\n" % triangle_no)
  402. write("\t\t\t\ttriangle_count = %d,\n" % len(submesh))
  403. for polygon in submesh:
  404. triangle_no = triangle_no + 1
  405. for loop_index in polygon.loop_indices:
  406. index_array.append(loop_to_vertex_num[loop_index])
  407. write("\t\t\t},\n")
  408. write("\t\t},\n")
  409. write("\t\tindex_array_offset = %d,\n" % blob_file.tell())
  410. index_array.tofile(blob_file)
  411. write("\t\tvertex_co_array_offset = %d,\n" % blob_file.tell())
  412. vertex_co_array.tofile(blob_file)
  413. write("\t\tvertex_normal_array_offset = %d,\n" % blob_file.tell())
  414. vertex_normal_array.tofile(blob_file)
  415. if weights_per_vert > 0:
  416. write("\t\tweights_array_offset = %d,\n" % blob_file.tell())
  417. weights_array.tofile(blob_file)
  418. write("\t},\n");
  419. bpy.data.meshes.remove(mesh)
  420. return
  421. def write_armature(write, blob_file, armature):
  422. tail_array = array.array('f')
  423. transform_array = array.array('f')
  424. def write_bone(write, blob_file, bone):
  425. write("\t\t{\n")
  426. write("\t\t\tname = %s,\n" % lua_string(bone.name))
  427. if bone.parent:
  428. write("\t\t\tparent=%s,\n" % lua_string(bone.parent.name))
  429. flatten_4x4mat(transform_array, bone.matrix_local)
  430. tail_array.append(bone.tail_local[0])
  431. tail_array.append(bone.tail_local[1])
  432. tail_array.append(bone.tail_local[2])
  433. write("\t\t},\n")
  434. return
  435. write("\t[%s] = {\n" % lua_string(armature.name))
  436. for bone in armature.bones:
  437. write_bone(write, blob_file, bone)
  438. write("\t\ttail_array_offset = %d,\n" % blob_file.tell())
  439. tail_array.tofile(blob_file)
  440. write("\t\ttransform_array_offset = %d,\n" % blob_file.tell())
  441. transform_array.tofile(blob_file)
  442. write("\t}\n")
  443. return
  444. def flatten_4x4mat(dest, src):
  445. for i in range(4):
  446. for j in range(4):
  447. dest.append(src[j][i])
  448. def write_object(scene, write, blob_file, obj):
  449. write("\t[%s] = {\n" % lua_string(obj.name))
  450. if obj.parent:
  451. write("\t\tparent = %s,\n" % lua_string(obj.parent.name))
  452. write("\t\tparent_type = %s,\n" % lua_string(obj.parent_type))
  453. if obj.parent_type == 'BONE':
  454. write("\t\tparent_bone = %s,\n" % lua_string(obj.parent_type))
  455. elif obj.parent_type == 'VERTEX':
  456. write("\t\tparent_vertex = %d,\n" % obj.parent_verticies[0])
  457. elif obj.parent_type == 'VERTEX_3':
  458. write("\t\tparent_vertices = {%d,%d,%d},\n" % (obj.parent_verticies[0], obj.parent_verticies[1],obj.parent_verticies[2]))
  459. write("\t\ttype = %s,\n" % lua_string(obj.type))
  460. if obj.data:
  461. write("\t\tdata = %s,\n" % lua_string(obj.data.name))
  462. if len(obj.vertex_groups) > 0:
  463. write("\t\tvertex_groups = {\n")
  464. for group in obj.vertex_groups:
  465. write("\t\t\t\t%s,\n" % lua_string(group.name))
  466. write("\t\t},\n")
  467. aobj = None
  468. for modifier in obj.modifiers:
  469. if modifier.type == 'ARMATURE':
  470. aobj = modifier.object
  471. write("\t\tarmature_deform = %s,\n" % lua_string(aobj.name))
  472. break
  473. if (obj.animation_data is not None):
  474. def write_nla_strip(strip):
  475. if strip.mute is True:
  476. return
  477. write("\t\t\t\t{\n")
  478. write("\t\t\t\t\tname = %s,\n" % lua_string(strip.name))
  479. write("\t\t\t\t\tframe_start = %d,\n" % strip.frame_start)
  480. write("\t\t\t\t\tframe_end = %d,\n" % strip.frame_end)
  481. write("\t\t\t\t},\n")
  482. def write_nla_track(track):
  483. if track.mute is True:
  484. return
  485. write("\t\t\t{\n")
  486. write("\t\t\t\tname = %s,\n" % lua_string(track.name))
  487. for strip in track.strips:
  488. write_nla_strip(strip)
  489. write("\t\t\t},\n")
  490. if obj.animation_data and len(obj.animation_data.nla_tracks) > 0:
  491. write("\t\tnla_tracks = {\n")
  492. for track in obj.animation_data.nla_tracks:
  493. write_nla_track(track)
  494. write("\t\t},\n")
  495. write("\t},\n")
  496. def save_b2l(operator, context, filepath=""):
  497. lua_file = open(filepath, "wt")
  498. blob_file = open(filepath + ".bin", "wb")
  499. def write_lua(s):
  500. lua_file.write(s)
  501. file = open(filepath, "wt")
  502. #Write blend data as LUA script
  503. write_lua("return {\n")
  504. write_lua("scenes = {\n")
  505. for scene in context.blend_data.scenes:
  506. write_lua("\t[%s] = {\n" % lua_string(scene.name))
  507. write_lua("\t\tframe_start = %f,\n" % scene.frame_start)
  508. write_lua("\t\tframe_end= %f,\n" % scene.frame_end)
  509. write_lua("\t\tframe_step = %f,\n" % scene.frame_step)
  510. write_lua("\t\tobjects = {\n")
  511. for obj in scene.objects:
  512. write_lua("\t\t\t[%s] = {\n" % lua_string(obj.name))
  513. object_transform_array = array.array('f')
  514. vertex_group_transform_array = array.array('f')
  515. aobj = None
  516. for modifier in obj.modifiers:
  517. if modifier.type == 'ARMATURE':
  518. aobj = modifier.object
  519. break
  520. def write_object_frame():
  521. flatten_4x4mat(object_transform_array, obj.matrix_local)
  522. for group in obj.vertex_groups:
  523. if aobj and (group.name in aobj.pose.bones):
  524. pbone = aobj.pose.bones[group.name]
  525. matrix_local_inv = mathutils.Matrix.copy(obj.matrix_local)
  526. mathutils.Matrix.invert(matrix_local_inv)
  527. rest_bone_inv = mathutils.Matrix.copy(pbone.bone.matrix_local)
  528. mathutils.Matrix.invert(rest_bone_inv)
  529. #TODO: we are assuming that the armature is our immediate parent which is probably
  530. # but not neccisarily true
  531. flatten_4x4mat(vertex_group_transform_array, matrix_local_inv * pbone.matrix * rest_bone_inv * obj.matrix_local)
  532. else:
  533. flatten_4x4mat(vertex_group_transform_array, mathutils.Matrix.Identity(4))
  534. frame = scene.frame_start
  535. scene.frame_set(frame)
  536. num_frames = 0
  537. if (obj.animation_data) or (aobj and aobj.animation_data):
  538. while frame < scene.frame_end:
  539. write_object_frame()
  540. frame = frame + 1
  541. scene.frame_set(frame)
  542. num_frames = num_frames + 1
  543. else:
  544. write_object_frame()
  545. num_frames = num_frames + 1
  546. write_lua("\t\t\t\tnum_frames = %d,\n" % num_frames)
  547. write_lua("\t\t\t\tobject_transform_array_offset = %d,\n" % blob_file.tell())
  548. object_transform_array.tofile(blob_file)
  549. if len(obj.vertex_groups) > 0:
  550. write_lua("\t\t\t\tvertex_group_transform_array_offset = %d,\n" % blob_file.tell())
  551. vertex_group_transform_array.tofile(blob_file)
  552. write_lua("\t\t\t},\n") #Object
  553. write_lua("\t\t},\n") #Objects
  554. write_lua("\t},\n") #Scene
  555. write_lua("},\n") #Scenes
  556. write_lua("objects = {\n")
  557. for obj in context.blend_data.objects:
  558. write_object(context.scene, write_lua, blob_file, obj)
  559. write_lua("},\n")
  560. write_lua("meshes={\n")
  561. for mesh in context.blend_data.meshes:
  562. write_mesh(write_lua, blob_file, context.blend_data.materials, mesh.name, mesh)
  563. write_lua("},\n")
  564. write_lua("armatures={\n")
  565. for armature in context.blend_data.armatures:
  566. write_armature(write_lua, blob_file, armature)
  567. write_lua("},\n")
  568. write_lua("materials={\n")
  569. for material in context.blend_data.materials:
  570. write_lua("\t%s,\n" % lua_string(material.name))
  571. write_lua("},\n")
  572. write_lua("}\n")
  573. lua_file.close()
  574. blob_file.close()
  575. return {'FINISHED'}