Changeset - a63635f98110
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 16 years ago 2009-06-15 00:41:29
drewp@bigasterisk.com
curve: add mute support, colo(u)rs change
1 file changed with 82 insertions and 17 deletions:
0 comments (0 inline, 0 general)
light9/curve.py
Show inline comments
 
@@ -4,47 +4,61 @@ from bisect import bisect_left,bisect,bi
 
import Tkinter as tk
 
try:
 
    from dispatch import dispatcher
 
except ImportError:
 
    import louie as dispatcher
 

	
 
import run_local
 
from light9 import cursors
 
from light9.dmxchanedit import gradient
 
from light9.zoomcontrol import RegionZoom
 
from bcf2000 import BCF2000
 

	
 
class Curve:
 
class Curve(object):
 
    """curve does not know its name. see Curveset"""
 
    points = None # x-sorted list of (x,y)
 
    def __init__(self):
 
        self.points = []
 
        self._muted = False
 

	
 
    def muted():
 
        doc = "Whether to currently send levels (boolean, obviously)"
 
        def fget(self):
 
            return self._muted
 
        def fset(self, val):
 
            self._muted = val
 
            dispatcher.send('mute changed', sender=self)
 
        return locals()
 
    muted = property(**muted())
 

	
 
    def load(self,filename):
 
        self.points[:]=[]
 
        for line in file(filename):
 
            self.points.append(tuple([float(a) for a in line.split()]))
 
        self.points.sort()
 
        dispatcher.send("points changed",sender=self)
 

	
 
    def save(self,filename):
 
        if filename.endswith('-music') or filename.endswith('_music'):
 
            print "not saving music track"
 
            return
 
        f = file(filename,'w')
 
        for p in self.points:
 
            f.write("%s %s\n" % p)
 
        f.close()
 

	
 
    def eval(self,t):
 
    def eval(self, t, allow_muting=True):
 
        if self.muted and allow_muting:
 
            return 0
 

	
 
        i = bisect_left(self.points,(t,None))-1
 

	
 
        if self.points[i][0]>t:
 
            return self.points[i][1]
 
        if i>=len(self.points)-1:
 
            return self.points[i][1]
 

	
 
        p1,p2 = self.points[i],self.points[i+1]
 
        frac = (t-p1[0])/(p2[0]-p1[0])
 
        y = p1[1]+(p2[1]-p1[1])*frac
 
        return y
 
    __call__=eval
 
@@ -149,24 +163,26 @@ class Curveview(tk.Canvas):
 
        self._time = 0
 
        self.last_mouse_world = None
 
        tk.Canvas.__init__(self,master,width=10,height=10,
 
                           relief='sunken',bd=1,
 
                           closeenough=5,takefocus=1, **kw)
 
        self.selected_points=[] # idx of points being dragged
 
        self.update_curve()
 
        # self.bind("<Enter>",self.focus)
 
        dispatcher.connect(self.input_time,"input time")
 
        dispatcher.connect(self.update_curve,"zoom changed")
 
        dispatcher.connect(self.update_curve,"points changed",
 
                           sender=self.curve)
 
        dispatcher.connect(self.update_curve, "mute changed", 
 
                           sender=self.curve)
 
        dispatcher.connect(self.select_between, "select between")
 
        if self.knobEnabled:
 
            dispatcher.connect(self.knob_in, "knob in")
 
            dispatcher.connect(self.slider_in, "set key")
 
        self.bind("<Configure>",self.update_curve)
 
        for x in range(1, 6):
 
            def add_kb_marker_point(evt, x=x):
 
                self.add_point((self.current_time(), (x - 1) / 4.0))
 

	
 
            self.bind("<Key-%s>" % x, add_kb_marker_point)
 

	
 

	
 
