Commit | Line | Data |
---|---|---|
8ee66edd FC |
1 | from logging import info |
2 | from os import system, walk, makedirs | |
6cd92a74 | 3 | from os.path import exists, dirname, join, basename, splitext |
c24f4e17 | 4 | from sys import executable |
6cd92a74 | 5 | from functools import reduce |
218c8938 | 6 | from multiprocessing import Pool |
8ee66edd | 7 | from hashlib import md5 |
bf77b5d5 | 8 | from shutil import rmtree |
53ddf3c3 | 9 | from ya2.build.build import to_be_built |
8ee66edd FC |
10 | |
11 | ||
12 | class 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 | ||
70 | class 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 | ||
109 | class 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 | ||
124 | class 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 |