Pattern Basics - AlbertGBarber/PixelSpork GitHub Wiki

Jump to:

Patterns Overview:

Patterns are used in certain effects to allow you to customize how colors are arranged. Patterns are always used in combination with a palette. The pattern sets the order for the colors, while the palette stores the actual CRGB colors.

In code, patterns are a struct that stores an array of palette indexes. Patterns have a maximum length of 65535 indexes (not that you'll probably ever need that many!)

For example, lets assume we have a simple palette consisting of red, green, and blue in that order (ie {red, green, blue} in array form). We could create a pattern for this palette like:

uint8_t pattern_arr[] = {0, 2, 1}; //Create an array of palette color indexes, which sets the order of the palette colors
patternPS rgbPattern = { pattern_arr, SIZE(pattern_arr), SIZE(pattern_arr)}; //Create the pattern using the index array and the array's length.
//The second SIZE() is used to record the maximum size of the palette array for memory management.
//It should always be the same as the actual size of the array. 

The first line above defines an array of uint8_t palette indexes. Each of the indexes corresponds to a color in the palette's color array (see palettes for more info). In this example, using the palette colors, we have set the pattern to be red, blue, green by swapping the second and last index of the palette.

The second line in the example, creates our pattern, named rgbPattern, using the index array and the array's length, 3. The pattern's length is stored in its length (uint8_t) variable, ie rgbPattern.length is 3.

Note that we are using the SIZE() macro to automatically set the array length.

Note that the above definition includes a second SIZE(pattern_arr) argument. This sets the maximum length of the pattern array (maxLength), and is used for memory management. You should always use the same value as you use for the pattern length. The pattern array's memory is handled internally. You should never touch maxLength unless you are certain you know what you are doing. You can read more about memory management here.

You can use the palette colors in any combination you wish, the only limitation is that you must use color indexes from the palette. For instance, we could make a pattern of two blues and two greens like: {1, 1, 2, 2}, but we should not make a pattern like {0, 1, 5}, because the palette doesn't have 5th index (ie, a sixth color). Technically, the code will still function, but the "5" will be treated as a "2", as explained in the advanced section below.

Pattern Functions:

In general you don't change patterns directly, rather you use helper the functions in patternUtilsPS to manage them. A list of helper functions is available here. As an example, we will shuffle the indexes of the rgbPattern above:

patternUtilsPS::shuffle(rgbPattern); 

In code above, use the shuffle() function on rgbPattern. shuffle(patternPS &pattern), takes a pattern as an argument and randomly re-arranges it. Note that shuffle() is a member of the patternUtilsPS namespace, which is the namespace container for all pattern functions.

Patterns in Effects:

If an effect uses a pattern, the pattern will probably be required in its constructor along with a palette. In most effects, the effect's pattern is a pointer, which is tied to the pattern you provide in the constructor. This is covered in more detail here.

Often times there will a separate effect constructor only requiring a palette. In this case, a pattern is still being used internally, but it is being set to match the palette. For example, for a palette length 5, the pattern would be set to {0, 1, 2, 3, 4}, which is each color in the palette in order.

To change an effect's pattern you would:

yourEffect.pattern = &yourNewPattern; 

This changes the effect's pattern address to be yourNewPattern. For some effects, you may need to use one of the effect's functions to change the pattern. This should be specified in the effect's documentation.

Note that because effects point to a pattern, changing the original pattern will also change it for the effect. For example if we changed the last color in the rgbPattern to red, this would also change it for any effects using rgbPattern. This is also true for the original color index array: if you change the last index in the pattern_arr above, it will also be changed for the pattern itself.

Advanced Stuff:

  • The pattern get and set functions (in the patternUtilsPS namespace) prevent you from reading off the end of a pattern by wrapping. For example if we try to get the color index from a pattern with two indexes by calling patternUtilsPS::getPatternVal(yourPattern, 2), we will get the first (0th index) color index instead. The "2" index is wrapped back round to 0 via inputIndex % patternLength. This helps prevent program crashes, and makes working with patterns a little more flexible.

  • 255 is often used to indicate a blank space in a pattern so the 255th palette color may be ignored (why would you even have a palette with 255 colors!?).

  • The index array is tied to the pattern using a pointer, patternArr, whose address is set to the index array's when the pattern is created. This means that any changes to the original index array will be reflected in the pattern (the pattern's index array and the original index array being one and the same).

  • Because a pattern's length is defined manually, a trick you can do is set the length to a smaller value than the actual length of the pattern array. The pattern will act as a smaller pattern, but you can increase its length at any time and "reveal" more colors. However, most effects don't expect the pattern length to change, so it may cause bugs. Likewise, make sure you do not touch the pattern's maxLength value, which stores the true length of the pattern array.