changeset 1469:70959bb51ab3

full page, 4-row TL. start doing static fx settings on notes Ignore-this: b581abc51d10e0c2dc62943e4fb3bebb
author Drew Perttula <drewp@bigasterisk.com>
date Sun, 12 Jun 2016 12:37:24 +0000
parents b291b7be7332
children b1d8abc96f06
files light9/effect/effecteval.py light9/effect/sequencer.py light9/web/timeline/index.html light9/web/timeline/timeline.coffee
diffstat 4 files changed, 84 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/light9/effect/effecteval.py	Sun Jun 12 11:35:25 2016 +0000
+++ b/light9/effect/effecteval.py	Sun Jun 12 12:37:24 2016 +0000
@@ -46,9 +46,6 @@
         # effect : [(dev, attr, value, isScaled)]
         self.effectOutputs = {}
         
-        #for ds in g.objects(g.value(uri, L9['effectClass']), L9['deviceSetting']):
-        #    self.setting = (g.value(ds, L9['device']), g.value(ds, L9['attr']))
-
         self.graph.addHandler(self.updateEffectsFromGraph)
 
     def updateEffectsFromGraph(self):
@@ -67,6 +64,7 @@
 
             if settings:
                 self.effectOutputs[effect] = settings
+            # also have to read eff :effectAttr [ :tint x; :tintStrength y ]
         
     def outputFromEffect(self, effectSettings, songTime):
         """
@@ -74,66 +72,82 @@
         settings like light1/bright=0.72;light2/bright=0.78. This runs
         the effect code.
         """
-        attr, strength = effectSettings[0]
-        strength = float(strength)
-        assert attr == L9['strength']
+        # both callers need to apply note overrides
+        effectSettings = dict(effectSettings) # we should make everything into nice float and Color objects too
+
+        strength = float(effectSettings[L9['strength']])
+        if strength <= 0:
+            return []
+
+        out = {} # (dev, attr): value
+
+        out.update(self.simpleOutput(strength))
 
-        out = []
+        if self.effect.startswith(L9['effect/']):
+            tail = 'effect_' + self.effect[len(L9['effect/']):]
+            try:
+                func = globals()[tail]
+            except KeyError:
+                pass
+            else:
+                out.update(func(effectSettings, strength, songTime))
+
+        # todo: callers should prefer the dict form too
+        outList = [(d, a, v) for (d, a), v in out.iteritems()]
+        outList.sort()
+        #import pprint; pprint.pprint(outList, width=170)
+        return outList
+                            
+    def simpleOutput(self, strength):
+        out = {}
         for dev, attr, value, isScaled in self.effectOutputs.get(self.effect, []):
             if isScaled:
                 value = scale(value, strength)
-            out.append((dev, attr, value))
-            
-        if self.effect == L9['effect/RedStripzzz']: # throwaway
-            mov = URIRef('http://light9.bigasterisk.com/device/moving1')
-            col = [
-                    ((songTime + .0) % 1.0),
-                    ((songTime + .4) % 1.0),
-                    ((songTime + .8) % 1.0),
-                ]
-            out.extend([
-                # device, attr, lev
-                
-                (mov, L9['color'], Literal(rgb_to_hex([strength*x*255 for x in col]))),
-                (mov, L9['rx'], Literal(100 + 70 * math.sin(songTime*2))),
-            ] * (strength>0))
-        elif self.effect == L9['effect/Curtain']:
-            out.extend([
-                (L9['device/lowPattern%s' % n], L9['color'],
-                 literalColor(0*strength, strength, strength))
-                for n in range(301,308+1)
-                ])
-        elif self.effect == L9['effect/animRainbow']:
-            for n in range(1, 5+1):
-                scl = strength * nsin(songTime + n * .3)**3
-                col = literalColor(
-                        scl * nsin(songTime + n * .2),
-                        scl * nsin(songTime + n * .2 + .3),
-                        scl * nsin(songTime + n * .3 + .6))
-                col = literalColor(scl * .6, scl * 0, scl * 1)
-                dev = L9['device/aura%s' % n]
-                out.append((dev, L9['color'], col))
-                out.append((dev, L9['zoom'], .9))
-                ang = songTime * 4
-                out.append((dev, L9['rx'], lerp(.27, .7, (n-1)/4) + .2 * math.sin(ang+n)))
-                out.append((dev, L9['ry'], lerp(.46, .52, (n-1)/4) + .5 * math.cos(ang+n)))
-                    
-        elif self.effect == L9['effect/Strobe']:
-            attr, value = effectSettings[0]
-            assert attr == L9['strength']
-            strength = float(value)
-            rate = 2
-            duty = .3
-            offset = 0
-            f = (((songTime + offset) * rate) % 1.0)
-            c = (f < duty) * strength
-            col = rgb_to_hex([c * 255, c * 255, c * 255])
-            out.extend([
-                (L9['device/colorStrip'], L9['color'], Literal(col)),
-            ])
-
+            out[(dev, attr)] = value
         return out
         
 
 
     
