Well, I decided to implement an easier to use version of my code. Now all the code changes required are to adjust the number of layers (LAYER_SIZE const), if you have added or removed from the default. And then there is an array that maps the color schemes to each of the layers.
I also implemented the ātransparencyā effect, where you can define a key to not change when you switch to it so e.g. if it was yellow and you change to a new layer where the color definition for that key is āTā, it will remain yellow.
Here is the main code:
// Color pallette. Can have up to 254 definitions (of any available color).
// The only requirement is for the first item to remain unchanged.
// The first item is used to shut down the led in any given key.
const cRGB colorPallette[4] = {
CRGB(0,0,0), // Off state, index 0
CRGB(255,255,100), // Base color, index 1
CRGB(0,0,255), // blue highlighting, index 2
CRGB(255,0,0) // red highlighting, index 3
};
// A 'transparent' mapping, will leave the key led in the same state as with the previous active layer
static const byte T = 255;
// Each number here is referencing an index from the colors array.
// The formatting reflects the actual key layout on the board
static const byte qwertyColor [ROWS][COLS] PROGMEM = {
{1,1,1,1,1,1,1, 1, 1, 1,1,1,1,1,1,1},
{1,1,1,1,1,1,1, 1, 1, 1,1,1,1,1,1,1},
{1,2,2,2,2,1,1, 1, 1, 1,1,2,2,2,2,1},
{1,1,1,1,1,1, 1, 1, 1, 1, 1,1,1,1,1,1}
};
// I moved wasd to esdf for FPS so they get highlighted for fraggin' :-)
// As an example, I am using 'transparent' colors but 1 instead of T would work as well.
static const byte numpadColor [ROWS][COLS] PROGMEM = {
{T,T,T,T,T,T,T, T, T, T,T,3,3,3,T,T},
{T,T,3,T,T,T,T, T, T, T,T,3,3,3,3,T},
{T,3,3,3,1,T,T, T, T, T,T,3,3,3,3,T},
{T,T,T,T,T,T, T, T, T, T, 3,3,3,3,3,3}
};
// The number of key mapping layers (by default, 3, i.e. QWERTY, NUMPAD and FUNCTION).
static const byte LAYER_SIZE = 3;
// Mapping color schemes to key mapping layers.
static const byte (*colorMapping[LAYER_SIZE]) [ROWS][COLS];
// A global variable to store the previously selected layer
static uint8_t previous_layer = -1;
/**
Loop hook to override LED colors
*/
static void layerColorOverride(bool post_clear) {
if (!post_clear)
return;
uint8_t top = Layer.top();
// Failsafe
if(top >= LAYER_SIZE)
return;
// Reference for the color scheme to use
const byte (*prevScheme)[ROWS][COLS];
const byte (*scheme)[ROWS][COLS];
for(byte x = 0; x < LAYER_SIZE; x++) {
if(top == x)
scheme = colorMapping[x];
else if (previous_layer == x)
prevScheme = colorMapping[x];
}
// Remember this layer for future calls
previous_layer = top;
// If the layer coming in is the same as last time, do nothing.
// Also in this case, qwerty and function are equivalent.
if(scheme == prevScheme)
return;
// Apply the scheme to the button LEDs
for(byte x = 0; x < ROWS;x++) {
for(byte y = 0; y < COLS;y++){
byte colorIndex = pgm_read_byte(*scheme[x][y]);
// Skip 'transparent' LED settings so they remain as is
if(T == colorIndex)
continue;
LEDControl.setCrgbAt(x, y, colorPallette[colorIndex]);
// Ensuring led shuts down if it was assigned to be off
if(0 == colorIndex)
LEDControl.refreshAt(x,y);
}
}
}
And here is the code to add in the setup() method to bind layers to color schemes:
// Assign color schemes to the colorMapping array. In this case, QWERTY and FUNCTION have the same scheme.
colorMapping[QWERTY] = &qwertyColor;
colorMapping[NUMPAD] = &numpadColor;
colorMapping[FUNCTION] = &qwertyColor;
If somebody has the time to review my code and suggest changes Iād be really thankful.
@algernon and everyone else: would you think this is worth putting in a plugin?
Also, I would really appreciate if someone gave this a test drive. Anyone?