You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Kaleidoscope/plugins/Kaleidoscope-LED-Stalker/src/kaleidoscope/plugin/LED-Stalker.cpp

158 lines
4.0 KiB

/* -*- mode: c++ -*-
* Kaleidoscope-LED-Stalker -- Stalk keys pressed by lighting up and fading back the LED under them
* Copyright (C) 2017, 2018 Keyboard.io, Inc
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Kaleidoscope-LED-Stalker.h>
#include <Kaleidoscope-LEDControl.h>
#include "kaleidoscope/keyswitch_state.h"
namespace kaleidoscope {
namespace plugin {
StalkerEffect::ColorComputer *StalkerEffect::variant;
uint16_t StalkerEffect::step_length = 50;
cRGB StalkerEffect::inactive_color = (cRGB) {
0, 0, 0
};
StalkerEffect::TransientLEDMode::TransientLEDMode(const StalkerEffect *parent)
: parent_(parent),
step_start_time_(0),
map_{}
{}
EventHandlerResult StalkerEffect::onKeyEvent(KeyEvent &event) {
if (!Runtime.has_leds)
return EventHandlerResult::OK;
if (!event.addr.isValid())
return EventHandlerResult::OK;
if (::LEDControl.get_mode_index() != led_mode_id_)
return EventHandlerResult::OK;
// The simplest thing to do is trigger on both press and release. The color
// will fade while the key is held, and get restored to full brightness when
// it's released.
::LEDControl.get_mode<TransientLEDMode>()->map_[event.addr.toInt()] = 0xff;
return EventHandlerResult::OK;
}
void StalkerEffect::TransientLEDMode::update(void) {
if (!Runtime.has_leds)
return;
if (!parent_->variant)
return;
if (!Runtime.hasTimeExpired(step_start_time_, parent_->step_length))
return;
for (auto key_addr : KeyAddr::all()) {
uint8_t step = map_[key_addr.toInt()];
if (step) {
::LEDControl.setCrgbAt(key_addr, parent_->variant->compute(&step));
}
map_[key_addr.toInt()] = step;
if (!map_[key_addr.toInt()])
::LEDControl.setCrgbAt(key_addr, parent_->inactive_color);
}
step_start_time_ = Runtime.millisAtCycleStart();
}
namespace stalker {
cRGB Haunt::highlight_color_;
// Haunt
Haunt::Haunt(const cRGB highlight_color) {
highlight_color_ = highlight_color;
}
cRGB Haunt::compute(uint8_t *step) {
cRGB color = CRGB((uint8_t)min(*step * highlight_color_.r / 255, 255),
(uint8_t)min(*step * highlight_color_.g / 255, 255),
(uint8_t)min(*step * highlight_color_.b / 255, 255));
if (*step >= 0xf0)
*step -= 1;
else if (*step >= 0x40)
*step -= 16;
else if (*step >= 32)
*step -= 32;
else
*step = 0;
return color;
}
// BlazingTrail
BlazingTrail::BlazingTrail(void) {
}
constexpr uint8_t hue_start = 50.0 / 360 * 0xff;
constexpr uint8_t hue_end = 0;
cRGB BlazingTrail::compute(uint8_t *step) {
cRGB color;
// Get the position in the animation, where 0 is start and 0xff is end
uint8_t pos255 = 0xff - *step;
// Fade hue linearly from orange to red
uint8_t hue = hue_start + (pos255 * (hue_end - hue_start) >> 8);
// Fade value from full following a 1-x^4 curve
uint8_t val =
0xff // Maximum brightness
- ((uint32_t) pos255 * pos255 * pos255 * pos255 // Animation position to 4th power
>> 24) // ...pulled down to 8-bit range (but this has a maximum of 0xfc rather than 0xff)
- pos255 / (0x100 / 4); // Correction to bring the end result into a full 0 to 0xff range
color = hsvToRgb(hue, 0xff, val);
if (*step < 4) {
*step = 0;
} else {
*step -= 4;
}
return color;
}
// Rainbow
Rainbow::Rainbow(void) {
}
cRGB Rainbow::compute(uint8_t *step) {
if (*step > 0)
*step -= 1;
else
*step = 0;
return hsvToRgb(255 - *step, 255, *step);
}
}
}
}
kaleidoscope::plugin::StalkerEffect StalkerEffect;