|
10 | 10 | from .base import BaseRegistry |
11 | 11 |
|
12 | 12 |
|
| 13 | +class ShaderMeta: |
| 14 | + |
| 15 | + def __init__(self, path, **kwargs): |
| 16 | + self.path = path |
| 17 | + self.kwargs = kwargs |
| 18 | + |
| 19 | + |
13 | 20 | class Shaders(BaseRegistry): |
14 | 21 | """ |
15 | 22 | A registry for shaders requested by effects. |
16 | 23 | Once all effects are initialized, we ask this class to load the shaders. |
17 | 24 | """ |
18 | 25 | def __init__(self): |
19 | 26 | super().__init__() |
20 | | - self.shaders = {} |
21 | | - |
22 | | - @property |
23 | | - def count(self): |
24 | | - """ |
25 | | - :return: Number of shaders |
26 | | - """ |
27 | | - return len(self.shaders) |
28 | 27 |
|
29 | | - def get(self, path: Union[str, Path], create=False) -> ShaderProgram: |
| 28 | + def load(self, path: Union[str, Path], **kwargs) -> ShaderProgram: |
30 | 29 | """ |
31 | | - Get or create a shader object. |
32 | | - This may return an empty object that will be filled during load |
33 | | - based on the ``create`` parameter. |
| 30 | + load shader program or return an exiting program. |
34 | 31 |
|
35 | 32 | :param path: Path to the shader (pathlib.Path instance) |
36 | | - :param create: (bool) Create an empty shader object if it doesn't exist |
37 | 33 | :return: Shader object |
38 | 34 | """ |
39 | 35 | path = Path(path) |
40 | 36 |
|
41 | | - shader = self.shaders.get(path) |
42 | | - if create and not shader: |
43 | | - shader = ShaderProgram(path) |
44 | | - self.shaders[path] = shader |
| 37 | + shader = self.file_map.get(path) |
| 38 | + if shader: |
| 39 | + return shader |
| 40 | + |
| 41 | + meta = self.load_deferred(path, **kwargs) |
| 42 | + shader = self._load(meta) |
| 43 | + |
45 | 44 | return shader |
46 | 45 |
|
47 | | - def load(self, reload=False): |
48 | | - """ |
49 | | - Loads all the shaders using the configured finders. |
| 46 | + def load_deferred(self, path: Union[str, Path], **kwargs) -> ShaderMeta: |
| 47 | + meta = ShaderMeta(path, **kwargs) |
50 | 48 |
|
51 | | - :param reload: (bool) Are we reloading the shaders? |
52 | | - """ |
53 | | - print("Loading shaders:") |
54 | | - for name, shader in self.shaders.items(): |
55 | | - self.load_shader(shader, name=name, reload=reload) |
| 49 | + self.file_map[path] = None |
| 50 | + self.file_meta[path] = meta |
56 | 51 |
|
57 | | - self._on_loaded() |
| 52 | + return meta |
58 | 53 |
|
59 | | - def load_shader(self, shader, name=None, reload=False): |
60 | | - """ |
61 | | - Loads a single shader adding it to the shader registry |
| 54 | + def _load(self, meta, reload=False): |
| 55 | + found_path = self._find_last_of(meta.path, list(get_finders())) |
62 | 56 |
|
63 | | - :param shader: The shader to load |
64 | | - :param name: Unique name in the registry. Usually the path |
65 | | - :param reload: (bool) Are we reloading the shader? |
66 | | - """ |
67 | | - if name is None: |
68 | | - name = Path(shader.path) |
69 | | - |
70 | | - finders = list(get_finders()) |
71 | | - |
72 | | - for finder in finders: |
73 | | - path = finder.find(name) |
74 | | - if path: |
75 | | - print(" - {}".format(path)) |
76 | | - with open(path, 'r') as fd: |
77 | | - shader.set_source(fd.read()) |
78 | | - |
79 | | - try: |
80 | | - shader.prepare(reload=reload) |
81 | | - except (ShaderError, moderngl.Error) as err: |
82 | | - print("ShaderError: ", err) |
83 | | - if not reload: |
84 | | - raise |
85 | | - except Exception as err: |
86 | | - print(err) |
87 | | - raise |
88 | | - |
89 | | - break |
| 57 | + if not found_path: |
| 58 | + raise ImproperlyConfigured("Cannot find shader {}".format(meta.path)) |
| 59 | + |
| 60 | + print("Loading: {}".format(meta.path)) |
| 61 | + if reload: |
| 62 | + shader = self.file_map[meta.path] |
90 | 63 | else: |
91 | | - raise ImproperlyConfigured("Cannot find shader {}".format(name)) |
| 64 | + shader = ShaderProgram(meta.path) |
| 65 | + |
| 66 | + with open(found_path, 'r') as fd: |
| 67 | + shader.set_source(fd.read()) |
| 68 | + |
| 69 | + try: |
| 70 | + shader.prepare(reload=reload) |
| 71 | + except (ShaderError, moderngl.Error) as err: |
| 72 | + print("ShaderError: ", err) |
| 73 | + if not reload: |
| 74 | + raise |
| 75 | + except Exception as err: |
| 76 | + print(err) |
| 77 | + raise |
| 78 | + |
| 79 | + self.file_map[meta.path] = shader |
| 80 | + |
| 81 | + return shader |
| 82 | + |
| 83 | + def _destroy(self, obj): |
| 84 | + obj.release() |
92 | 85 |
|
93 | 86 | def reload(self): |
94 | 87 | """ |
95 | 88 | Reloads all shaders |
96 | 89 | """ |
97 | | - self.load(reload=True) |
| 90 | + for path, meta in self.file_meta.items(): |
| 91 | + print(path, meta) |
| 92 | + self._load(meta, reload=True) |
98 | 93 |
|
99 | 94 |
|
100 | 95 | shaders = Shaders() |
0 commit comments