Skip to content

Learning LX: Patterns

Mark Slee edited this page Dec 9, 2020 · 2 revisions

Overview

The main unit for generation of animations in LX is the LXPattern class. An LXPattern owns a rendering buffer that holds a color value for every individual LED in the installation. It also implements a real-time run loop which generates and updates these colors in real time.

Scaffolding

The basic scaffolding of a pattern class looks as follows:

public class ExamplePattern extends LXPattern {

  /**
   * A basic constructor should be provided which passes lx to the super-constructor
   */
  public ExamplePattern(LX lx) {
    super(lx);
  }

  public void run(double deltaMs) {
    // This method is called in real-time when the pattern is active, with
    // deltaMs indicating how many milliseconds have passed since the previous frame
  }
}

Rendering

The core render loop should visit every point in the model and generate a color based upon the geometric coordinates of the point, or whatever other factors may be taken into account. Here the LXColor methods are useful to construct 24-bit ARGB integer color values.

  public void run(double deltaMs) {
    for (LXPoint p : model.points) {
      float hue = /* compute hue for this position */
      float sat = /* compute saturation for this position */
      float brightness = /* compute brightness for this position */
      colors[p.index] = LXColor.hsb(hue, sat, brightness);
    }
  }

Note that the colors array is owned by this pattern object. At the time run is called, it will contain the values generated by the last iteration of this pattern's runloop. Some patterns may elect only to update certain pixels. In general, the most reliable practice is to generate full frames on each iteration of run.

Parameters and Modulators

A pattern may expose parameters to give expose control of its behaviors to the user. As well as using modulators to help generate changing values over time. These should be added as fields to the class and registered in the constructor.

public class ExamplePattern extends LXPattern {

  // This is a parameter with default value 5, range 0-100
  public final CompoundParameter exampleParam =
    new CompoundParameter("Param", 5, 0, 100)
    .setDescription("This is an example parameter");

  // This is an LFO oscillating in a sin wave from 0 to 1 every second (1000ms)
  public final SinLFO lfo = new SinLFO(0, 1, 1000);
  
  public ExamplePattern(LX lx) {
    super(lx);
    addParameter("example", this.exampleParam);
    addModulator(this.lfo).start();
  }

  public void run(double deltaMs) {
    // Parameter and modulator values are automatically updated and can be
    // retrieved at runtime
    float paramValue = this.exampleParam.getValuef();
    float lfoValue = this.lfo.getValuef();
    ...
  }
}

Annotations

Category

/**
 * The LXCategory annotation may specify a String (or LXCategory constant) indicating
 * where this pattern is shown in the LX content library
 */
@LXCategory(LXCategory.TEXTURE)
public class ExamplePattern extends LXPattern {

Custom Name

/**
 * The LXComponentName annotation may be used to provide a custom name for this device
 * to be show in the UI. The default name will be the name of the class itself, with
 * the "Pattern" suffix removed. Another name may be specified if preferred.
 */
@LXComponentName("CustomName")
public class ExamplePattern extends LXPattern {