Mercurial > code > home > repos > light9
annotate Widgets/FlyingFader.py @ 134:f2f73a2171e6
many adjustments to the loops and timing
many adjustments to the loops and timing
now sends the hardware updates only when clients change, but at least 1Hz
new option to adjust the rate of the loop that considers sending changes (if
the lights have changed)
author | drewp |
---|---|
date | Sat, 14 Jun 2003 14:59:09 +0000 |
parents | 0c619695d6c6 |
children |
rev | line source |
---|---|
52 | 1 from Tix import * |
24 | 2 from time import time,sleep |
3 from __future__ import division | |
4 | |
5 class Mass: | |
6 def __init__(self): | |
7 self.x=0 # position | |
8 self.xgoal=0 # position goal | |
9 | |
10 self.v=0 # velocity | |
11 self.maxspeed = .8 # maximum speed, in position/second | |
12 self.maxaccel = 3 # maximum acceleration, in position/second^2 | |
25
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
13 self.eps = .03 # epsilon - numbers within this much are considered the same |
24 | 14 |
15 self._lastupdate=time() | |
16 self._stopped=1 | |
17 | |
18 def equal(self,a,b): | |
19 return abs(a-b)<self.eps | |
20 | |
21 def stop(self): | |
22 self.v=0 | |
23 self.xgoal=self.x | |
24 self._stopped=1 | |
25 | |
26 def update(self): | |
27 t0 = self._lastupdate | |
28 tnow = time() | |
29 self._lastupdate = tnow | |
30 | |
31 dt = tnow-t0 | |
32 | |
33 self.x += self.v*dt | |
34 # hitting the ends stops the slider | |
35 if self.x>1: self.v=max(self.v,0); self.x=1 | |
36 if self.x<0: self.v=min(self.v,0); self.x=0 | |
37 | |
38 if self.equal(self.x,self.xgoal): | |
39 self.x=self.xgoal # clean up value | |
40 self.stop() | |
41 return | |
42 | |
43 self._stopped=0 | |
44 dir = (-1.0,1,0)[self.xgoal>self.x] | |
45 | |
25
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
46 if abs(self.xgoal-self.x) < abs(self.v*5*dt): |
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
47 # apply the brakes on the last 5 steps |
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
48 dir *= -.5 |
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
49 |
24 | 50 self.v += dir*self.maxaccel*dt # velocity changes with acceleration in the right direction |
51 self.v = min(max(self.v,-self.maxspeed),self.maxspeed) # clamp velocity | |
52 | |
25
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
53 #print "x=%+.03f v=%+.03f a=%+.03f %f" % (self.x,self.v,self.maxaccel,self.xgoal) |
24 | 54 |
55 def goto(self,newx): | |
56 self.xgoal=newx | |
57 | |
58 def ismoving(self): | |
59 return not self._stopped | |
0 | 60 |
61 class FlyingFader(Frame): | |
31 | 62 def __init__(self, master, variable, label, fadedur=1.5, font=('Arial', 8), labelwidth=12, |
15
c76b62eccdec
put **kw back in, they now go to the scale and can override the defaults.
dmcc
parents:
11
diff
changeset
|
63 **kw): |
0 | 64 Frame.__init__(self, master) |
65 self.name = label | |
66 self.variable = variable | |
67 | |
24 | 68 self.mass = Mass() |
69 | |
0 | 70 self.config({'bd':1, 'relief':'raised'}) |
22 | 71 scaleopts = {'variable' : variable, 'showvalue' : 0, 'from' : 1.0, |
31 | 72 'to' : 0, 'res' : 0.001, 'width' : 20, 'length' : 200, 'orient':'vert'} |
15
c76b62eccdec
put **kw back in, they now go to the scale and can override the defaults.
dmcc
parents:
11
diff
changeset
|
73 scaleopts.update(kw) |
31 | 74 if scaleopts['orient']=='vert': |
75 side1=TOP | |
76 side2=BOTTOM | |
77 else: | |
78 side1=RIGHT | |
79 side2=LEFT | |
15
c76b62eccdec
put **kw back in, they now go to the scale and can override the defaults.
dmcc
parents:
11
diff
changeset
|
80 |
111 | 81 self.scale = Scale(self, **scaleopts) |
22 | 82 self.vlabel = Label(self, text="0.0", width=6, font=font) |
31 | 83 self.label = Label(self, text=label, font=font, anchor='w',width=labelwidth) #wraplength=40, ) |
0 | 84 |
85 self.oldtrough = self.scale['troughcolor'] | |
86 | |
31 | 87 self.scale.pack(side=side2, expand=1, fill=BOTH, anchor='c') |
88 self.vlabel.pack(side=side2, expand=0, fill=X) | |
89 self.label.pack(side=side2, expand=0, fill=X) | |
0 | 90 |
91 for k in range(1, 10): | |
92 self.scale.bind("<Key-%d>" % k, | |
20 | 93 lambda evt, k=k: self.newfade(k / 10.0, evt)) |
0 | 94 |
24 | 95 self.scale.bind("<Key-0>", lambda evt: self.newfade(1.0, evt)) |
0 | 96 self.scale.bind("<grave>", lambda evt: self.newfade(0, evt)) |
97 | |
98 self.scale.bind("<1>", self.cancelfade) | |
11
c65119b66b00
- no more kw args -- they didn't do anything. use configure to change
dmcc
parents:
9
diff
changeset
|
99 self.scale.bind("<2>", self.cancelfade) |
0 | 100 self.scale.bind("<3>", self.mousefade) |
101 | |
50 | 102 self.trace_ret = self.variable.trace('w', self.updatelabel) |
103 self.bind("<Destroy>",self.ondestroy) | |
104 | |
105 def ondestroy(self,*ev): | |
106 self.variable.trace_vdelete('w',self.trace_ret) | |
0 | 107 |
108 def cancelfade(self, evt): | |
24 | 109 self.fadegoal = self.variable.get() |
110 self.fadevel = self.fadeacc = 0 | |
111 | |
0 | 112 self.scale['troughcolor'] = self.oldtrough |
113 | |
114 def mousefade(self, evt): | |
115 target = float(self.tk.call(self.scale, 'get', evt.x, evt.y)) | |
116 self.newfade(target, evt) | |
117 | |
24 | 118 def ismoving(self): |
119 return self.fadevel!=0 or self.fadeacc!=0 | |
22 | 120 |
9
342f7d1c7561
The FlyingFader will accept keyboard values and fade to them over 1.5
dmcc
parents:
0
diff
changeset
|
121 def newfade(self, newlevel, evt=None, length=None): |
24 | 122 |
25
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
123 # these are currently unused-- Mass needs to accept a speed input |
9
342f7d1c7561
The FlyingFader will accept keyboard values and fade to them over 1.5
dmcc
parents:
0
diff
changeset
|
124 mult = 1 |
0 | 125 if evt.state & 8 and evt.state & 4: mult = 0.25 # both |
126 elif evt.state & 8: mult = 0.5 # alt | |
127 elif evt.state & 4: mult = 2 # control | |
128 | |
25
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
129 |
24 | 130 self.mass.x = self.variable.get() |
131 self.mass.goto(newlevel) | |
0 | 132 |
133 self.gofade() | |
134 | |
135 def gofade(self): | |
24 | 136 self.mass.update() |
137 self.variable.set(self.mass.x) | |
138 | |
139 if not self.mass.ismoving(): | |
0 | 140 self.scale['troughcolor'] = self.oldtrough |
141 return | |
25
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
142 |
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
143 # blink the trough while the thing's moving |
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
144 if time()%.4>.2: |
27 | 145 # self.scale.config(troughcolor=self.oldtrough) |
146 self.scale.config(troughcolor='orange') | |
25
f0e1dde35aec
better brakes and numerics (oscillations are still possible if the updates get
drewp
parents:
24
diff
changeset
|
147 else: |
27 | 148 # self.scale.config(troughcolor='white') |
149 self.scale.config(troughcolor='yellow') | |
24 | 150 |
151 # colorfade(self.scale, percent) | |
22 | 152 self.after(30, self.gofade) |
0 | 153 |
154 def updatelabel(self, *args): | |
52 | 155 if self.variable: |
156 self.vlabel['text'] = "%.3f" % self.variable.get() | |
24 | 157 # if self.fadetimes[1] == 0: # no fade |
158 # self.vlabel['fg'] = 'black' | |
159 # elif self.curfade[1] > self.curfade[0]: | |
160 # self.vlabel['fg'] = 'red' | |
161 # else: | |
162 # self.vlabel['fg'] = 'blue' | |
0 | 163 |
11
c65119b66b00
- no more kw args -- they didn't do anything. use configure to change
dmcc
parents:
9
diff
changeset
|
164 def get(self): |
c65119b66b00
- no more kw args -- they didn't do anything. use configure to change
dmcc
parents:
9
diff
changeset
|
165 return self.scale.get() |
0 | 166 |
11
c65119b66b00
- no more kw args -- they didn't do anything. use configure to change
dmcc
parents:
9
diff
changeset
|
167 def set(self, val): |
c65119b66b00
- no more kw args -- they didn't do anything. use configure to change
dmcc
parents:
9
diff
changeset
|
168 self.scale.set(val) |
c65119b66b00
- no more kw args -- they didn't do anything. use configure to change
dmcc
parents:
9
diff
changeset
|
169 |
c65119b66b00
- no more kw args -- they didn't do anything. use configure to change
dmcc
parents:
9
diff
changeset
|
170 def colorfade(scale, lev): |
0 | 171 low = (255, 255, 255) |
172 high = (0, 0, 0) | |
11
c65119b66b00
- no more kw args -- they didn't do anything. use configure to change
dmcc
parents:
9
diff
changeset
|
173 out = [int(l+lev*(h-l)) for h, l in zip(high,low)] |
0 | 174 col="#%02X%02X%02X" % tuple(out) |
175 scale.config(troughcolor=col) | |
176 | |
177 if __name__ == '__main__': | |
178 root = Tk() | |
179 root.tk_focusFollowsMouse() | |
180 | |
181 FlyingFader(root, variable=DoubleVar(), label="suck").pack(side=LEFT, | |
182 expand=1, fill=BOTH) | |
183 FlyingFader(root, variable=DoubleVar(), label="moof").pack(side=LEFT, | |
184 expand=1, fill=BOTH) | |
185 FlyingFader(root, variable=DoubleVar(), label="zarf").pack(side=LEFT, | |
186 expand=1, fill=BOTH) | |
187 FlyingFader(root, variable=DoubleVar(), | |
188 label="long name goes here. got it?").pack(side=LEFT, expand=1, | |
189 fill=BOTH) | |
190 | |
191 root.mainloop() |