Skip to content

Basic preset development

Jon Evans edited this page May 21, 2013 · 5 revisions

Introduction

For this and all of the other development pages, I assume that you have a basic understanding of the Python language, but not much background is necessary to understand preset development.

User-made presets are all subclasses of the Preset class. This class describes a common interface that each preset must implement. The following methods are designed to be overridden in your preset:

def setup():
    """This method is called once when a preset is loaded.  Put any initialization code here."""

def parameter_changed():
    """This method is called when any parameters are changed (by the GUI)."""

def reset():
    """This method is called right before the preset becomes active in the playlist."""

Tickers

Basic presets use a concept called a "ticker" to define the preset behavior. A ticker is a function that is called by the mixer during each frame, and can return the behavior of a single pixel or a group of pixels. Some tickers are defined in basic_tickers.py, but you can feel free to add others in your preset (or submit a pull request to add them to basic_tickers.py if they could be useful to other presets).

To understand how tickers work, let's take a look at a few examples. First, the simplest preset, RGBFade. This preset applies a rainbow color change to all pixels at the same time.

from lib.preset import Preset
from lib.basic_tickers import fade, speed
from lib.color_fade import Rainbow
from lib.parameters import FloatParameter

class RGBFade(Preset):
    """Simple RGB fade"""

    def setup(self):
        self.add_parameter(FloatParameter('speed', 0.2))
        self.add_ticker(speed(fade((), Rainbow), self.parameter('speed')))

Here, we only define a setup() method, because this preset is very simple and does not require special treatment each time it is queued up in the playlist.

The first line (self.add_parameter()) creates a Parameter that will be stored with the preset. More about Parameters later, but for now, note that there is a parameter called speed that holds a float value and can be used in the preset.

The next line adds a single ticker to update the entire scene. The call to self.add_ticker() creates an entry in the preset's list of tickers. As noted in the documentation for Preset.add_ticker(), the first argument to this call is a function that should yield a list of (lights, color) tuples when called:

def add_ticker(self, ticker, priority=0):
    """
    Adds a ticker. Tickers are run every tick and can yield any number of (lights, color) tuples.
 
    lights is one of:
        an empty tuple (to change all strands)
        a (strand) tuple (to change all addresses on the strand)
        a (strand, address) tuple (to change all pixels on the strand)
        a (strand, address, pixel) tuple (to change a single pixel)
        a list of any of the above tuples

    color is an (r, g, b) tuple where r, g, and b are either:
        integers between 0 and 255
        floats between 0 and 1
    """

The first argument to fade() is an empty tuple (), which refers to all pixels in all strands, as noted above.

The second argument to fade() is an instance of the ColorFade class. Rainbow is a pre-defined instance that fades between all the possible hues, but you can define your own (more on that later).

The speed() function modifies the ticker by multiplying the timestep that the mixer passes in by a constant. The second argument can be a floating point number or a Parameter. The call to self.parameter('speed') returns a reference to the Parameter with the name speed.

Behind the scenes, at each frame, the mixer will ask the preset to generate a list of commands. The preset will go through the list of tickers, and call the ticker functions with the number of ticks and the elapsed time as arguments (tickers will use these arguments to create animation by varying output by time). Each ticker will return a list of (lights, color) tuples. In this case, the Rainbow fade ticker will return ((), color) for each tick, and color will change with time according to the speed parameter.

More Examples

These presets are good examples of basic presets to use as references when making your own:

SeparateStrandRGB demonstrates the offset ticker and parameter_changed() method

RadialRainbow demonstrates the use of the Scene object to get information about pixel positions

FixtureStepFade demonstrates the callback() ticker used to change the behavior of a preset at a certain interval

Outgrowing Basic Presets

Using the ticker model to develop presets that apply different rules to each pixel can quickly get tedious (and performance can suffer). The Raw Preset model was designed to solve this problem. Developing raw presets requires more legwork than basic presets, but is still approachable for someone who is new to Python.

Head over to the Raw Preset Development page to read more about this type of preset.