changeset 466:f69ba5ac17c5

qt version of lightsim now works
author drewp@bigasterisk.com
date Mon, 01 Sep 2008 05:36:24 +0000
parents 62bea321edbf
children ab99105cd4fe
files bin/lightsim lightsim/openglsim.py
diffstat 2 files changed, 75 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/bin/lightsim	Mon Sep 01 05:35:58 2008 +0000
+++ b/bin/lightsim	Mon Sep 01 05:36:24 2008 +0000
@@ -2,18 +2,17 @@
 
 from __future__ import division
 import run_local
-import xmlrpclib, sys, logging
+import sys, logging
 
 sys.path.append("lib")
 import qt4reactor
 qt4reactor.install()
 
-from rdflib import Literal, URIRef
 from twisted.internet import reactor
 from twisted.internet.task import LoopingCall
 from twisted.web.xmlrpc import Proxy
 from louie import dispatcher
-from PyQt4 import QtCore, QtGui, QtOpenGL
+from PyQt4.QtGui import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QMainWindow
 from OpenGL.GL import *
 from OpenGL.GLU import *
 
@@ -25,11 +24,21 @@
 logging.basicConfig(format="%(asctime)s %(levelname)-5s %(name)s %(filename)s:%(lineno)d: %(message)s")
 log.setLevel(logging.DEBUG)
 
+def filenamesForChan(graph, chan):
+    for lyr in graph.objects(chan, L9['previewLayer']):
+        for imgPath in graph.objects(lyr, L9['path']):
+            yield imgPath
+
+_lastLevels = None
 def poll(graph, serv, pollFreq, oglSurface):
     pollFreq.update()
     dispatcher.send("status", key="pollFreq", value=str(pollFreq))
     d = serv.callRemote("currentlevels", dmxclient._id)
     def received(dmxLevels):
+        global _lastLevels
+        if dmxLevels == _lastLevels:
+            return
+        _lastLevels = dmxLevels
         level = {} # filename : level
         for i, lev in enumerate(dmxLevels):
             if lev == 0:
@@ -40,79 +49,77 @@
             except KeyError:
                 continue
 
-            for lyr in graph.objects(chan, L9['previewLayer']):
-                for imgPath in graph.objects(lyr, L9['path']):
-                    level[str(imgPath)] = lev
+            for imgPath in filenamesForChan(graph, chan):
+                level[str(imgPath)] = lev
 
         oglSurface.newLevels(levels=level)
     d.addCallback(received)
     return d
 
-class StatusKeys(object):
-    # watch out- this might be an accidental redo of what curvecalc
-    # has. Or, maybe CC should use this obj
-    def __init__(self, master):
-        tk.Frame.__init__(self, master)
+class StatusKeys(QWidget):
+    """listens for dispatcher signal 'status' and displays the key/value args"""
+    def __init__(self, parent):
+        QWidget.__init__(self)
+        self.layout = QVBoxLayout()
+        self.setLayout(self.layout)
+        self.row = {} # key name : (Frame, value Label)
         dispatcher.connect(self.status, "status")
-        self.row = {} # key name : (Frame, value Label)
         
     def status(self, key, value):
         if key not in self.row:
-            f = tk.Frame(self)
-            f.pack(side='top')
-            tk.Label(f, text=key, font="arial 8").pack(side='left')
-            l = tk.Label(f, text=value, font="arial 8")
-            l.pack(side='left')
-            self.row[key] = (f, l)
+            row = QWidget()
+            self.layout.addWidget(row)
+            cols = QHBoxLayout()
+            row.setLayout(cols)
+            lab1 = QLabel(key)
+            lab2 = QLabel(value)
+            cols.addWidget(lab1)
+            cols.addWidget(lab2)
+            self.row[key] = lab2
         else:
-            row, lab = self.row[key]
-            lab.config(text=value)
-
+            lab = self.row[key]
+            lab.setText(value)
 
-
-class Window(QtGui.QMainWindow):
+class Window(QMainWindow):
     def __init__(self, filenames):
-        QtGui.QMainWindow.__init__(self, None)
+        QMainWindow.__init__(self, None)
+        self.setWindowTitle(dmxclient._id)
 
-        self.w = QtGui.QWidget()
-        self.setCentralWidget(self.w)
+        w = QWidget()
+        self.setCentralWidget(w)
+        mainLayout = QVBoxLayout()
+        w.setLayout(mainLayout)
         
-        self.glWidget = Surface(self, filenames,
-                                width=120*3, height=80*3,
-                                imgRescaleTo=128)
+        self.glWidget = Surface(self, filenames, imgRescaleTo=128*2)
+
+        mainLayout.addWidget(self.glWidget)
+
+        status = StatusKeys(mainLayout)
+        mainLayout.addWidget(status)      
 