@@ -331,83 +347,97 @@ class Curveview(tk.Canvas):
 
        self.zoom = dispatcher.send("zoom area")[0][1]
 
        cp = self.curve.points
 

	
 
        visible_x = (self.world_from_screen(0,0)[0],
 
                     self.world_from_screen(self.winfo_width(),0)[0])
 

	
 
        visible_idxs = self.curve.indices_between(visible_x[0], visible_x[1],
 
                                                  beyond=1)
 
        visible_points = [cp[i] for i in visible_idxs]
 
        
 
        self.delete('curve')
 

	
 
        if self.curve.muted:
 
            self['bg'] = 'grey20'
 
        else:
 
            self['bg'] = 'black'
 

	
 
        if self.winfo_height() < 40:
 
            self._draw_gradient()
 
        else:
 
            self._draw_markers(visible_x)
 
            self._draw_line(visible_points)
 

	
 
            self.dots = {} # idx : canvas rectangle
 

	
 
            if len(visible_points)<50:
 
                self._draw_handle_points(visible_idxs,visible_points)
 

	
 
    def _draw_gradient(self):
 
        gradient_res = 3
 
        for x in range(0,self.winfo_width(),gradient_res):
 
            wx = self.world_from_screen(x,0)[0]
 
            mag = self.curve.eval(wx)
 
            mag = self.curve.eval(wx, allow_muting=False)
 
            if self.curve.muted:
 
                low = (8, 8, 8)
 
                high = (60, 60, 60)
 
            else:
 
                low = (20, 10, 50)
 
                high = (255, 187, 255)
 
            self.create_line(x,0, x,40,
 
                             fill=gradient(mag,
 
                                           low=(20,10,50),
 
                                           high=(255,187,255)),
 
                             fill=gradient(mag, low=low, high=high),
 
                             width=gradient_res, tags='curve')
 

	
 
    def _draw_markers(self,visible_x):
 
        mark = self._draw_one_marker
 

	
 
        mark(0,"0")
 
        t1,t2=visible_x
 
        if t2-t1<30:
 
            for t in range(int(t1),int(t2)+1):
 
                mark(t,str(t))
 
        mark(-4,"-4")
 

	
 
        endtimes = dispatcher.send("get max time")
 
        if endtimes:
 
            endtime = endtimes[0][1]
 
            mark(endtime,"end %.1f"%endtime)
 
            mark(endtime+10,"post %.1f"%(endtime+10))
 
        
 
    def _draw_one_marker(self,t,label):
 
        x = self.screen_from_world((t,0))[0]
 
        ht = self.winfo_height()
 
        self.create_line(x,ht,x,ht-20,
 
        self.create_line(x,ht,x,ht-20, fill='white',
 
                         tags=('curve',))
 
        self.create_text(x,ht-20,text=label,anchor='s',
 
        self.create_text(x,ht-20,text=label,anchor='s', fill='white',
 
                         tags=('curve',))
 

	
 

	
 
    def _draw_line(self,visible_points):
 
        linepts=[]
 
        step=1
 
        linewidth=2
 
        if len(visible_points)>800:
 
            step = int(len(visible_points)/800)
 
            linewidth=1
 
        for p in visible_points[::step]:
 
            linepts.extend(self.screen_from_world(p))
 
        if len(linepts)<4:
 
            return
 
        line = self.create_line(*linepts,**dict(width=linewidth,tags='curve'))
 
        if self.curve.muted:
 
            fill = 'grey34'
 
        else:
 
            fill = 'white'
 
        kwargs = dict(width=linewidth, tags='curve', fill=fill)
 
        line = self.create_line(*linepts, **kwargs)
 

	
 
        # canvas doesnt have keyboard focus, so i can't easily change the
 
        # cursor when ctrl is pressed
 
        #        def curs(ev):
 
        #            print ev.state
 
        #        self.bind("<KeyPress>",curs)
 
        #        self.bind("<KeyRelease-Control_L>",lambda ev: curs(0))
 
        self.tag_bind(line,"<Control-ButtonPress-1>",self.new_point_at_mouse)
 

	
 

	
 
    def _draw_handle_points(self,visible_idxs,visible_points):
 
        for i,p in zip(visible_idxs,visible_points):
 
@@ -709,50 +739,85 @@ class Curvesetview(tk.Frame):
 
        
 
        entry = tk.Entry(f, textvariable=self.newcurvename)
 
        entry.pack(side='left', fill='x',exp=1)        
 
        entry.bind("<Key-Return>", new_curve)
 

	
 
        def focus_entry():
 
            entry.focus()
 
        
 
        dispatcher.connect(self.add_curve, "add_curve", sender=self.curveset)
 
        dispatcher.connect(focus_entry, "focus new curve", weak=False)
 
        
 
    def add_curve(self,name, slider=None, knobEnabled=False):
 
        labelFont = "arial 8"
 

	
 
        f = tk.Frame(self,relief='raised',bd=1)
 
        f.pack(side='top',fill='both',exp=1)
 

	
 
        leftside = tk.Frame(f)
 
        leftside.pack(side='left')
 

	
 
        collapsed = tk.IntVar()
 
        txt = "curve '%s'" % name
 
        if len(name) > 7:
 
            txt = name
 
        labelFont = "arial 8"
 
        tk.Label(leftside,text=txt,font=labelFont,
 
                 width=15).pack(side='top')
 
        curve_name_label = tk.Label(leftside,text=txt,font=labelFont,
 
                 width=15)
 
        curve_name_label.pack(side='left')
 

	
 
        sliderLabel = None
 
        def cmd():
 
        def collapsed_cmd():
 
            if collapsed.get():
 
                if sliderLabel:
 
                    sliderLabel.pack_forget()
 
                f.pack(exp=0)
 
            else:
 
                if sliderLabel:
 
                    sliderLabel.pack(side='top')
 
                    sliderLabel.pack(side='left')
 
                f.pack(exp=1)
 
        tk.Checkbutton(leftside, text="collapsed", font=labelFont,
 
                       variable=collapsed, command=cmd).pack(side='top')
 
        collapsed_cb = tk.Checkbutton(leftside, text="C",
 
                       font=labelFont, variable=collapsed, 
 
                       command=collapsed_cmd)
 
        collapsed_cb.pack(side='left')
 

	
 
        muted = tk.IntVar()
 
        default_bg = leftside['bg']
 
        muted_cb = tk.Checkbutton(leftside, text="M", font=labelFont,
 
                       variable=muted)
 
        muted_cb.pack(side='left')
 

	
 
        if slider is not None:
 
            # slider should have a checkbutton, defaults to off for
 
            # music tracks
 
            sliderLabel = tk.Label(leftside, text="Slider %s" % slider,
 
                                   fg='#800000', font=labelFont)
 
            sliderLabel.pack(side='top')
 
            sliderLabel.pack(side='left')
 

	
 
        cv = Curveview(f, self.curveset.curves[name],
 
                       knobEnabled=knobEnabled)
 
        cv.pack(side='left',fill='both',exp=1)
 
        self.curves[name] = cv
 

	
 
        def muted_cmd(*args):
 
            new_mute = muted.get()
 
            old_mute = cv.curve.muted
 
            if new_mute == old_mute:
 
                return
 

	
 
            cv.curve.muted = new_mute
 

	
 
            if muted.get():
 
                new_bg = 'grey20'
 
            else:
 
                new_bg = default_bg
 

	
 
            widgets = [leftside, collapsed_cb, muted_cb, curve_name_label, f]
 
            if sliderLabel:
 
                widgets.append(sliderLabel)
 
            for widget in widgets:
 
                widget['bg'] = new_bg
 
        muted.trace('w', muted_cmd)
 

	
 
        def mute_changed():
 
            muted.set(cv.curve.muted)
 

	
 
        dispatcher.connect(mute_changed, 'mute changed', sender=cv.curve)
0 comments (0 inline, 0 general)