changeset 303:d434a74fc068

moves/removes
author drewp@bigasterisk.com
date Tue, 21 Mar 2006 04:50:35 +0000
parents 11597ff6ff6a
children 5f9cf6174e62
files bin/tracker doc/talk.py flax/tracker light9/Effects.py
diffstat 4 files changed, 273 insertions(+), 450 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/tracker	Tue Mar 21 04:50:35 2006 +0000
@@ -0,0 +1,273 @@
+#!/usr/bin/python
+from __future__ import division,nested_scopes
+
+import sys
+sys.path.append("../../editor/pour")
+sys.path.append("../light8")
+
+from Submaster import Submaster
+from skim.zooming import Zooming,Pair
+from math import sqrt,sin,cos
+from pygame.rect import Rect
+from xmlnodebase import xmlnodeclass,collectiveelement,xmldocfile
+from dispatch import dispatcher
+
+import dmxclient
+
+import Tkinter as tk
+
+defaultfont="arial 8"
+
+def pairdist(pair1,pair2):
+    return pair1.dist(pair2)
+
+def canvashighlighter(canvas,obj,attribute,normalval,highlightval):
+    """creates bindings on a canvas obj that make attribute go
+    from normal to highlight when the mouse is over the obj"""
+    canvas.tag_bind(obj,"<Enter>",
+                    lambda ev: canvas.itemconfig(obj,**{attribute:highlightval}))
+    canvas.tag_bind(obj,"<Leave>",
+                    lambda ev: canvas.itemconfig(obj,**{attribute:normalval}))
+
+class Field(xmlnodeclass):
+    
+    """one light has a field of influence. for any point on the
+    canvas, you can ask this field how strong it is. """
+
+    def name(self,newval=None):
+        """light/sub name"""
+        return self._getorsetattr("name",newval)
+    def center(self,x=None,y=None):
+        """x,y float coords for the center of this light in the field. returns
+        a Pair, although it accepts x,y"""
+        return Pair(self._getorsettypedattr("x",float,x),
+                    self._getorsettypedattr("y",float,y))
+
+    def falloff(self,dist=None):
+        
+        """linear falloff from 1 at center, to 0 at dist pixels away
+        from center"""
+        return self._getorsettypedattr("falloff",float,dist)
+
+    def getdistforintensity(self,intens):
+        """returns the distance you'd have to be for the given intensity (0..1)"""
+        return (1-intens)*self.falloff()
+
+    def calc(self,x,y):
+        """returns field strength at point x,y"""
+        dist=pairdist(Pair(x,y),self.center())
+        return max(0,(self.falloff()-dist)/self.falloff())
+
+class Fieldset(collectiveelement):
+    """group of fields. persistent."""
+    def childtype(self): return Field
+
+    def version(self):
+        """read-only version attribute on fieldset tag"""
+        return self._getorsetattr("version",None)
+
+    def report(self,x,y):
+        """reports active fields and their intensities"""
+        active=0
+        for f in self.getall():
+            name=f.name()
+            intens=f.calc(x,y)
+            if intens>0:
+                print name,intens,
+                active+=1
+        if active>0:
+            print
+        self.dmxsend(x,y)
+    def dmxsend(self,x,y):
+        """output lights to dmx"""
+        levels=dict([(f.name(),f.calc(x,y)) for f in self.getall()])
+        dmxlist=Submaster(None,levels).get_dmx_list()
+        dmxclient.outputlevels(dmxlist)
+        
+        
+    def getbounds(self):
+        """returns xmin,xmax,ymin,ymax for the non-zero areas of this field"""
+        r=None
+        for f in self.getall():
+            rad=f.getdistforintensity(0)
+            fx,fy=f.center()
+            fieldrect=Rect(fx-rad,fy-rad,rad*2,rad*2)
+            if r is None:
+                r=fieldrect
+            else:
+                r=r.union(fieldrect)
+        return r.left,r.right,r.top,r.bottom
+
+class Fieldsetfile(xmldocfile):
+    def __init__(self,filename):
+        self._openornew(filename,topleveltype=Fieldset)
+    def fieldset(self):
+        return self._gettoplevel()
+
+########################################################################
+########################################################################
+
+class FieldDisplay:
+    """the view for a Field."""
+    def __init__(self,canvas,field):
+        self.canvas=canvas
+        self.field=field
+        self.tags=[str(id(self))] # canvas tag to id our objects
+        
+    def setcoords(self):
+        """adjust canvas obj coords to match the field"""
+        # this uses the canvas object ids saved by makeobjs
+        f=self.field
+        c=self.canvas
+        w2c=self.canvas.world2canvas
+
+        # rings
+        for intens,ring in self.rings.items():
+            rad=f.getdistforintensity(intens)
+            p1=w2c(*(f.center()-Pair(rad,rad)))
+            p2=w2c(*(f.center()+Pair(rad,rad)))
+            c.coords(ring,p1[0],p1[1],p2[0],p2[1])
+
+        # text
+        p1=w2c(*f.center())
+        c.coords(self.txt,*p1)
+
+    def makeobjs(self):
+        """(re)create the canvas objs (null coords) and make their bindings"""
+        c=self.canvas
+        f=self.field
+        c.delete(self.tags)
+
+        w2c=self.canvas.world2canvas
+
+        # make rings
+        self.rings={} # rad,canvasobj
+        for intens,color in (#(1,'white'),
+                             (.8,'gray90'),(.6,'gray80'),(.4,'gray60'),(.2,'gray50'),
+                             (0,'#000080')):
+            self.rings[intens]=c.create_oval(0,0,0,0,
+                                          outline=color,width=2,tags=self.tags,
+                                          outlinestipple='gray50')
+
+        # make text
+        self.txt=c.create_text(0,0,text=f.name(),font=defaultfont+" bold",
+                               fill='white',anchor='c',
+                               tags=self.tags)
+
+        # highlight text bindings
+        canvashighlighter(c,self.txt,'fill',normalval='white',highlightval='red')
+
+        # position drag bindings
+        def press(ev):
+            self._lastmouse=ev.x,ev.y
+        def motion(ev):
+            dcan=Pair(*[a-b for a,b in zip((ev.x,ev.y),self._lastmouse)])
+            dworld=c.canvas2world_vector(*dcan)
+            self.field.center(*(self.field.center()+dworld))
+            self._lastmouse=ev.x,ev.y
+            self.setcoords() # redraw
+        def release(ev):
+            if hasattr(self,'_lastmouse'):
+                del self._lastmouse
+            dispatcher.send("field coord changed") # updates bounds
+            
+        c.tag_bind(self.txt,"<ButtonPress-1>",press)
+        c.tag_bind(self.txt,"<B1-Motion>",motion)
+        c.tag_bind(self.txt,"<B1-ButtonRelease>",release)
+
+        # radius drag bindings
+        outerring=self.rings[0]
+        canvashighlighter(c,outerring,
+                          'outline',normalval='#000080',highlightval='#4040ff')
+        def motion(ev):
+            worldmouse=self.canvas.canvas2world(ev.x,ev.y)
+            currentdist=pairdist(worldmouse,self.field.center())
+            self.field.falloff(currentdist)
+            self.setcoords()
+        c.tag_bind(outerring,"<B1-Motion>",motion)
+        c.tag_bind(outerring,"<B1-ButtonRelease>",release) # from above
+
+        self.setcoords()
+    
+class Tracker(tk.Frame):
+
+    """whole tracker widget, which is mostly a view for a
+    Fieldset. tracker makes its own fieldset"""
+
+    # world coords of the visible canvas (preserved even in window resizes)
+    xmin=0
+    xmax=100
+    ymin=0
+    ymax=100
+
+    fieldsetfile=None
+    displays=None # Field : FieldDisplay. we keep these in sync with the fieldset
+    
+    def __init__(self,master):
+        tk.Frame.__init__(self,master)
+
+        self.displays={}
+        
+        c=self.canvas=Zooming(self,bg='black',closeenough=5)
+        c.pack(fill='both',exp=1)
+
+        # preserve edge coords over window resize
+        c.bind("<Configure>",self.configcoords)
+        
+        c.bind("<Motion>",
+               lambda ev: self._fieldset().report(*c.canvas2world(ev.x,ev.y)))
+        def save(ev):
+            print "saving"
+            self.fieldsetfile.save()
+        master.bind("<Key-s>",save)
+        dispatcher.connect(self.autobounds,"field coord changed")
+
+    def _fieldset(self):
+        return self.fieldsetfile.fieldset()
+
+    def load(self,filename):
+        self.fieldsetfile=Fieldsetfile(filename)
+        self.displays.clear()
+        for f in self.fieldsetfile.fieldset().getall():
+            self.displays[f]=FieldDisplay(self.canvas,f)
+            self.displays[f].makeobjs()
+        self.autobounds()
+
+    def configcoords(self,*args):
+        # force our canvas coords to stay at the edges of the window
+        c=self.canvas
+        cornerx,cornery=c.canvas2world(0,0)
+        c.move(cornerx-self.xmin,
+               cornery-self.ymin)
+        c.setscale(0,0,
+                   c.winfo_width()/(self.xmax-self.xmin),
+                   c.winfo_height()/(self.ymax-self.ymin))
+
+    def autobounds(self):
+        """figure out our bounds from the fieldset, and adjust the display zooms.
+        writes the corner coords onto the canvas."""
+        self.xmin,self.xmax,self.ymin,self.ymax=self._fieldset().getbounds()
+
+        self.configcoords()
+        
+        c=self.canvas
+        c.delete('cornercoords')
+        for x,anc2 in ((self.xmin,'w'),(self.xmax,'e')):
+            for y,anc1 in ((self.ymin,'n'),(self.ymax,'s')):
+                pos=c.world2canvas(x,y)
+                c.create_text(pos[0],pos[1],text="%s,%s"%(x,y),
+                              fill='white',anchor=anc1+anc2,
+                              tags='cornercoords')
+        [d.setcoords() for d in self.displays.values()]
+
+########################################################################
+########################################################################
+                
+root=tk.Tk()
+root.wm_geometry('700x350')
+tra=Tracker(root)
+tra.pack(fill='both',exp=1)
+
+tra.load("fieldsets/demo")
+
+root.mainloop()
--- a/doc/talk.py	Tue Mar 21 04:45:56 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-def light9_presentation():
-    """
-    Drew Perttula
-
-    drewp@bigasterisk.com
-
-    http://light9.bigasterisk.com
-
-
-    Goals of light9:
-
-    - control the brightness of many lights while playing music
-
-    - allow easy editing of the show
-
-    - allow easy maintenance of the code, even while the show is running
-
-
-
-
-
-
-
-
-    """
-
-
-
-
-
-
-
-
-
-def dependencies():
-    """
-    Twisted - event loop and networking
-    TwistedWeb - xmlrpc protocol
-    tk, tix
-    pympd - my twisted interface to mpd
-    pydispatcher - signals
-
-    mpd - music player daemon
-
-    swig - interface to C code
-    darcs
-
-*
-
-
-
-
-
-
-    """
-
-
-
-
-
-def connections():
-    """
-               (play cmds)
-    ascoltami --------------> mpd ----------> audio out
-        | (timing)
-        v
-    curvecalc    subcomposer    keyboardcomposer
-        |            |                 |
-        +---         |             ----+
-            \-----   |    --------/
-                  \--+---/
-                     | (light levels)
-                     v
-*                dmxserver
-                    | (dmx levels)
-          ......... v ....................
-          .      chippy                  .
-          .         | (dmx)              . external hardware
-          .         v                    .
-          .      dmx dimmer              .
-          .         | (juice)            .
-          .         v                    .
-          .      light                   .
-          ................................
-    """
-
-
-def metrics():
-    """
-    selected linecounts:
-      356 ascoltami              (music player)
-      318 curvecalc              (curve and expression editor)
-      279 keyboardcomposer
-      189 dmxserver              (hardware output)
-      153 subcomposer
-       17 wavecurve              (create smoothed waveforms from .wav)
-
-      311 light9/curve.py        (curve widgets)
-      191 light9/FlyingFader.py  (enhanced tk.Scale)
-      168 light9/Submaster.py
-*     151 light9/zoomcontrol.py
-      137 light9/dmxchanedit.py
-       40 light9/wavepoints.py
-
-       65 light9/io/parport.c    (dmx interface protocol)
-       50 light9/io/serport.i    (i2c interface to sliders)
-
-    total in project: about 3200 in about 30 files
-
-    """
-
-
-
-def future_projects():
-    """
-    A submaster server that talks with the other programs and
-    eliminates all the explicit saving and reloading of subs
-
-    More abstract output layer, to which I can add home lighting, for
-    example
-
-    Small timed 'clips' that can be triggered
-
-    Generalize to a whizzy, distributed real-time circuit simulator
-    node network with a 5GL editor and failsafe checkpointing and
-    redundancy
-*
-
-
-
-    """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- a/flax/tracker	Tue Mar 21 04:45:56 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +0,0 @@
-#!/usr/bin/python
-from __future__ import division,nested_scopes
-
-import sys
-sys.path.append("../../editor/pour")
-sys.path.append("../light8")
-
-from Submaster import Submaster
-from skim.zooming import Zooming,Pair
-from math import sqrt,sin,cos
-from pygame.rect import Rect
-from xmlnodebase import xmlnodeclass,collectiveelement,xmldocfile
-from dispatch import dispatcher
-
-import dmxclient
-
-import Tkinter as tk
-
-defaultfont="arial 8"
-
-def pairdist(pair1,pair2):
-    return pair1.dist(pair2)
-
-def canvashighlighter(canvas,obj,attribute,normalval,highlightval):
-    """creates bindings on a canvas obj that make attribute go
-    from normal to highlight when the mouse is over the obj"""
-    canvas.tag_bind(obj,"<Enter>",
-                    lambda ev: canvas.itemconfig(obj,**{attribute:highlightval}))
-    canvas.tag_bind(obj,"<Leave>",
-                    lambda ev: canvas.itemconfig(obj,**{attribute:normalval}))
-
-class Field(xmlnodeclass):
-    
-    """one light has a field of influence. for any point on the
-    canvas, you can ask this field how strong it is. """
-
-    def name(self,newval=None):
-        """light/sub name"""
-        return self._getorsetattr("name",newval)
-    def center(self,x=None,y=None):
-        """x,y float coords for the center of this light in the field. returns
-        a Pair, although it accepts x,y"""
-        return Pair(self._getorsettypedattr("x",float,x),
-                    self._getorsettypedattr("y",float,y))
-
-    def falloff(self,dist=None):
-        
-        """linear falloff from 1 at center, to 0 at dist pixels away
-        from center"""
-        return self._getorsettypedattr("falloff",float,dist)
-
-    def getdistforintensity(self,intens):
-        """returns the distance you'd have to be for the given intensity (0..1)"""
-        return (1-intens)*self.falloff()
-
-    def calc(self,x,y):
-        """returns field strength at point x,y"""
-        dist=pairdist(Pair(x,y),self.center())
-        return max(0,(self.falloff()-dist)/self.falloff())
-
-class Fieldset(collectiveelement):
-    """group of fields. persistent."""
-    def childtype(self): return Field
-
-    def version(self):
-        """read-only version attribute on fieldset tag"""
-        return self._getorsetattr("version",None)
-
-    def report(self,x,y):
-        """reports active fields and their intensities"""
-        active=0
-        for f in self.getall():
-            name=f.name()
-            intens=f.calc(x,y)
-            if intens>0:
-                print name,intens,
-                active+=1
-        if active>0:
-            print
-        self.dmxsend(x,y)
-    def dmxsend(self,x,y):
-        """output lights to dmx"""
-        levels=dict([(f.name(),f.calc(x,y)) for f in self.getall()])
-        dmxlist=Submaster(None,levels).get_dmx_list()
-        dmxclient.outputlevels(dmxlist)
-        
-        
-    def getbounds(self):
-        """returns xmin,xmax,ymin,ymax for the non-zero areas of this field"""
-        r=None
-        for f in self.getall():
-            rad=f.getdistforintensity(0)
-            fx,fy=f.center()
-            fieldrect=Rect(fx-rad,fy-rad,rad*2,rad*2)
-            if r is None:
-                r=fieldrect
-            else:
-                r=r.union(fieldrect)
-        return r.left,r.right,r.top,r.bottom
-
-class Fieldsetfile(xmldocfile):
-    def __init__(self,filename):
-        self._openornew(filename,topleveltype=Fieldset)
-    def fieldset(self):
-        return self._gettoplevel()
-
-########################################################################
-########################################################################
-
-class FieldDisplay:
-    """the view for a Field."""
-    def __init__(self,canvas,field):
-        self.canvas=canvas
-        self.field=field
-        self.tags=[str(id(self))] # canvas tag to id our objects
-        
-    def setcoords(self):
-        """adjust canvas obj coords to match the field"""
-        # this uses the canvas object ids saved by makeobjs
-        f=self.field
-        c=self.canvas
-        w2c=self.canvas.world2canvas
-
-        # rings
-        for intens,ring in self.rings.items():
-            rad=f.getdistforintensity(intens)
-            p1=w2c(*(f.center()-Pair(rad,rad)))
-            p2=w2c(*(f.center()+Pair(rad,rad)))
-            c.coords(ring,p1[0],p1[1],p2[0],p2[1])
-
-        # text
-        p1=w2c(*f.center())
-        c.coords(self.txt,*p1)
-
-    def makeobjs(self):
-        """(re)create the canvas objs (null coords) and make their bindings"""
-        c=self.canvas
-        f=self.field
-        c.delete(self.tags)
-
-        w2c=self.canvas.world2canvas
-
-        # make rings
-        self.rings={} # rad,canvasobj
-        for intens,color in (#(1,'white'),
-                             (.8,'gray90'),(.6,'gray80'),(.4,'gray60'),(.2,'gray50'),
-                             (0,'#000080')):
-            self.rings[intens]=c.create_oval(0,0,0,0,
-                                          outline=color,width=2,tags=self.tags,
-                                          outlinestipple='gray50')
-
-        # make text
-        self.txt=c.create_text(0,0,text=f.name(),font=defaultfont+" bold",
-                               fill='white',anchor='c',
-                               tags=self.tags)
-
-        # highlight text bindings
-        canvashighlighter(c,self.txt,'fill',normalval='white',highlightval='red')
-
-        # position drag bindings
-        def press(ev):
-            self._lastmouse=ev.x,ev.y
-        def motion(ev):
-            dcan=Pair(*[a-b for a,b in zip((ev.x,ev.y),self._lastmouse)])
-            dworld=c.canvas2world_vector(*dcan)
-            self.field.center(*(self.field.center()+dworld))
-            self._lastmouse=ev.x,ev.y
-            self.setcoords() # redraw
-        def release(ev):
-            if hasattr(self,'_lastmouse'):
-                del self._lastmouse
-            dispatcher.send("field coord changed") # updates bounds
-            
-        c.tag_bind(self.txt,"<ButtonPress-1>",press)
-        c.tag_bind(self.txt,"<B1-Motion>",motion)
-        c.tag_bind(self.txt,"<B1-ButtonRelease>",release)
-
-        # radius drag bindings
-        outerring=self.rings[0]
-        canvashighlighter(c,outerring,
-                          'outline',normalval='#000080',highlightval='#4040ff')
-        def motion(ev):
-            worldmouse=self.canvas.canvas2world(ev.x,ev.y)
-            currentdist=pairdist(worldmouse,self.field.center())
-            self.field.falloff(currentdist)
-            self.setcoords()
-        c.tag_bind(outerring,"<B1-Motion>",motion)
-        c.tag_bind(outerring,"<B1-ButtonRelease>",release) # from above
-
-        self.setcoords()
-    
-class Tracker(tk.Frame):
-
-    """whole tracker widget, which is mostly a view for a
-    Fieldset. tracker makes its own fieldset"""
-
-    # world coords of the visible canvas (preserved even in window resizes)
-    xmin=0
-    xmax=100
-    ymin=0
-    ymax=100
-
-    fieldsetfile=None
-    displays=None # Field : FieldDisplay. we keep these in sync with the fieldset
-    
-    def __init__(self,master):
-        tk.Frame.__init__(self,master)
-
-        self.displays={}
-        
-        c=self.canvas=Zooming(self,bg='black',closeenough=5)
-        c.pack(fill='both',exp=1)
-
-        # preserve edge coords over window resize
-        c.bind("<Configure>",self.configcoords)
-        
-        c.bind("<Motion>",
-               lambda ev: self._fieldset().report(*c.canvas2world(ev.x,ev.y)))
-        def save(ev):
-            print "saving"
-            self.fieldsetfile.save()
-        master.bind("<Key-s>",save)
-        dispatcher.connect(self.autobounds,"field coord changed")
-
-    def _fieldset(self):
-        return self.fieldsetfile.fieldset()
-
-    def load(self,filename):
-        self.fieldsetfile=Fieldsetfile(filename)
-        self.displays.clear()
-        for f in self.fieldsetfile.fieldset().getall():
-            self.displays[f]=FieldDisplay(self.canvas,f)
-            self.displays[f].makeobjs()
-        self.autobounds()
-
-    def configcoords(self,*args):
-        # force our canvas coords to stay at the edges of the window
-        c=self.canvas
-        cornerx,cornery=c.canvas2world(0,0)
-        c.move(cornerx-self.xmin,
-               cornery-self.ymin)
-        c.setscale(0,0,
-                   c.winfo_width()/(self.xmax-self.xmin),
-                   c.winfo_height()/(self.ymax-self.ymin))
-
-    def autobounds(self):
-        """figure out our bounds from the fieldset, and adjust the display zooms.
-        writes the corner coords onto the canvas."""
-        self.xmin,self.xmax,self.ymin,self.ymax=self._fieldset().getbounds()
-
-        self.configcoords()
-        
-        c=self.canvas
-        c.delete('cornercoords')
-        for x,anc2 in ((self.xmin,'w'),(self.xmax,'e')):
-            for y,anc1 in ((self.ymin,'n'),(self.ymax,'s')):
-                pos=c.world2canvas(x,y)
-                c.create_text(pos[0],pos[1],text="%s,%s"%(x,y),
-                              fill='white',anchor=anc1+anc2,
-                              tags='cornercoords')
-        [d.setcoords() for d in self.displays.values()]
-
-########################################################################
-########################################################################
-                
-root=tk.Tk()
-root.wm_geometry('700x350')
-tra=Tracker(root)
-tra.pack(fill='both',exp=1)
-
-tra.load("fieldsets/demo")
-
-root.mainloop()
--- a/light9/Effects.py	Tue Mar 21 04:45:56 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-import random
-import light9.Submaster as Submaster
-from chase import chase as chase_logic
-
-thirds = 'third-l', 'third-c', 'third-r'
-thirds_bounce = 'third-l', 'third-c', 'third-r', 'third-c'
-backs = ['back%d' % d for d in range(1, 11)]
-rand_flutter = ['scoop-l', 'scoop-c', 'scoop-r', 'down-c', 'down-l', 'down-r', 'cyc', 'zip_blue', 'zip_red', 'zip_green', 'zip_orange'] + backs
-rand_flutter *= 10
-random.shuffle(rand_flutter)
-
-# don't forget to update this!
-__all__ = ['chase', 'thirds', 'thirds_bounce', 'rand_flutter', 'backs']
-
-def chase(t, ontime=0.5, offset=0.2, onval=1.0, 
-          offval=0.0, names=None, combiner=max):
-    """names is list of sub or channel names"""
-    sub_vals = {}
-    chase_vals = chase_logic(t, ontime, offset, onval, offval, names, combiner)
-    for name, value in chase_vals.items():
-        sub = Submaster.get_sub_by_name(name)
-        sub_vals[sub] = value
-
-    return Submaster.combine_subdict(sub_vals)