class Container(Axon.AdaptiveCommsComponent.AdaptiveCommsComponent): """\ Container(...) -> A new Container component. A container to control several OpenGLComponents. Keyword arguments: - position -- Initial container position (default=(0,0,0)). - rotation -- Initial container rotation (default=(0,0,0)). - scaling -- Initial container scaling (default=(1,1,1)). - contents -- Nested dictionary of contained components. """ Inboxes = { "inbox": "", "control": "For shutdown messages", "position" : "receive position triple (x,y,z)", "rotation": "receive rotation triple (x,y,z)", "scaling": "receive scaling triple (x,y,z)", "rel_position" : "receive position triple (x,y,z)", "rel_rotation": "receive rotation triple (x,y,z)", "rel_scaling": "receive scaling triple (x,y,z)", } Outboxes = { "outbox": "", "signal": "For shutdown messages" } def __init__(self, **argd): """x.__init__(...) initializes x; see x.__class__.__doc__ for signature""" super(Container, self).__init__() # get transformation data and convert to vectors self.position = Vector( *argd.get("position", (0,0,0)) ) self.rotation = Vector( *argd.get("rotation", (0.0,0.0,0.0)) ) self.scaling = Vector( *argd.get("scaling", (1,1,1) ) ) # for detection of changes self.oldrot = Vector() self.oldpos = Vector() self.oldscaling = Vector() # inital apply trasformations self.transform = Transform() self.components = [] self.rel_positions = {} self.rel_rotations = {} self.rel_scalings = {} self.poscomms = {} self.rotcomms = {} self.scacomms = {} contents = argd.get("contents", None) if contents is not None: for (comp, params) in contents.items(): self.addElement(comp, **params) def main(self): while 1: while self.dataReady("control"): cmsg = self.recv("control") if isinstance(cmsg, producerFinished) or isinstance(cmsg, shutdownMicroprocess): self.send(cmsg, "signal") return self.handleMovement() self.applyTransforms() yield 1 def handleMovement(self): """ Handle movement commands received by corresponding inboxes. """ while self.dataReady("position"): pos = self.recv("position") self.position = Vector(*pos) while self.dataReady("rotation"): rot = self.recv("rotation") self.rotation = Vector(*rot) while self.dataReady("scaling"): scaling = self.recv("scaling") self.scaling = Vector(*scaling) while self.dataReady("rel_position"): self.position += Vector(*self.recv("rel_position")) while self.dataReady("rel_rotation"): self.rotation += Vector(*self.recv("rel_rotation")) while self.dataReady("rel_scaling"): self.scaling = Vector(*self.recv("rel_scaling")) def applyTransforms(self): """ Use the objects translation/rotation/scaling values to generate a new transformation Matrix if changes have happened. """ # generate new transformation matrix if needed if self.oldscaling != self.scaling or self.oldrot != self.rotation or self.oldpos != self.position: self.transform = Transform() self.transform.applyScaling(self.scaling) self.transform.applyRotation(self.rotation) self.transform.applyTranslation(self.position) self.oldpos = self.position.copy() self.oldrot = self.rotation.copy() self.oldscaling = self.scaling.copy() self.rearangeContents() def rearangeContents(self): for comp in self.components: trans = self.transform.transformVector(self.rel_positions[comp]) self.send(trans.toTuple(), self.poscomms[comp]) # self.send(self.rotation.toTuple(), self.rotcomms[comp]) self.send(self.scaling.toTuple(), self.scacomms[comp]) def addElement(self, comp, position=(0,0,0), rotation=(0,0,0), scaling=(1,1,1) ): self.components.append(comp) self.rel_positions[comp] = Vector( *position ) self.rel_rotations[comp] = Vector( *rotation ) self.rel_scalings[comp] = Vector( *scaling ) self.poscomms[comp] = self.addOutbox("pos") self.link( (self, self.poscomms[comp]), (comp, "position") ) # self.rotcomms[comp] = self.addOutbox("rot") # self.link( (self, self.rotcomms[comp]), (comp, "rotation") ) self.scacomms[comp] = self.addOutbox("sca") self.link( (self, self.scacomms[comp]), (comp, "scaling") ) self.rearangeContents() def removeElement(self, comp): self.components.remove(comp) self.rel_positions.pop(comp) self.rel_rotations.pop(comp) self.rel_scalings.pop(comp) # todo: unlink self.poscomms.pop(comp) self.rotcomms.pop(comp) self.scacomms.pop(comp) self.rearangeContents()
class Container(Axon.AdaptiveCommsComponent.AdaptiveCommsComponent): """\ Container(...) -> A new Container component. A container to control several OpenGLComponents. Keyword arguments: - position -- Initial container position (default=(0,0,0)). - rotation -- Initial container rotation (default=(0,0,0)). - scaling -- Initial container scaling (default=(1,1,1)). - contents -- Nested dictionary of contained components. """ Inboxes = { "inbox": "", "control": "For shutdown messages", "position": "receive position triple (x,y,z)", "rotation": "receive rotation triple (x,y,z)", "scaling": "receive scaling triple (x,y,z)", "rel_position": "receive position triple (x,y,z)", "rel_rotation": "receive rotation triple (x,y,z)", "rel_scaling": "receive scaling triple (x,y,z)", } Outboxes = {"outbox": "", "signal": "For shutdown messages"} def __init__(self, **argd): """x.__init__(...) initializes x; see x.__class__.__doc__ for signature""" super(Container, self).__init__() # get transformation data and convert to vectors self.position = Vector(*argd.get("position", (0, 0, 0))) self.rotation = Vector(*argd.get("rotation", (0.0, 0.0, 0.0))) self.scaling = Vector(*argd.get("scaling", (1, 1, 1))) # for detection of changes self.oldrot = Vector() self.oldpos = Vector() self.oldscaling = Vector() # inital apply trasformations self.transform = Transform() self.components = [] self.rel_positions = {} self.rel_rotations = {} self.rel_scalings = {} self.poscomms = {} self.rotcomms = {} self.scacomms = {} contents = argd.get("contents", None) if contents is not None: for (comp, params) in contents.items(): self.addElement(comp, **params) def main(self): while 1: while self.dataReady("control"): cmsg = self.recv("control") if isinstance(cmsg, producerFinished) or isinstance( cmsg, shutdownMicroprocess): self.send(cmsg, "signal") return self.handleMovement() self.applyTransforms() yield 1 def handleMovement(self): """ Handle movement commands received by corresponding inboxes. """ while self.dataReady("position"): pos = self.recv("position") self.position = Vector(*pos) while self.dataReady("rotation"): rot = self.recv("rotation") self.rotation = Vector(*rot) while self.dataReady("scaling"): scaling = self.recv("scaling") self.scaling = Vector(*scaling) while self.dataReady("rel_position"): self.position += Vector(*self.recv("rel_position")) while self.dataReady("rel_rotation"): self.rotation += Vector(*self.recv("rel_rotation")) while self.dataReady("rel_scaling"): self.scaling = Vector(*self.recv("rel_scaling")) def applyTransforms(self): """ Use the objects translation/rotation/scaling values to generate a new transformation Matrix if changes have happened. """ # generate new transformation matrix if needed if self.oldscaling != self.scaling or self.oldrot != self.rotation or self.oldpos != self.position: self.transform = Transform() self.transform.applyScaling(self.scaling) self.transform.applyRotation(self.rotation) self.transform.applyTranslation(self.position) self.oldpos = self.position.copy() self.oldrot = self.rotation.copy() self.oldscaling = self.scaling.copy() self.rearangeContents() def rearangeContents(self): for comp in self.components: trans = self.transform.transformVector(self.rel_positions[comp]) self.send(trans.toTuple(), self.poscomms[comp]) # self.send(self.rotation.toTuple(), self.rotcomms[comp]) self.send(self.scaling.toTuple(), self.scacomms[comp]) def addElement(self, comp, position=(0, 0, 0), rotation=(0, 0, 0), scaling=(1, 1, 1)): self.components.append(comp) self.rel_positions[comp] = Vector(*position) self.rel_rotations[comp] = Vector(*rotation) self.rel_scalings[comp] = Vector(*scaling) self.poscomms[comp] = self.addOutbox("pos") self.link((self, self.poscomms[comp]), (comp, "position")) # self.rotcomms[comp] = self.addOutbox("rot") # self.link( (self, self.rotcomms[comp]), (comp, "rotation") ) self.scacomms[comp] = self.addOutbox("sca") self.link((self, self.scacomms[comp]), (comp, "scaling")) self.rearangeContents() def removeElement(self, comp): self.components.remove(comp) self.rel_positions.pop(comp) self.rel_rotations.pop(comp) self.rel_scalings.pop(comp) # todo: unlink self.poscomms.pop(comp) self.rotcomms.pop(comp) self.scacomms.pop(comp) self.rearangeContents()
class OpenGLComponent(Axon.AdaptiveCommsComponent.AdaptiveCommsComponent): """\ OpenGLComponent(...) -> create a new OpenGL component (not very useful though; it is rather designed to inherit from). This components implements the interaction with the OpenGLDisplay service that is needed to setup, draw and move an object using OpenGL. Keyword arguments: - size -- three dimensional size of component (default=(0,0,0)) - rotation -- rotation of component around (x,y,z) axis (defaul=(0,0,0)) - scaling -- scaling along the (x,y,z) axis (default=(1,1,1)) - position -- three dimensional position (default=(0,0,0)) - name -- name of component (mostly for debugging, default="nameless") """ Inboxes = { "inbox": "not used", "control": "For shutdown messages", "callback": "for the response after a displayrequest", "events": "Input events", "position" : "receive position triple (x,y,z)", "rotation": "receive rotation triple (x,y,z)", "scaling": "receive scaling triple (x,y,z)", "rel_position" : "receive position triple (x,y,z)", "rel_rotation": "receive rotation triple (x,y,z)", "rel_scaling": "receive scaling triple (x,y,z)", } Outboxes = { "outbox": "not used", "signal": "For shutdown messages", "display_signal" : "Outbox used for communicating to the display surface", "position" : "send position status when updated", "rotation": "send rotation status when updated", "scaling": "send scaling status when updated", } def __init__(self, **argd): """x.__init__(...) initializes x; see x.__class__.__doc__ for signature""" super(OpenGLComponent, self).__init__() # get transformation data and convert to vectors self.size = Vector( *argd.get("size", (0,0,0)) ) self.position = Vector( *argd.get("position", (0,0,0)) ) self.rotation = Vector( *argd.get("rotation", (0.0,0.0,0.0)) ) self.scaling = Vector( *argd.get("scaling", (1,1,1) ) ) # for detection of changes self.oldrot = Vector() self.oldpos = Vector() self.oldscaling = Vector() self.transform = Transform() # name (mostly for debugging) self.name = argd.get("name", "nameless") # create clock self.clock = pygame.time.Clock() self.frametime = 0.0 # get display service displayservice = OpenGLDisplay.getDisplayService() # link display_signal to displayservice self.link((self,"display_signal"), displayservice) def main(self): # create display request self.disprequest = { "OGL_DISPLAYREQUEST" : True, "objectid" : id(self), "callback" : (self,"callback"), "events" : (self, "events"), "size": self.size } # send display request self.send(self.disprequest, "display_signal") # inital apply trasformations self.applyTransforms() # setup function from derived objects self.setup() # initial draw to display list self.redraw() # wait for response on displayrequest while not self.dataReady("callback"): yield 1 self.identifier = self.recv("callback") while 1: yield 1 while self.dataReady("control"): cmsg = self.recv("control") if isinstance(cmsg, producerFinished) or isinstance(cmsg, shutdownMicroprocess): self.send(cmsg, "signal") return self.frametime = float(self.clock.tick())/1000.0 self.handleMovement() self.handleEvents() self.applyTransforms() # frame function from derived objects self.frame() while not self.anyReady(): self.pause() yield 1 def applyTransforms(self): """ Use the objects translation/rotation/scaling values to generate a new transformation Matrix if changes have happened. """ # generate new transformation matrix if needed if self.oldscaling != self.scaling or self.oldrot != self.rotation or self.oldpos != self.position: self.transform = Transform() self.transform.applyScaling(self.scaling) self.transform.applyRotation(self.rotation) self.transform.applyTranslation(self.position) if self.oldscaling != self.scaling: self.send(self.scaling.toTuple(), "scaling") self.oldscaling = self.scaling.copy() if self.oldrot != self.rotation: self.send(self.rotation.toTuple(), "rotation") self.oldrot = self.rotation.copy() if self.oldpos != self.position: self.send(self.position.toTuple(), "position") self.oldpos = self.position.copy() # send new transform to display service transform_update = { "TRANSFORM_UPDATE": True, "objectid": id(self), "transform": self.transform } self.send(transform_update, "display_signal") def handleMovement(self): """ Handle movement commands received by corresponding inboxes. """ while self.dataReady("position"): pos = self.recv("position") self.position = Vector(*pos) while self.dataReady("rotation"): rot = self.recv("rotation") self.rotation = Vector(*rot) while self.dataReady("scaling"): scaling = self.recv("scaling") self.scaling = Vector(*scaling) while self.dataReady("rel_position"): self.position += Vector(*self.recv("rel_position")) while self.dataReady("rel_rotation"): self.rotation += Vector(*self.recv("rel_rotation")) while self.dataReady("rel_scaling"): self.scaling = Vector(*self.recv("rel_scaling")) ## # Methods to be used by derived objects ## def addListenEvents(self, events): """\ Sends listening request for pygame events to the display service. The events parameter is expected to be a list of pygame event constants. """ for event in events: self.send({"ADDLISTENEVENT":event, "objectid":id(self)}, "display_signal") def removeListenEvents(self, events): """\ Sends stop listening request for pygame events to the display service. The events parameter is expected to be a list of pygame event constants. """ for event in events: self.send({"REMOVELISTENEVENT":event, "objectid":id(self)}, "display_signal") def redraw(self): """\ Invoke draw() and save its commands to a newly generated displaylist. The displaylist name is then sent to the display service via a "DISPLAYLIST_UPDATE" request. """ # display list id displaylist = glGenLists(1); # draw object to its displaylist glNewList(displaylist, GL_COMPILE) self.draw() glEndList() dl_update = { "DISPLAYLIST_UPDATE": True, "objectid": id(self), "displaylist": displaylist } self.send(dl_update, "display_signal") ## # Method stubs to be overridden by derived objects ## def handleEvents(self): """ Method stub Override this method to do event handling inside. Should look like this:: while self.dataReady("events"): event = self.recv("events") # handle event ... """ pass def draw(self): """ Method stub Override this method for drawing. Only use commands which are needed for drawing. Will not draw directly but be saved to a displaylist. Therefore, make sure not to use any commands which cannot be stored in displaylists (unlikely anyway). """ pass def setup(self): """ Method stub Override this method for component setup. It will be called on the first scheduling of the component. """ pass def frame(self): """ Method stub Override this method for operations you want to do every frame. It will be called every time the component is scheduled. Do not include infinite loops, the method has to return every time it gets called. """ pass
class OpenGLComponent(Axon.AdaptiveCommsComponent.AdaptiveCommsComponent): """\ OpenGLComponent(...) -> create a new OpenGL component (not very useful though; it is rather designed to inherit from). This components implements the interaction with the OpenGLDisplay service that is needed to setup, draw and move an object using OpenGL. Keyword arguments: - size -- three dimensional size of component (default=(0,0,0)) - rotation -- rotation of component around (x,y,z) axis (defaul=(0,0,0)) - scaling -- scaling along the (x,y,z) axis (default=(1,1,1)) - position -- three dimensional position (default=(0,0,0)) - name -- name of component (mostly for debugging, default="nameless") """ Inboxes = { "inbox": "not used", "control": "For shutdown messages", "callback": "for the response after a displayrequest", "events": "Input events", "position": "receive position triple (x,y,z)", "rotation": "receive rotation triple (x,y,z)", "scaling": "receive scaling triple (x,y,z)", "rel_position": "receive position triple (x,y,z)", "rel_rotation": "receive rotation triple (x,y,z)", "rel_scaling": "receive scaling triple (x,y,z)", } Outboxes = { "outbox": "not used", "signal": "For shutdown messages", "display_signal": "Outbox used for communicating to the display surface", "position": "send position status when updated", "rotation": "send rotation status when updated", "scaling": "send scaling status when updated", } def __init__(self, **argd): """x.__init__(...) initializes x; see x.__class__.__doc__ for signature""" super(OpenGLComponent, self).__init__() # get transformation data and convert to vectors self.size = Vector(*argd.get("size", (0, 0, 0))) self.position = Vector(*argd.get("position", (0, 0, 0))) self.rotation = Vector(*argd.get("rotation", (0.0, 0.0, 0.0))) self.scaling = Vector(*argd.get("scaling", (1, 1, 1))) # for detection of changes self.oldrot = Vector() self.oldpos = Vector() self.oldscaling = Vector() self.transform = Transform() # name (mostly for debugging) self.name = argd.get("name", "nameless") # create clock self.clock = pygame.time.Clock() self.frametime = 0.0 # get display service displayservice = OpenGLDisplay.getDisplayService() # link display_signal to displayservice self.link((self, "display_signal"), displayservice) def main(self): # create display request self.disprequest = { "OGL_DISPLAYREQUEST": True, "objectid": id(self), "callback": (self, "callback"), "events": (self, "events"), "size": self.size } # send display request self.send(self.disprequest, "display_signal") # inital apply trasformations self.applyTransforms() # setup function from derived objects self.setup() # initial draw to display list self.redraw() # wait for response on displayrequest while not self.dataReady("callback"): yield 1 self.identifier = self.recv("callback") while 1: yield 1 while self.dataReady("control"): cmsg = self.recv("control") if isinstance(cmsg, producerFinished) or isinstance( cmsg, shutdownMicroprocess): self.send(cmsg, "signal") return self.frametime = float(self.clock.tick()) / 1000.0 self.handleMovement() self.handleEvents() self.applyTransforms() # frame function from derived objects self.frame() while not self.anyReady(): self.pause() yield 1 def applyTransforms(self): """ Use the objects translation/rotation/scaling values to generate a new transformation Matrix if changes have happened. """ # generate new transformation matrix if needed if self.oldscaling != self.scaling or self.oldrot != self.rotation or self.oldpos != self.position: self.transform = Transform() self.transform.applyScaling(self.scaling) self.transform.applyRotation(self.rotation) self.transform.applyTranslation(self.position) if self.oldscaling != self.scaling: self.send(self.scaling.toTuple(), "scaling") self.oldscaling = self.scaling.copy() if self.oldrot != self.rotation: self.send(self.rotation.toTuple(), "rotation") self.oldrot = self.rotation.copy() if self.oldpos != self.position: self.send(self.position.toTuple(), "position") self.oldpos = self.position.copy() # send new transform to display service transform_update = { "TRANSFORM_UPDATE": True, "objectid": id(self), "transform": self.transform } self.send(transform_update, "display_signal") def handleMovement(self): """ Handle movement commands received by corresponding inboxes. """ while self.dataReady("position"): pos = self.recv("position") self.position = Vector(*pos) while self.dataReady("rotation"): rot = self.recv("rotation") self.rotation = Vector(*rot) while self.dataReady("scaling"): scaling = self.recv("scaling") self.scaling = Vector(*scaling) while self.dataReady("rel_position"): self.position += Vector(*self.recv("rel_position")) while self.dataReady("rel_rotation"): self.rotation += Vector(*self.recv("rel_rotation")) while self.dataReady("rel_scaling"): self.scaling = Vector(*self.recv("rel_scaling")) ## # Methods to be used by derived objects ## def addListenEvents(self, events): """\ Sends listening request for pygame events to the display service. The events parameter is expected to be a list of pygame event constants. """ for event in events: self.send({ "ADDLISTENEVENT": event, "objectid": id(self) }, "display_signal") def removeListenEvents(self, events): """\ Sends stop listening request for pygame events to the display service. The events parameter is expected to be a list of pygame event constants. """ for event in events: self.send({ "REMOVELISTENEVENT": event, "objectid": id(self) }, "display_signal") def redraw(self): """\ Invoke draw() and save its commands to a newly generated displaylist. The displaylist name is then sent to the display service via a "DISPLAYLIST_UPDATE" request. """ # display list id displaylist = glGenLists(1) # draw object to its displaylist glNewList(displaylist, GL_COMPILE) self.draw() glEndList() dl_update = { "DISPLAYLIST_UPDATE": True, "objectid": id(self), "displaylist": displaylist } self.send(dl_update, "display_signal") ## # Method stubs to be overridden by derived objects ## def handleEvents(self): """ Method stub Override this method to do event handling inside. Should look like this:: while self.dataReady("events"): event = self.recv("events") # handle event ... """ pass def draw(self): """ Method stub Override this method for drawing. Only use commands which are needed for drawing. Will not draw directly but be saved to a displaylist. Therefore, make sure not to use any commands which cannot be stored in displaylists (unlikely anyway). """ pass def setup(self): """ Method stub Override this method for component setup. It will be called on the first scheduling of the component. """ pass def frame(self): """ Method stub Override this method for operations you want to do every frame. It will be called every time the component is scheduled. Do not include infinite loops, the method has to return every time it gets called. """ pass