ya2 · news · projects · code · about

some cleaning
[pmachines.git] / ya2 / build / models.py
CommitLineData
8ee66edd
FC
1'''Provides tools for building models.'''
2from logging import info
3from os import system, walk, makedirs
e65a09cf 4from os.path import exists, dirname
218c8938 5from multiprocessing import Pool
8ee66edd 6from hashlib import md5
e65a09cf 7from shutil import copyfile, rmtree
53ddf3c3 8from ya2.build.build import to_be_built
8ee66edd
FC
9
10
11class ModelsBuilder():
12
13 def __init__(self):
14 self._cache_files = [] # for avoiding rebuilding the same file
15
16 def build(self, blend_path, cores):
17 '''Builds the models i.e. creates glTF and bam files from blend
18 ones.'''
218c8938 19 args = []
8ee66edd 20 for root, _, fnames in walk(blend_path):
e65a09cf
FC
21 blends = [fname for fname in fnames if fname.endswith('.blend')]
22 for fname in blends:
8ee66edd 23 if '/prototypes/' not in root:
218c8938
FC
24 args += [(root, fname)]
25 with Pool() as p:
26 p.starmap(self._export_blend, args)
27 # caching is broken now: it is based on the previous
28 # non-multiprocessing approach
e65a09cf
FC
29 # i should evaluate if fix it or just change the blend_path for
30 # building only specific models
8ee66edd
FC
31 cache, lines = [], []
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())]
43 cache = cache[-2048:]
44 with open('hash_cache.txt', 'w') as fhash:
45 fhash.write('\n'.join([' '.join(line) for line in cache]))
46
218c8938 47 def _export_blend(self, root, fname):
8ee66edd
FC
48 '''Exports blend files to glTF and bam formats.'''
49 if self._export_gltf(root, fname):
218c8938 50 self._export_bam(root, fname)
8ee66edd
FC
51
52 def _export_gltf(self, root, fname):
53 '''Exports glTF files from blend ones.'''
54 _fname = '%s/%s' % (root, fname)
218c8938
FC
55 pgltf = 'assets/models/gltf/'
56 new_dir = root.replace('assets/models/blend/', pgltf)
57 rmtree(new_dir, ignore_errors=True)
58 makedirs(new_dir)
e65a09cf 59 # files_before = [basename(gname) for gname in glob('./*')]
53ddf3c3 60 cmd = 'blender %s --background --python ya2/build/blend2gltf.py '
8ee66edd 61 cmd += '-- %s.gltf'
218c8938 62 cmd = cmd % (_fname, new_dir + '/' + fname[:-6])
420ce99a 63 gltf_name = _fname.replace('assets/models/blend/', pgltf)
8ee66edd
FC
64 gltf_name = gltf_name.replace('.blend', '.gltf')
65 if not to_be_built(gltf_name, [_fname]):
66 return False
67 system(cmd)
68 self._cache_files += [_fname, gltf_name]
e65a09cf
FC
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)
73 # makedirs(new_dir)
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))
420ce99a
FC
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/')
82 # if not exists(src):
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)
8ee66edd
FC
90 return True
91
218c8938 92 def _export_bam(self, root, fname):
8ee66edd
FC
93 '''Exports bam files from glTF ones.'''
94 _fname = '%s/%s' % (root, fname)
420ce99a
FC
95 gltf_name = (_fname[:-5] + 'gltf').replace('/blend/', '/gltf/', 1)
96 bam_name = (_fname[:-5] + 'bam').replace('/blend/', '/bam/', 1)
8ee66edd
FC
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()
102 deps = []
103 for line in lines:
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)
420ce99a 107 deps += [tname.replace('/models/blend/', '/models/gltf/', 1)]
8ee66edd
FC
108 for dep in deps:
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))
e65a09cf
FC
114
115 def rpl(lin):
116 lin = lin.replace('.png', '.dds')
117 lin = lin.replace('.jpg', '.dds')
118 lin = lin.replace('/png', '/dds')
119 return lin.replace('/jpg', '/dds')
8ee66edd
FC
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):
218c8938
FC
124 system('gltf2bam %s %s' % cmd_args)
125 self._cache_files += [bam_name] + deps