diff --git a/compass.png b/compass.png new file mode 100644 index 0000000..c2033fe Binary files /dev/null and b/compass.png differ diff --git a/compass.py b/compass.py new file mode 100644 index 0000000..3cc1f56 --- /dev/null +++ b/compass.py @@ -0,0 +1,61 @@ +""" + compass +""" +from __future__ import absolute_import, division, print_function, unicode_literals +import logging +from OpenGL import GL +from drawable import Drawable +from glutils import gl +from mceutils import loadPNGTexture + +log = logging.getLogger(__name__) + + +def makeQuad(minx, miny, width, height): + return [minx, miny, minx+width, miny, minx+width, miny+height, minx, miny + height] + +class CompassOverlay(Drawable): + _tex = None + _yawPitch = (0., 0.) + + def __init__(self, small=False): + super(CompassOverlay, self).__init__() + self.small = small + + @property + def yawPitch(self): + return self._yawPitch + + @yawPitch.setter + def yawPitch(self, value): + self._yawPitch = value + self.invalidate() + + def drawSelf(self): + if self._tex is None: + if self.small: + filename = "compass_small.png" + else: + filename = "compass.png" + + self._tex = loadPNGTexture(filename)#, minFilter=GL.GL_LINEAR, magFilter=GL.GL_LINEAR) + + self._tex.bind() + size = 0.075 + + with gl.glPushMatrix(GL.GL_MODELVIEW): + GL.glLoadIdentity() + + yaw, pitch = self.yawPitch + GL.glTranslatef(1.-size, size, 0.0) # position on upper right corner + GL.glRotatef(180-yaw, 0., 0., 1.) # adjust to north + GL.glColor3f(1., 1., 1.) + + with gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY): + GL.glVertexPointer(2, GL.GL_FLOAT, 0, makeQuad(-size, -size, 2*size, 2*size)) + GL.glTexCoordPointer(2, GL.GL_FLOAT, 0, makeQuad(0, 0, 256, 256)) + + with gl.glEnable(GL.GL_BLEND, GL.GL_TEXTURE_2D): + GL.glDrawArrays(GL.GL_QUADS, 0, 4) + + diff --git a/compass_small.png b/compass_small.png new file mode 100644 index 0000000..16391e8 Binary files /dev/null and b/compass_small.png differ diff --git a/drawable.py b/drawable.py new file mode 100644 index 0000000..3025da6 --- /dev/null +++ b/drawable.py @@ -0,0 +1,62 @@ +""" + ${NAME} +""" +from __future__ import absolute_import, division, print_function, unicode_literals +import logging +log = logging.getLogger(__name__) + +from OpenGL import GL + +class Drawable(object): + + def __init__(self): + super(Drawable, self).__init__() + self._displayList = None + self.invalidList = True + self.children = [] + + def setUp(self): + """ + Set up rendering settings and view matrices + :return: + :rtype: + """ + + def tearDown(self): + """ + Return any settings changed in setUp to their previous states + :return: + :rtype: + """ + + def drawSelf(self): + """ + Draw this drawable, if it has its own graphics. + :return: + :rtype: + """ + + def _draw(self): + self.setUp() + self.drawSelf() + for child in self.children: + child.draw() + self.tearDown() + + def draw(self): + if self._displayList is None: + self._displayList = GL.glGenLists(1) + + if self.invalidList: + self.compileList() + + GL.glCallList(self._displayList) + + def compileList(self): + GL.glNewList(self._displayList, GL.GL_COMPILE) + self._draw() + GL.glEndList() + self.invalidList = False + + def invalidate(self): + self.invalidList = True diff --git a/glutils.py b/glutils.py index cca1b2f..c2d95c8 100644 --- a/glutils.py +++ b/glutils.py @@ -79,6 +79,18 @@ class gl(object): finally: GL.glPopAttrib() + @classmethod + @contextmanager + def glEnableClientState(cls, *enables): + try: + GL.glPushClientAttrib(GL.GL_CLIENT_ALL_ATTRIB_BITS) + for e in enables: + GL.glEnableClientState(e) + + yield + finally: + GL.glPopClientAttrib() + listCount = 0 @classmethod diff --git a/leveleditor.py b/leveleditor.py index 685fd4d..ebeb880 100644 --- a/leveleditor.py +++ b/leveleditor.py @@ -12,6 +12,7 @@ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""" import sys +from compass import CompassOverlay from editortools.thumbview import ThumbView from pymclevel.infiniteworld import SessionLockLost @@ -1304,6 +1305,18 @@ class CameraViewport(GLViewport): if self.drawFog: self.disableFog() + if self._compass is None: + self._compass = CompassOverlay() + + self._compass.yawPitch = self.yaw, 0 + + with gl.glPushMatrix(GL.GL_PROJECTION): + GL.glLoadIdentity() + GL.glOrtho(0., 1., float(self.height) / self.width, 0, -200, 200) + + self._compass.draw() + + _compass = None class ChunkViewport(CameraViewport): defaultScale = 1.0 # pixels per block diff --git a/mceutils.py b/mceutils.py index 93cc490..f17ea74 100644 --- a/mceutils.py +++ b/mceutils.py @@ -306,8 +306,6 @@ def loadPNGFile(filename): powers = (16, 32, 64, 128, 256, 512, 1024, 2048, 4096) assert (w in powers) and (h in powers) # how crude - ndata = numpy.array(data, dtype='uint8') - return w, h, data @@ -316,12 +314,12 @@ def loadTextureFunc(w, h, ndata): return w, h -def loadPNGTexture(filename): +def loadPNGTexture(filename, *a, **kw): filename = os.path.join(directories.dataDir, filename) try: w, h, ndata = loadPNGFile(filename) - tex = glutils.Texture(functools.partial(loadTextureFunc, w, h, ndata)) + tex = glutils.Texture(functools.partial(loadTextureFunc, w, h, ndata), *a, **kw) tex.data = ndata return tex except Exception, e: