#!/usr/bin/env python from OpenGL.GL import * from OpenGL.GLU import * import pygame from pygame.locals import * import sys, StringIO class Log: history = [] output = sys.stdout def Warning(info): history.append(" Warning - %s" % info) output.write(" Warning - %s" % info) def Error(info): history.append(" Error - %s" % info) output.write(" Error - %s" % info) def Critical(info, exception=None): history.append("!!Critical!! - %s" % info) output.write("!!Critical!! - %s" % info) if exception: raise exception class Theme: canvas = (0.5, 0.5, 0.5, 1.0) raised = (0.7, 0.7, 0.7, 1.0) sunken = (0.3, 0.3, 0.3, 1.0) unsel = (0.3, 0.3, 0.3, 1.0) linecol = (0.2, 0.2, 0.2, 1.0) def draw_rectangle(x, y, w, h, drawmode=GL_QUADS): glBegin(drawmode) glVertex2f(x, y) glVertex2f(x + w, y) glVertex2f(x + w, y + h) glVertex2f(x, y + h) glEnd() class Entity: def __init__(self, x, y, w, h): self.x, self.y, self.w, self.h = x, y, w, h self.sel = 0 self.entities = [] self.parent = None def __getpos__(self): if not self.parent: return self.x, self.y x, y = self.parent.position return self.x + x, self.y + y position = property(__getpos__) def linkChild(self, child): self.entities.append(child) child.parent = self def linkChildren(self, *children): for child in children: self.linkChild(child) def unlinkChild(self, child): try: self.entities.remove(child) except ValueError: Log.Error('Unlink failed - No such child : Entity type - %s Child type - %s' % (self.__class__, child.__class__)) def displayEntity(self): print self self.draw() if not self.entities: return #don't bother doing the rest if there are no children x, y, w, h = glGetFloatv(GL_SCISSOR_BOX) #check here for wierd scissor issues if self.x > x: #may be because of upside down y mapping x1 = self.x else: x1 = x if self.x + self.w < x + w: x2 = self.x + self.w else: x2 = x + w if self.y > y: y1 = self.y else: y1 = y if self.y + self.h < y + h: y2 = self.y + self.h else: y2 = y + h abspos = self.position glPushMatrix() glTranslatef(abspos[0], abspos[1], 0) glPushAttrib(GL_SCISSOR_BIT) glScissor(x1, y1, x2-x1, y2-y1) for entity in self.entities: entity.displayEntity() glPopAttrib() glPopMatrix() def draw(self): pass class Rectangle(Entity): def __init__(self, x, y, w, h, col=[.0,.0,.0,1.], drawmode=GL_QUADS): self.x = x self.y = y self.w = w self.h = h self.col = col self.drawmode = drawmode Entity.__init__(self, x, y, w, h) def draw(self): glColor4f(*self.col) draw_rectangle(self.x, self.y, self.w, self.h, self.drawmode) class PanelSunken(Entity): def __init__(self, x, y, w, h): Entity.__init__(self, x, y, w, h) self.linkChild(Rectangle(x, y, w, h, Theme.sunken)) self.linkChild(Rectangle(x + 1, y, w - 1, h - 1, Theme.raised)) self.linkChild(Rectangle(x + 1, y + 1, w - 2, h - 2, Theme.canvas)) class PanelFlat(Entity): def __init__(self, x, y, w, h, col=Theme.sunken, linecol=Theme.linecol): Entity.__init__(self, x, y, w, h) self.linkChild(Rectangle(x, y, w, h, col)) self.linkChild(Rectangle(x, y, w, h, linecol, drawmode=GL_LINE_LOOP)) class GenericButton(PanelSunken): def __init__(self, x, y, w, h, draw=None): PanelSunken.__init__(self, x, y, w, h) self.draw = draw class GenericNodeInterface(Entity): def __init__(self, x, y, w=100, h=100): Entity.__init__(self, x, y, w, h) self.mx = self.my = 0 #offset for mouse moving self.cx = x + w / 2 #center of box x axis self.cy = y + h / 2 #center of box y axis self.border = Rectangle(x - 3, y - 3, w + 3, h + 3, Theme.unsel, drawmode=GL_LINE_LOOP) self.panel = PanelSunken(x, y, w, h) self.input = GenericButton(x + 1, y + 1, 16, 16) self.output = GenericButton(x + w - 17, y + 1, 16, 16) self.properties = GenericButton(x + 17, y + 1, w - 34, 16) self.linkChildren(self.panel, self.input, self.output, self.properties) def drawNodeButtonIdent(self): pass class WindowManager(Entity): GL_MAPPING_Y_STANDARD = 0 GL_MAPPING_Y_INVERT = 1 def __init__(self, width, height, fullscreen=False, resize=False, frameless=False, title='Untitled'): Entity.__init__(self, 0, 0, width, height) self.fullscreen = fullscreen self.resizable = resize self.frameless = frameless self.title = title self.mouse = () self.entities = [] self.y_mapping = WindowManager.GL_MAPPING_Y_STANDARD self.exit = 0 def __getitem__(self, key): if self.__dict__.has_key(key): return self.__dict__[key] else: raise AttributeError, 'Window Manage has no such attribute' def run(self): vid_flags = OPENGL | DOUBLEBUF if self.fullscreen: vid_flags |= FULLSCREEN if self.resizable: vid_flags |= RESIZABLE if self.frameless: vid_flags |= NOFRAME pygame.init() pygame.display.set_mode((self.w, self.h), vid_flags) pygame.display.set_caption(self.title) self.resize((self.w, self.h)) glShadeModel(GL_SMOOTH) glClearColor(*Theme.canvas) glScissor(-self.w, -self.h, self.w * 2, self.h * 2) glEnable(GL_SCISSOR_TEST) while not self.exit: event = pygame.event.poll() self.event_handler(event) self.draw() pygame.display.flip() pygame.quit() def event_handler(self, event): if event.type == NOEVENT: return elif event.type == MOUSEMOTION: pass elif event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): self.exit = 1 def draw(self): glClear(GL_COLOR_BUFFER_BIT) for elem in self.entities: elem.displayEntity() def resize(self, (width, height)): if height==0: height=1 glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() if self.y_mapping == WindowManager.GL_MAPPING_Y_STANDARD: gluOrtho2D(0, width, 0, height) elif self.y_mapping == WindowManager.GL_MAPPING_Y_INVERSE: gluOrtho2D(0, width, height, 0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() wm = WindowManager(500,500) #rect = Rectangle(100, 100, 100, 100, (1.0, 0.0, 0.0, 1.0)) #rect2 = Rectangle(150, 150, 100, 100, (1.0, 1.0, 0.0, 1.0)) #rect.linkChild(rect2) #wm.entities.append(rect) #panel = PanelSunken(100,100,200,200) node = GenericNodeInterface(300,300) wm.entities.append(node) wm.run()