+
+def effect_Curtain(effectSettings, strength, songTime):
+    return {
+        (L9['device/lowPattern%s' % n], L9['color']):
+        literalColor(0*strength, strength, strength)
+        for n in range(301,308+1)
+        }
+    
+def effect_animRainbow(effectSettings, strength, songTime):
+    out = {}
+    tint = effectSettings.get(L9['tint'], '#ffffff')
+    tintStrength = float(effectSettings.get(L9['tintStrength'], 0))
+    print tint, tintStrength
+    tr, tg, tb = hex_to_rgb(tint)
+    for n in range(1, 5+1):
+        scl = strength * nsin(songTime + n * .3)**3
+        col = literalColor(
+            scl * lerp(nsin(songTime + n * .2), tr/255, tintStrength),
+            scl * lerp(nsin(songTime + n * .2 + .3), tg/255, tintStrength),
+            scl * lerp(nsin(songTime + n * .3 + .6), tb/255, tintStrength))
+
+        dev = L9['device/aura%s' % n]
+        out.update({
+            (dev, L9['color']): col,
+            (dev, L9['zoom']): .9,
+            })
+        ang = songTime * 4
+        out.update({
+        (dev, L9['rx']): lerp(.27, .7, (n-1)/4) + .2 * math.sin(ang+n),
+        (dev, L9['ry']): lerp(.46, .52, (n-1)/4) + .5 * math.cos(ang+n),
+            })
+    return out
+
+def effect_Strobe(effectSettings, strength, songTime):
+    rate = 2
+    duty = .3
+    offset = 0
+    f = (((songTime + offset) * rate) % 1.0)
+    c = (f < duty) * strength
+    col = rgb_to_hex([c * 255, c * 255, c * 255])
+    return {(L9['device/colorStrip'], L9['color']): Literal(col)}
+
--- a/light9/effect/sequencer.py	Sun Jun 12 11:35:25 2016 +0000
+++ b/light9/effect/sequencer.py	Sun Jun 12 12:37:24 2016 +0000
@@ -140,9 +140,6 @@
         settings = []
         
         for note in self.notes.get(song, []):
-            # we have to send zeros to make past settings go
-            # away. might be better for collector not to merge our
-            # past requests, and then we can omit zeroed notes?
             outs = note.outputSettings(t)
             #print 'out', outs
             settings.extend(outs)
--- a/light9/web/timeline/index.html	Sun Jun 12 11:35:25 2016 +0000
+++ b/light9/web/timeline/index.html	Sun Jun 12 12:37:24 2016 +0000
@@ -4,10 +4,10 @@
     <title>timeline</title>
     <meta charset="utf-8" />
     <script src="/lib/webcomponentsjs/webcomponents-lite.min.js"></script>
-    <link rel="import" href="timeline-elements.html"
+    <link rel="import" href="timeline-elements.html">
   </head>
   <body>
-    <light9-timeline-editor style="width: 100%; height: 400px">
+    <light9-timeline-editor style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px;">
     </light9-timeline-editor>
   </body>
 </html>
--- a/light9/web/timeline/timeline.coffee	Sun Jun 12 11:35:25 2016 +0000
+++ b/light9/web/timeline/timeline.coffee	Sun Jun 12 12:37:24 2016 +0000
@@ -1,6 +1,7 @@
 log = console.log
 RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
 
+ROW_COUNT = 4
 
 # polymer dom-repeat is happy to shuffle children by swapping their
 # attribute values, and it's hard to correctly setup/teardown your
@@ -250,7 +251,7 @@
     dia: { type: Object, notify: true }
     song: { type: String, notify: true }
     zoomInX: { type: Object, notify: true }
-    rows: { value: [0] }
+    rows: { value: [0...ROW_COUNT] }
     zoom: { type: Object, notify: true, observer: 'onZoom' }
     zoomFlattened: { type: Object, notify: true }
   onZoom: ->
@@ -326,7 +327,7 @@
     rowIndex: { type: Object, notify: true }
   observers: [
     'onGraph(graph, dia, setAdjuster, song, zoomInX)'
-    'update(song)'
+    'update(song, rowIndex)'
     'onZoom(zoomInX)'
     ]
   onGraph: ->
@@ -335,7 +336,13 @@
     U = (x) -> @graph.Uri(x)
     log("row #{@rowIndex} updating")
 
-    notesForThisRow = @graph.objects(@song, U(':note'))
+    notesForThisRow = []
+    i = 0
+    for n in _.sortBy(@graph.objects(@song, U(':note')))
+      if (i % ROW_COUNT) == @rowIndex
+        notesForThisRow.push(n)
+      i++
+    log("row #{@rowIndex} gets", notesForThisRow)
 
     updateChildren @, notesForThisRow, (newUri) =>
       child = document.createElement('light9-timeline-note')
@@ -420,7 +427,7 @@
     screenPts = ($V([@zoomInX(pt.e(1)), @offsetTop + (1 - pt.e(2)) * @offsetHeight]) for pt in worldPts)
     @dia.setNote(@uri, screenPts, label)
 
-    leftX = screenPts[1].e(1) + 5
+    leftX = Math.max(2, screenPts[1].e(1) + 5)
     rightX = screenPts[2].e(1) - 5
     w = 120
     h = 45