1 '''Provides tools for building models.'''
2 from logging
import info
3 from os
import system
, walk
, makedirs
4 from os
.path
import exists
, dirname
5 from multiprocessing
import Pool
6 from hashlib
import md5
7 from shutil
import copyfile
, rmtree
8 from ya2
.build
.build
import to_be_built
11 class ModelsBuilder():
14 self
._cache
_files
= [] # for avoiding rebuilding the same file
16 def build(self
, blend_path
, cores
):
17 '''Builds the models i.e. creates glTF and bam files from blend
20 for root
, _
, fnames
in walk(blend_path
):
21 blends
= [fname
for fname
in fnames
if fname
.endswith('.blend')]
23 if '/prototypes/' not in root
:
24 args
+= [(root
, fname
)]
26 p
.starmap(self
._export
_blend
, args
)
27 # caching is broken now: it is based on the previous
28 # non-multiprocessing approach
29 # i should evaluate if fix it or just change the blend_path for
30 # building only specific models
32 if exists('hash_cache.txt'):
33 with
open('hash_cache.txt') as fhash
:
34 lines
= fhash
.readlines()
35 for line
in lines
: # line's e.g. assets/path/to/gltf_or_png.ext 68ced1
36 line_spl
= line
.split()
37 hashval
= line_spl
[-1]
38 fname
= ' '.join(line_spl
[:-1])
39 if fname
not in self
._cache
_files
:
40 cache
+= [(fname
, hashval
)]
41 for cfile
in self
._cache
_files
:
42 cache
+= [(cfile
, md5(open(cfile
, 'rb').read()).hexdigest())]
44 with
open('hash_cache.txt', 'w') as fhash
:
45 fhash
.write('\n'.join([' '.join(line
) for line
in cache
]))
47 def _export_blend(self
, root
, fname
):
48 '''Exports blend files to glTF and bam formats.'''
49 if self
._export
_gltf
(root
, fname
):
50 self
._export
_bam
(root
, fname
)
52 def _export_gltf(self
, root
, fname
):
53 '''Exports glTF files from blend ones.'''
54 _fname
= '%s/%s' % (root
, fname
)
55 pgltf
= 'assets/models/gltf/'
56 new_dir
= root
.replace('assets/models/blend/', pgltf
)
57 rmtree(new_dir
, ignore_errors
=True)
59 # files_before = [basename(gname) for gname in glob('./*')]
60 cmd
= 'blender %s --background --python ya2/build/blend2gltf.py '
62 cmd
= cmd
% (_fname
, new_dir
+ '/' + fname
[:-6])
63 gltf_name
= _fname
.replace('assets/models/blend/', pgltf
)
64 gltf_name
= gltf_name
.replace('.blend', '.gltf')
65 if not to_be_built(gltf_name
, [_fname
]):
68 self
._cache
_files
+= [_fname
, gltf_name
]
69 # files_after = [basename(gname) for gname in glob('./*')]
70 # new_files = [nnm for nnm in files_after if nnm not in files_before]
71 # new_dir = root.replace('assets/models/blend/', pgltf)
72 # rmtree(new_dir, ignore_errors=True)
74 # for mname in new_files:
75 # new_name = '%s/%s' % (new_dir, mname)
76 # move(mname, new_name)
77 # info('move %s %s' % (mname, new_name))
78 # # blender rewrites metal files: let's restore them
79 # metal_files = [fnm for fnm in glob(new_dir + '/*') if 'metal' in fnm]
80 # for metal_file in metal_files:
81 # src = metal_file.replace(pgltf, 'assets/models/')
83 # src = metal_file.replace(pgltf, 'assets/models/prototypes/')
84 # src_split = src.split('/')
85 # src_tracks_idx = src_split.index('tracks')
86 # before = src_split[:src_tracks_idx]
87 # after = src_split[src_tracks_idx + 2:]
88 # src = '/'.join(before + after)
89 # copyfile(src, metal_file)
92 def _export_bam(self
, root
, fname
):
93 '''Exports bam files from glTF ones.'''
94 _fname
= '%s/%s' % (root
, fname
)
95 gltf_name
= (_fname
[:-5] + 'gltf').replace('/blend/', '/gltf/', 1)
96 bam_name
= (_fname
[:-5] + 'bam').replace('/blend/', '/bam/', 1)
97 cmd_args
= gltf_name
, bam_name
98 # use dds files in place of png/jpg in gltf2bam
99 copyfile(gltf_name
, gltf_name
+ '.tmp')
100 with
open(gltf_name
) as fgltf
:
101 lines
= fgltf
.readlines()
104 if ('.png' in line
or '.jpg' in line
) and '"uri"' in line
:
105 rln
= line
[line
.index('"uri"') + 9:].rstrip(',\n"')
106 tname
= '%s/%s' % (root
, rln
)
107 deps
+= [tname
.replace('/models/blend/', '/models/gltf/', 1)]
109 tgt
= dep
.replace('/gltf/', '/bam/', 1)
110 tgt
= tgt
.replace('.png', '.dds').replace('.jpg', '.dds')
111 makedirs(dirname(tgt
), exist_ok
=True)
112 info('convert %s %s' % (dep
, tgt
))
113 system('convert %s %s' % (dep
, tgt
))
116 lin
= lin
.replace('.png', '.dds')
117 lin
= lin
.replace('.jpg', '.dds')
118 lin
= lin
.replace('/png', '/dds')
119 return lin
.replace('/jpg', '/dds')
120 with
open(gltf_name
, 'w') as fgltf
:
121 fgltf
.write(''.join([rpl(line
) for line
in lines
]))
122 makedirs(dirname(bam_name
), exist_ok
=True)
123 if to_be_built(bam_name
, deps
):
124 system('gltf2bam %s %s' % cmd_args
)
125 self
._cache
_files
+= [bam_name
] + deps