from .GameObjectReference import GameObjectReference from .MaterialManager import MaterialManager from .Process import Process import traceback import sys import bge __all__ = ['ShaderMaterial'] class ShaderMaterial(Process): class InvalidContext(RuntimeError): pass MaterialManager = MaterialManager FragmentShader = '' VertexShader = '' @property def owner(self): return self.reference.object @property def invalid(self): return self.owner is None def __init__(self, *args, **kargs): self.MaterialManager = kargs.pop('manager', self.MaterialManager) self.FragmentShader = kargs.pop('fragment', self.FragmentShader) self.VertexShader = kargs.pop('vertex', self.VertexShader) # Fetch the object at initialisation object = kargs.pop('object', None) if object is None: try: controller = bge.logic.getCurrentController() object = controller.owner except SystemError: self.owner = None self.error( self.InvalidContext('No KX_GameObject could be fetched')) return self.reference = GameObjectReference(object) self.init(*args, **kargs) self.MaterialManager.Register(self) def filterShader(self, object, mesh, shader): '''Filter function: how to discriminate the shaders''' return shader is not None def getShaders(self): '''Should return the shaders to keep track of''' for mesh in self.owner.meshes: for material in mesh.materials: shader = material.getShader() if self.filterShader(object, mesh, shader): if not shader.isValid(): shader.setSource( self.VertexShader, self.FragmentShader, True) yield shader def init(self): '''This is called on shader instanciation''' def error(self, error): '''This is called on error (invalidation)''' sys.stderr.write('Error occured in object "{}":\n'.format(self.owner)) traceback.print_exc() def pre_draw_setup_dispatch(self): for shader in self.getShaders(): self.pre_draw_setup(shader) def pre_draw_dispatch(self): for shader in self.getShaders(): self.pre_draw(shader) def post_draw_dispatch(self): for shader in self.getShaders(): self.post_draw(shader)