Files @ 3f1b9b9b0505
Branch filter:

Location: light9/light9/Effects.py

drewp@bigasterisk.com
add yapf tool
Ignore-this: 28fe07e21ca358a97282f5316c8820e0
from __future__ import division
import random as random_mod
import math
import logging, colorsys
import light9.Submaster as Submaster
from chase import chase as chase_logic
import showconfig
from rdflib import RDF
from light9 import Patch
from light9.namespaces import L9
log = logging.getLogger()

registered = []
def register(f):
    registered.append(f)
    return f

@register
class Strip(object):
    """list of r,g,b tuples for sending to an LED strip"""
    which = 'L' # LR means both. W is the wide one
    pixels = []

    def __repr__(self):
        return '<Strip which=%r px0=%r>' % (self.which, self.pixels[0])
    
    @classmethod
    def solid(cls, which='L', color=(1,1,1), hsv=None):
        """hsv overrides color"""
        if hsv is not None:
            color = colorsys.hsv_to_rgb(hsv[0] % 1.0, hsv[1], hsv[2])
        x = cls()
        x.which = which
        x.pixels = [tuple(color)] * 50
        return x

    def __mul__(self, f):
        if not isinstance(f, (int, float)):
            raise TypeError
            
        s = Strip()
        s.which = self.which
        s.pixels = [(r*f, g*f, b*f) for r,g,b in self.pixels]
        return s

    __rmul__ = __mul__

@register
class Blacklight(float):
    """a level for the blacklight PWM output"""
    def __mul__(self, f):
        return Blacklight(float(self) * f)
    __rmul__ = __mul__
    
@register
def chase(t, ontime=0.5, offset=0.2, onval=1.0, 
          offval=0.0, names=None, combiner=max, random=False):
    """names is list of URIs. returns a submaster that chases through
    the inputs"""
    if random:
        r = random_mod.Random(random)
        names = names[:]
        r.shuffle(names)

    chase_vals = chase_logic(t, ontime, offset, onval, offval, names, combiner)
    lev = {}
    for uri, value in chase_vals.items():
        try:
            dmx = Patch.dmx_from_uri(uri)
        except KeyError:
            log.info(("chase includes %r, which doesn't resolve to a dmx chan" %
                   uri))
            continue
        lev[dmx] = value

    return Submaster.Submaster(name="chase" ,levels=lev)

@register
def hsv(h, s, v, light='all', centerScale=.5):
    r,g,b = colorsys.hsv_to_rgb(h % 1.0, s, v)
    lev = {}
    if light in ['left', 'all']:
        lev[73], lev[74], lev[75] = r,g,b
    if light in ['right', 'all']:
        lev[80], lev[81], lev[82] = r,g,b
    if light in ['center', 'all']:
        lev[88], lev[89], lev[90] = r*centerScale,g*centerScale,b*centerScale
    return Submaster.Submaster(name='hsv', levels=lev)
    
@register
def stack(t, names=None, fade=0):
    """names is list of URIs. returns a submaster that stacks the the inputs

    fade=0 makes steps, fade=1 means each one gets its full fraction
    of the time to fade in. Fades never...
    """
    frac = 1.0 / len(names)

    lev = {}
    for i, uri in enumerate(names):
        if t >= (i + 1) * frac:
            try:
                dmx = Patch.dmx_from_uri(uri)
            except KeyError:
                log.info(("stack includes %r, which doesn't resolve to a dmx chan"%
                       uri))
                continue
            lev[dmx] = 1
        else:
            break
    
    return Submaster.Submaster(name="stack", levels=lev)

@register
def smoove(x):
    return -2 * (x ** 3) + 3 * (x ** 2)
    
def configExprGlobals():
    graph = showconfig.getGraph()
    ret = {}

    for chaseUri in graph.subjects(RDF.type, L9['Chase']):
        shortName = chaseUri.rsplit('/')[-1]
        chans = graph.value(chaseUri, L9['channels'])
        ret[shortName] = list(graph.items(chans))
        print "%r is a chase" % shortName

    for f in registered:
        ret[f.__name__] = f

    ret['nsin'] = lambda x: (math.sin(x * (2 * math.pi)) + 1) / 2
    ret['ncos'] = lambda x: (math.cos(x * (2 * math.pi)) + 1) / 2
    def nsquare(t, on=.5):
        return (t % 1.0) < on
    ret['nsquare'] = nsquare

    _smooth_random_items = [random_mod.random() for x in range(100)]

    # suffix '2' to keep backcompat with the versions that magically knew time
    def smooth_random2(t, speed=1):
        """1 = new stuff each second, <1 is slower, fade-ier"""
        x = (t * speed) % len(_smooth_random_items)
        x1 = int(x)
        x2 = (int(x) + 1) % len(_smooth_random_items)
        y1 = _smooth_random_items[x1]
        y2 = _smooth_random_items[x2]
        return y1 + (y2 - y1) * ((x - x1))

    def notch_random2(t, speed=1):
        """1 = new stuff each second, <1 is slower, notch-ier"""
        x = (t * speed) % len(_smooth_random_items)
        x1 = int(x)
        y1 = _smooth_random_items[x1]
        return y1

    ret['noise2'] = smooth_random2
    ret['notch2'] = notch_random2



    
    return ret