"""Shader Registry"""
import moderngl
from demosys.core.exceptions import ImproperlyConfigured
from demosys.core.shaderfiles.finders import get_finders
from demosys.opengl import ShaderError, ShaderProgram


class Shaders:
    """
    A registry for shaders requested by effects.
    Once all effects are initialized, we ask this class to load the shaders.
    """
    def __init__(self):
        self.shaders = {}

    @property
    def count(self):
        """
        :return: Number of shaders
        """
        return len(self.shaders)

    def get(self, path, create=False) -> ShaderProgram:
        """
        Get or create a shader object.
        This may return an empty object that will be filled during load
        based on the ``create`` parameter.

        :param path: Path to the shader
        :param create: (bool) Create an empty shader object if it doesn't exist
        :return: Shader object
        """
        shader = self.shaders.get(path)
        if create and not shader:
            shader = ShaderProgram(path)
            self.shaders[path] = shader
        return shader

    def load(self, reload=False):
        """
        Loads all the shaders using the configured finders.
        """
        finders = list(get_finders())
        print("Loading shaders:")
        for name, shader in self.shaders.items():
            for finder in finders:
                path = finder.find(name)
                if path:
                    print(" - {}".format(path))
                    with open(path, 'r') as fd:
                        shader.set_source(fd.read())

                    try:
                        shader.prepare(reload=reload)
                    except (ShaderError, moderngl.Error) as err:
                        print("ShaderError: ", err)
                        if not reload:
                            raise
                    except Exception as err:
                        print(err)
                        raise

                    break
            else:
                raise ImproperlyConfigured("Cannot find shader {}".format(name))

    def reload(self):
        """
        Reloads all shaders
        """
        self.load(reload=True)


shaders = Shaders()

@@ -1207,24 +1207,25 @@
 inders.%0A
+%0A
         
 %22%22%22%0A    
@@ -1220,49 +1220,71 @@
     
-%22%22%22%0A        finders = list(get_finders())
+:param reload: (bool) Are we reloading the shaders?%0A        %22%22%22
 %0A   
@@ -1380,88 +1380,511 @@
     
-for finder in finders:%0A                path = finder.find(name)%0A        
+self.load_shader(shader, name=name, reload=reload)%0A%0A    def load_shader(self, shader, name=None, reload=False):%0A        %22%22%22%0A        Loads a single shader adding it to the shader registry%0A%0A        :param shader: The shader to load%0A        :param name: Unique name in the registry. Usually the path%0A        :param reload: (bool) Are we reloading the shader?%0A        %22%22%22%0A        if name is None:%0A            name = shader.path%0A%0A        finders = list(get_finders())%0A%0A        for finder in finders:%0A
         
 if p
@@ -1883,21 +1883,58 @@
     
-if
+   
  path
-:%0A    
+ = finder.find(name)%0A            if path:%0A
     
@@ -1989,20 +1989,16 @@
         
-    
 with ope
@@ -2033,28 +2033,24 @@
             
-   
- 
 shader.set_s
@@ -2083,20 +2083,16 @@
         
-    
 try:%0A   
@@ -2104,28 +2104,24 @@
             
-   
- 
 shader.prepa
@@ -2138,20 +2138,16 @@
 reload)%0A
-    
         
@@ -2215,28 +2215,24 @@
             
-   
- 
 print(%22Shade
@@ -2263,28 +2263,24 @@
             
-    
 if not reloa
@@ -2282,20 +2282,16 @@
 reload:%0A
-    
         
@@ -2324,28 +2324,24 @@
             
-    
 except Excep
@@ -2345,36 +2345,32 @@
 ception as err:%0A
-    
                 
@@ -2408,23 +2408,15 @@
     
-    
 raise%0A%0A
-    
     
@@ -2445,22 +2445,14 @@
     
-    
 else:%0A
-    
     

Allow loading single shader