-        self.glWidget.newLevels(levels={
-            "lightsim/skyline/front-left.png" : .4,
-            "lightsim/skyline/front-right.png" : .8})
-
-        mainLayout = QtGui.QHBoxLayout()
-        mainLayout.addWidget(self.glWidget)
-        self.w.setLayout(mainLayout)
-
-        self.setWindowTitle(dmxclient._id)
+def requiredImages(graph):
+    """filenames that we'll need to show, based on a config structure
+    like this:
+      ch:frontLeft a :Channel;
+         :previewLayer [ :path "lightsim/skyline/front-left.png" ] .
+    """
+    filenames = []
+    for lyr in graph.objects(None, L9['previewLayer']):
+        for p in graph.objects(lyr, L9['path']):
+            filenames.append(str(p))
+    return filenames
 
 if __name__ == '__main__':
     app = reactor.qApp
 
     graph = showconfig.getGraph()
-    filenames = []
-    for lyr in graph.objects(None, L9['previewLayer']):
-        for p in graph.objects(lyr, L9['path']):
-            filenames.append(str(p))
-    filenames.append("lightsim/skyline/front-left.png") # test
-    filenames.append("lightsim/skyline/front-right.png") # test
 
-    window = Window(filenames)
+    window = Window(requiredImages(graph))
     window.show()
 
     serv = Proxy(networking.dmxServerUrl())
-    pollFreq = updatefreq.Updatefreq(samples=5)
-    LoopingCall(poll, graph, serv, pollFreq, window.glWidget).start(.1)
+    pollFreq = updatefreq.Updatefreq()
+    LoopingCall(poll, graph, serv, pollFreq, window.glWidget).start(.05)
 
     reactor.run()
 
-
-######################################################
-#sk = StatusKeys(root)
-#sk.pack(side='top', fill='x')
-#prof.run(reactor.run, profile=False)
--- a/lightsim/openglsim.py	Mon Sep 01 05:35:58 2008 +0000
+++ b/lightsim/openglsim.py	Mon Sep 01 05:36:24 2008 +0000
@@ -8,7 +8,8 @@
 import Image
 from louie import dispatcher
 
-from PyQt4 import QtCore, QtOpenGL
+from PyQt4.QtCore import QSize
+from PyQt4.QtOpenGL import QGLWidget
 from OpenGL.GL import *
 
 def xxxdrawWithAlpha(imgString, w, h, alpha):
@@ -21,15 +22,14 @@
     #glBlendColor(1, 1, 1, mag) # needs ARB_imaging
     glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, imgString)
 
-class Surface(QtOpenGL.QGLWidget):
+class Surface(QGLWidget):
     """widget that adds multiple image files together with adjustable scales"""
-    def __init__(self, parent, filenames, width=512, height=270,
-                 imgRescaleTo=None):
+    def __init__(self, parent, filenames, imgRescaleTo=None):
         """
         imgRescaleTo can be a length of pixels to reduce all the input
         images into. Try 64 for a low res drawing.
         """
-        QtOpenGL.QGLWidget.__init__(self, parent)
+        QGLWidget.__init__(self, parent)
 
         self.levels = {} # filename : brightness
   
@@ -37,6 +37,7 @@
         for filename in filenames:
             print "open", filename
             im = Image.open(filename)
+            self.origImageSize = im.size[0], im.size[1]
             if imgRescaleTo:
                 im.thumbnail((imgRescaleTo, imgRescaleTo))
             im = im.transpose(Image.FLIP_TOP_BOTTOM)
@@ -44,8 +45,6 @@
             self.imageHeight = im.size[1]
             self.image[filename] = im.convert("RGBA").tostring()
   
-        #self.set_centerpoint(0, 0, 0)
-
     def initializeGL(self): 
         glDisable(GL_CULL_FACE)
         glShadeModel(GL_FLAT)
@@ -53,11 +52,8 @@
         import OpenGL
         print OpenGL.__version__
        
-#    def minimumSizeHint(self):
-#        return QtCore.QSize(512, 512)
-
-#    def sizeHint(self):
-#        return QtCore.QSize(512, 512)
+    def sizeHint(self):
+        return QSize(*self.origImageSize)
 
     def paintGL(self):
         """you set self.levels to dict and call tkRedraw"""
@@ -75,20 +71,23 @@
 
         # drawing to glAccum might be good
         layerTimes = []
+        layers = 0
         for filename, mag in self.levels.items():
             t = time.time()
-            self.drawWithAlpha(self.image[filename],
-                               self.imageWidth, self.imageHeight, mag)
+            layers += self.drawWithAlpha(self.image[filename],
+                                         self.imageWidth, self.imageHeight, mag)
             layerTimes.append(time.time() - t)
 
+        dispatcher.send("status", key="visibleLayers", value=str(layers))
+
         dispatcher.send("status", key="redraw",
                         value="%.1fms" % ((time.time() - start) * 1000))
         
 
     def drawWithAlpha(self, imgString, w, h, alpha):
-        """without opengl extensions"""
+        """without opengl extensions. Returns number of layers drawn"""
         if alpha == 0:
-            return
+            return 0
         t = time.time()
         ar = num.reshape(num.fromstring(imgString, dtype='uint8'),
                          (w * h, 4))
@@ -109,6 +108,7 @@
         glDrawPixels(w, h,
                      GL_RGBA, GL_UNSIGNED_BYTE, ar.tostring())
         #print "  draw", time.time() - t
+        return 1
 
     def newLevels(self, event=None, levels=None):
         if levels != self.levels: