ya2 · news · projects · code · about

gettext: --no-location
[pmachines.git] / ya2 / build / models.py
CommitLineData
8ee66edd
FC
1from logging import info
2from os import system, walk, makedirs
6cd92a74 3from os.path import exists, dirname, join, basename, splitext
c24f4e17 4from sys import executable
6cd92a74 5from functools import reduce
218c8938 6from multiprocessing import Pool
8ee66edd 7from hashlib import md5
bf77b5d5 8from shutil import rmtree
53ddf3c3 9from ya2.build.build import to_be_built
8ee66edd
FC
10
11
12class ModelsBuilder():
13
524e2ef5
FC
14 def __init__(self, blend_path, cores):
15 self.__blend_path = blend_path
16 self.__cores = cores
c24f4e17 17 self.__manifest = ModelsManifest()
8ee66edd 18
c24f4e17 19 def build(self):
6cd92a74
FC
20 self.__compute_files_to_build()
21 return self.__run_build()
22
23 def __compute_files_to_build(self):
24 self.__blend_files = []
524e2ef5 25 for root, _, file_names in walk(self.__blend_path):
6cd92a74 26 b = [f for f in file_names if f.endswith('.blend')]
c24f4e17 27 if '/prototypes/' in root:
6cd92a74
FC
28 b = []
29 b = [join(root, f)
30 for f in b
31 if to_be_built(join(root, f), [join(root, f)])]
32 self.__blend_files += b
33
34 def __run_build(self):
35 with Pool(self.__cores) as p:
36 just_built = p.map(self.blend2bam, self.__blend_files)
c24f4e17
FC
37 p.close()
38 p.join()
6cd92a74 39 just_built = [assets for b in just_built for assets in b]
c24f4e17
FC
40 self.__manifest.update(just_built)
41 return just_built
42
43 def blend2bam(self, file_path):
44 built = []
6cd92a74
FC
45 if to_be_built(self.gltf_name(file_path), [file_path]):
46 self.__clean_gltf_dir(file_path)
c24f4e17
FC
47 built += self.__blend2gltf(file_path)
48 built += self.__gltf2bam(file_path)
49 return built
50
c24f4e17
FC
51 def __clean_gltf_dir(self, file_path):
52 gltf_dir = dirname(file_path)
6cd92a74 53 gltf_dir = gltf_dir.replace('assets/models/blend/', 'assets/models/gltf/')
524e2ef5 54 rmtree(gltf_dir, ignore_errors=True)
c24f4e17
FC
55
56 @staticmethod
57 def gltf_name(file_path):
524e2ef5 58 gltf_name = file_path.replace('assets/models/blend/', 'assets/models/gltf/')
c24f4e17
FC
59 return gltf_name.replace('.blend', '.gltf')
60
61 def __blend2gltf(self, file_path):
62 b2g = Blend2Gltf(file_path)
63 return b2g.export()
64
65 def __gltf2bam(self, file_path):
66 g2b = Gltf2Bam(file_path)
67 return g2b.export()
68
69
70class ModelsManifest:
71
72 def __init__(self):
73 self.__lines = []
74 self.__manifest = []
75 self.__file_name = 'models_manifest.txt'
76
77 def update(self, just_built):
78 self.__just_built = just_built
79 self.__load()
80 self.__add_just_built()
81 self.__discard_old_entries()
82 self.__rewrite()
83
84 def __load(self):
85 if exists(self.__file_name):
86 with open(self.__file_name) as f: self.__lines = f.readlines()
87 for l in self.__lines: # line's e.g. assets/path/to/gltf_or_png.ext 68ced1
88 self.__process_line(l)
89
90 def __process_line(self, l):
91 line_splitted = l.split()
92 hash_value = line_splitted[-1]
93 file_name = ' '.join(line_splitted[:-1])
94 if file_name not in self.__just_built:
95 self.__manifest += [(file_name, hash_value)]
96
97 def __add_just_built(self):
98 for f in self.__just_built:
99 self.__manifest += [(f, md5(open(f, 'rb').read()).hexdigest())]
100
101 def __discard_old_entries(self):
102 self.__manifest = self.__manifest[-2048:]
103
104 def __rewrite(self):
105 with open(self.__file_name, 'w') as f:
106 f.write('\n'.join([' '.join(l) for l in self.__manifest]))
107
108
109class Blend2Gltf:
110
111 def __init__(self, file_path):
112 self.__file_path = file_path
113
114 def export(self):
6cd92a74 115 gltf_dir, file_name = dirname(self.__file_path), basename(self.__file_path)
c24f4e17 116 gltf_dir = gltf_dir.replace('assets/models/blend/', 'assets/models/gltf/')
c24f4e17 117 makedirs(gltf_dir, exist_ok=True)
6cd92a74
FC
118 file_path = splitext(gltf_dir + '/' + file_name)[0]
119 command = f'blender {self.__file_path} --background --python ya2/build/blend2gltf.py -- {file_path}.gltf'
524e2ef5 120 system(command)
c24f4e17
FC
121 return [self.__file_path, ModelsBuilder.gltf_name(self.__file_path)]
122
123
124class Gltf2Bam:
125
126 def __init__(self, file_path):
6cd92a74
FC
127 self.__gltf_name = (file_path[:-5] + 'gltf').replace('/blend/', '/gltf/', 1)
128 self.__bam_name = (file_path[:-5] + 'bam').replace('/blend/', '/bam/', 1)
c24f4e17
FC
129
130 def export(self):
131 self.__build_dds_from_jpg_and_png()
132 self.__rewrite_gltf()
133 return self.__export_bam()
134
135 def __build_dds_from_jpg_and_png(self):
c24f4e17 136 with open(self.__gltf_name) as f: self.__lines = f.readlines()
6cd92a74 137 self.__jpg_png_files = []
c24f4e17 138 for l in self.__lines:
524e2ef5 139 if ('.png' in l or '.jpg' in l) and '"uri"' in l:
59537c34 140 r = l[l.index('"uri"') + 7:].rstrip(',\n"')
6cd92a74
FC
141 t = f'{dirname(self.__gltf_name)}/{r}'
142 self.__jpg_png_files += [t.replace('/models/blend/', '/models/gltf/', 1)]
143 self.__create_dds_files()
144
145 def __create_dds_files(self):
146 for d in self.__jpg_png_files:
147 t = d.replace('/gltf/', '/bam/', 1)
148 t = t.replace('.png', '.dds').replace('.jpg', '.dds')
149 makedirs(dirname(t), exist_ok=True)
150 info(f'convert {d} {t}')
151 system(f'convert {d} {t}')
c24f4e17
FC
152
153 def __rewrite_gltf(self):
6cd92a74
FC
154 def r(lin):
155 e = [('.png', '.dds'), ('.jpg', '.dds'),
156 ('/png', '/dds'), ('/jpg', '/dds')]
157 return reduce(lambda s, p: s.replace(*p), e, lin)
158 with open(self.__gltf_name, 'w') as f:
159 f.write(''.join([r(line) for line in self.__lines]))
c24f4e17
FC
160
161 def __export_bam(self):
162 makedirs(dirname(self.__bam_name), exist_ok=True)
6cd92a74 163 if to_be_built(self.__bam_name, self.__jpg_png_files):
c24f4e17
FC
164 venv_path = dirname(executable)
165 gltf2bam_path = join(venv_path, 'gltf2bam')
166 system(f'{gltf2bam_path} {self.__gltf_name} {self.__bam_name}')
6cd92a74 167 return [self.__bam_name] + self.__jpg_png_files