1 '''Provides tools for building models.'''
2 from logging
import info
3 from os
import system
, walk
, makedirs
4 from os
.path
import exists
, basename
, dirname
6 from hashlib
import md5
7 from shutil
import copyfile
, move
, rmtree
8 from lib
.build
.mtprocesser
import ProcesserMgr
9 from lib
.build
.build
import to_be_built
12 class ModelsBuilder():
15 self
._cache
_files
= [] # for avoiding rebuilding the same file
17 def build(self
, blend_path
, cores
):
18 '''Builds the models i.e. creates glTF and bam files from blend
20 mp_mgr
= ProcesserMgr(cores
)
21 for root
, _
, fnames
in walk(blend_path
):
22 for fname
in [fname
for fname
in fnames
if fname
.endswith('.blend')]:
23 if '/prototypes/' not in root
:
24 self
._export
_blend
(root
, fname
, mp_mgr
)
27 if exists('hash_cache.txt'):
28 with
open('hash_cache.txt') as fhash
:
29 lines
= fhash
.readlines()
30 for line
in lines
: # line's e.g. assets/path/to/gltf_or_png.ext 68ced1
31 line_spl
= line
.split()
32 hashval
= line_spl
[-1]
33 fname
= ' '.join(line_spl
[:-1])
34 if fname
not in self
._cache
_files
:
35 cache
+= [(fname
, hashval
)]
36 for cfile
in self
._cache
_files
:
37 cache
+= [(cfile
, md5(open(cfile
, 'rb').read()).hexdigest())]
39 with
open('hash_cache.txt', 'w') as fhash
:
40 fhash
.write('\n'.join([' '.join(line
) for line
in cache
]))
42 def _export_blend(self
, root
, fname
, mp_mgr
):
43 '''Exports blend files to glTF and bam formats.'''
44 if self
._export
_gltf
(root
, fname
):
45 self
._export
_bam
(root
, fname
, mp_mgr
)
47 def _export_gltf(self
, root
, fname
):
48 '''Exports glTF files from blend ones.'''
49 _fname
= '%s/%s' % (root
, fname
)
50 files_before
= [basename(gname
) for gname
in glob('./*')]
51 cmd
= 'blender %s --background --python lib/build/blend2gltf.py '
53 cmd
= cmd
% (_fname
, fname
[:-6])
54 pgltf
= 'assets/models/gltf/'
55 gltf_name
= _fname
.replace('assets/models/blend/', pgltf
)
56 gltf_name
= gltf_name
.replace('.blend', '.gltf')
57 if not to_be_built(gltf_name
, [_fname
]):
60 self
._cache
_files
+= [_fname
, gltf_name
]
61 files_after
= [basename(gname
) for gname
in glob('./*')]
62 new_files
= [nnm
for nnm
in files_after
if nnm
not in files_before
]
63 new_dir
= root
.replace('assets/models/blend/', pgltf
)
64 rmtree(new_dir
, ignore_errors
=True)
66 for mname
in new_files
:
67 new_name
= '%s/%s' % (new_dir
, mname
)
69 info('move %s %s' % (mname
, new_name
))
70 # # blender rewrites metal files: let's restore them
71 # metal_files = [fnm for fnm in glob(new_dir + '/*') if 'metal' in fnm]
72 # for metal_file in metal_files:
73 # src = metal_file.replace(pgltf, 'assets/models/')
75 # src = metal_file.replace(pgltf, 'assets/models/prototypes/')
76 # src_split = src.split('/')
77 # src_tracks_idx = src_split.index('tracks')
78 # before = src_split[:src_tracks_idx]
79 # after = src_split[src_tracks_idx + 2:]
80 # src = '/'.join(before + after)
81 # copyfile(src, metal_file)
84 def _export_bam(self
, root
, fname
, mp_mgr
):
85 '''Exports bam files from glTF ones.'''
86 _fname
= '%s/%s' % (root
, fname
)
87 gltf_name
= (_fname
[:-5] + 'gltf').replace('/blend/', '/gltf/', 1)
88 bam_name
= (_fname
[:-5] + 'bam').replace('/blend/', '/bam/', 1)
89 cmd_args
= gltf_name
, bam_name
90 # use dds files in place of png/jpg in gltf2bam
91 copyfile(gltf_name
, gltf_name
+ '.tmp')
92 with
open(gltf_name
) as fgltf
:
93 lines
= fgltf
.readlines()
96 if ('.png' in line
or '.jpg' in line
) and '"uri"' in line
:
97 rln
= line
[line
.index('"uri"') + 9:].rstrip(',\n"')
98 tname
= '%s/%s' % (root
, rln
)
99 deps
+= [tname
.replace('/models/blend/', '/models/gltf/', 1)]
101 tgt
= dep
.replace('/gltf/', '/bam/', 1)
102 tgt
= tgt
.replace('.png', '.dds').replace('.jpg', '.dds')
103 makedirs(dirname(tgt
), exist_ok
=True)
104 info('convert %s %s' % (dep
, tgt
))
105 system('convert %s %s' % (dep
, tgt
))
106 rpl
= lambda lin
: lin
.replace('.png', '.dds').replace('.jpg', '.dds').replace('/png', '/dds').replace('/jpg', '/dds')
107 with
open(gltf_name
, 'w') as fgltf
:
108 fgltf
.write(''.join([rpl(line
) for line
in lines
]))
109 makedirs(dirname(bam_name
), exist_ok
=True)
110 if to_be_built(bam_name
, deps
):
111 mp_mgr
.add('gltf2bam %s %s' % cmd_args
)
112 self
._cache
_files
+= [gltf_name
] + deps