| 1 | # PySoy widgets.Canvas class |
|---|
| 2 | # |
|---|
| 3 | # Copyright (C) 2006,2007,2008,2009 PySoy Group |
|---|
| 4 | # |
|---|
| 5 | # This program is free software; you can redistribute it and/or modify |
|---|
| 6 | # it under the terms of the GNU Affero General Public License as published |
|---|
| 7 | # by the Free Software Foundation, either version 3 of the License, or |
|---|
| 8 | # (at your option) any later version. |
|---|
| 9 | # |
|---|
| 10 | # This program is distributed in the hope that it will be useful, |
|---|
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | # GNU Affero General Public License for more details. |
|---|
| 14 | # |
|---|
| 15 | # You should have received a copy of the GNU Affero General Public License |
|---|
| 16 | # along with this program; if not, see http://www.gnu.org/licenses |
|---|
| 17 | # |
|---|
| 18 | # $Id: Canvas.pym 1393 2008-12-31 23:51:25Z ArcRiley $ |
|---|
| 19 | |
|---|
| 20 | cdef class Canvas (Widget) : |
|---|
| 21 | """ |
|---|
| 22 | Renders a :class:`~soy.textures.Texture`. |
|---|
| 23 | |
|---|
| 24 | Since :class:`~soy.textures.Texture`s can be any sort of bitmap, including text, images, |
|---|
| 25 | and video, adding a :class:`~soy.widgets.Canvas` to a :class:`~soy.Window` containing a video or |
|---|
| 26 | image before adding a :class:`~soy.widgets.Projector` will create a background. The |
|---|
| 27 | :class:`~soy.widgets.Canvas` will be rendered, then the :class:`~soy.widgets.Projector` will render the |
|---|
| 28 | scene, overwriting the :class:`~soy.widgets.Canvas` where scene elements overlap. |
|---|
| 29 | |
|---|
| 30 | Adding a :class:`~soy.widgets.Canvas` after a :class:`~soy.widgets.Projector` with a :class:`~soy.textures.Print` can also be |
|---|
| 31 | used to create a heads-up display. The :class:`~soy.widgets.Projector` renders the |
|---|
| 32 | scene, then the :class:`~soy.widgets.Canvas` renders the :class:`~soy.widgets.Print` texture on top of the |
|---|
| 33 | :class:`~soy.scenes.Scene`, overwriting the overlapping scene regions. |
|---|
| 34 | |
|---|
| 35 | Even more effects can be created by combining :class:`~soy.widgets.Canvas`es with the |
|---|
| 36 | different :class:`~soy.widgets.Container` subclasses. |
|---|
| 37 | """ |
|---|
| 38 | |
|---|
| 39 | ############################################################################ |
|---|
| 40 | # |
|---|
| 41 | # Python functions |
|---|
| 42 | # |
|---|
| 43 | |
|---|
| 44 | def __cinit__(self, parent=None, margin=None, aspect=-1.0, |
|---|
| 45 | texture=None, |
|---|
| 46 | *args, **keywords) : |
|---|
| 47 | ###################################### |
|---|
| 48 | # |
|---|
| 49 | # Pass arguments to properties |
|---|
| 50 | # |
|---|
| 51 | self.texture = texture |
|---|
| 52 | if aspect < 0.0 : |
|---|
| 53 | self._aspect = (<soy.textures.Texture> self._texture)._aspect |
|---|
| 54 | # |
|---|
| 55 | ###################################### |
|---|
| 56 | # |
|---|
| 57 | # Static Vertex and Face Array |
|---|
| 58 | # |
|---|
| 59 | # self._verts[0] = (0,0) - no change needed |
|---|
| 60 | # self._verts[1] = (1,0) - change X to 1.0 |
|---|
| 61 | # self._verts[2] = (1,1) - change both X and Y to 1.0 |
|---|
| 62 | # self._verts[3] = (0,1) - change Y to 1.0 |
|---|
| 63 | # |
|---|
| 64 | # Thus, these verts form a 1x1 square with 2 tris (A and B) : |
|---|
| 65 | # 3----2 |
|---|
| 66 | # | B/ | |
|---|
| 67 | # | /A | |
|---|
| 68 | # 0----1 |
|---|
| 69 | # |
|---|
| 70 | self._verts[1].px = 1.0 |
|---|
| 71 | self._verts[1].tx = 1.0 |
|---|
| 72 | self._verts[2].px = 1.0 |
|---|
| 73 | self._verts[2].py = 1.0 |
|---|
| 74 | self._verts[2].tx = 1.0 |
|---|
| 75 | self._verts[2].ty = 1.0 |
|---|
| 76 | self._verts[3].py = 1.0 |
|---|
| 77 | self._verts[3].ty = 1.0 |
|---|
| 78 | self._faces[0].a = 0 |
|---|
| 79 | self._faces[0].b = 1 |
|---|
| 80 | self._faces[0].c = 2 |
|---|
| 81 | self._faces[1].a = 2 |
|---|
| 82 | self._faces[1].b = 3 |
|---|
| 83 | self._faces[1].c = 0 |
|---|
| 84 | # |
|---|
| 85 | ###################################### |
|---|
| 86 | |
|---|
| 87 | |
|---|
| 88 | ############################################################################ |
|---|
| 89 | # |
|---|
| 90 | # C functions |
|---|
| 91 | # |
|---|
| 92 | |
|---|
| 93 | cdef void _render(self) : |
|---|
| 94 | cdef int _i |
|---|
| 95 | # |
|---|
| 96 | ###################################### |
|---|
| 97 | # |
|---|
| 98 | # don't bother rendering w/o a texture |
|---|
| 99 | # |
|---|
| 100 | if self._texture is None : |
|---|
| 101 | return |
|---|
| 102 | # |
|---|
| 103 | ###################################### |
|---|
| 104 | # |
|---|
| 105 | # Set the viewport to the current Widget position and size |
|---|
| 106 | # |
|---|
| 107 | gl.glViewport(self._xpos, self._ypos, self._width, self._height) |
|---|
| 108 | # |
|---|
| 109 | ###################################### |
|---|
| 110 | # |
|---|
| 111 | # Reset the projection and modelview matrix, set ortho rendering |
|---|
| 112 | # |
|---|
| 113 | gl.glMatrixMode(gl.GL_PROJECTION) |
|---|
| 114 | gl.glLoadIdentity() |
|---|
| 115 | gl.glOrtho(0.0, 1.0, 0.0, 1.0, -1, 1) |
|---|
| 116 | gl.glMatrixMode(gl.GL_MODELVIEW) |
|---|
| 117 | gl.glLoadIdentity() |
|---|
| 118 | # |
|---|
| 119 | ###################################### |
|---|
| 120 | # |
|---|
| 121 | # VBO-ONLY: Unbind buffers |
|---|
| 122 | # |
|---|
| 123 | if gl.GLEW_ARB_vertex_buffer_object : |
|---|
| 124 | gl.glBindBufferARB (gl.GL_ELEMENT_ARRAY_BUFFER_ARB, 0) |
|---|
| 125 | gl.glBindBufferARB (gl.GL_ARRAY_BUFFER_ARB, 0) |
|---|
| 126 | # |
|---|
| 127 | ###################################### |
|---|
| 128 | # |
|---|
| 129 | # enable texture0 |
|---|
| 130 | # |
|---|
| 131 | gl.glClientActiveTexture(gl.GL_TEXTURE0) |
|---|
| 132 | gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) |
|---|
| 133 | self._texture._enable() |
|---|
| 134 | # |
|---|
| 135 | ###################################### |
|---|
| 136 | # |
|---|
| 137 | # Enable blending if texture has an alpha channel (LA or RGBA) |
|---|
| 138 | # |
|---|
| 139 | if self._texture._chans & 1: |
|---|
| 140 | gl.glDisable(gl.GL_BLEND) |
|---|
| 141 | else: |
|---|
| 142 | gl.glEnable(gl.GL_BLEND) |
|---|
| 143 | gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) |
|---|
| 144 | # |
|---|
| 145 | ###################################### |
|---|
| 146 | # |
|---|
| 147 | # Set vertex, normal, and texcoord pointers and draw |
|---|
| 148 | # |
|---|
| 149 | gl.glVertexPointer (3, gl.GL_FLOAT, 48, &self._verts[0].px) |
|---|
| 150 | gl.glNormalPointer ( gl.GL_FLOAT, 48, &self._verts[0].nx) |
|---|
| 151 | gl.glTexCoordPointer(3, gl.GL_FLOAT, 48, &self._verts[0].tx) |
|---|
| 152 | gl.glDrawElements (gl.GL_TRIANGLES, 6, gl.GL_UNSIGNED_SHORT, |
|---|
| 153 | <unsigned short*> self._faces) |
|---|
| 154 | # |
|---|
| 155 | ###################################### |
|---|
| 156 | # |
|---|
| 157 | # Disable blending when using alpha texture, disable texture, and return |
|---|
| 158 | # |
|---|
| 159 | if not self._texture._chans & 1 : |
|---|
| 160 | gl.glDisable(gl.GL_BLEND) |
|---|
| 161 | self._texture._disable() |
|---|
| 162 | # |
|---|
| 163 | ###################################### |
|---|
| 164 | |
|---|
| 165 | |
|---|
| 166 | ############################################################################ |
|---|
| 167 | # |
|---|
| 168 | # Properties |
|---|
| 169 | # |
|---|
| 170 | |
|---|
| 171 | property texture : |
|---|
| 172 | """ |
|---|
| 173 | :class:`~soy.textures.Texture` rendered by this :class:`~soy.widgets.Canvas`. Setting to None or |
|---|
| 174 | deleting it disables this Canvas. This can be changed at any time |
|---|
| 175 | to change the :class:`~soy.textures.Texture` this :class:`~soy.widgets.Canvas` renders. |
|---|
| 176 | """ |
|---|
| 177 | |
|---|
| 178 | def __get__(self) : |
|---|
| 179 | if self._texture : |
|---|
| 180 | return self._texture |
|---|
| 181 | return None |
|---|
| 182 | def __set__(self, value) : |
|---|
| 183 | if isinstance(value, soy.textures.Texture) or value == None : |
|---|
| 184 | self._texture = value |
|---|
| 185 | else : |
|---|
| 186 | raise TypeError('that is not a texture') |
|---|
| 187 | def __del__(self) : |
|---|
| 188 | self._texture = None |
|---|