mirror of
https://github.com/esphome/esphome.git
synced 2024-11-26 17:05:21 +01:00
Light transition fixes (#2320)
This commit is contained in:
parent
c78fb90e2f
commit
4c61cf153c
3 changed files with 16 additions and 6 deletions
|
@ -62,10 +62,13 @@ void AddressableLightTransformer::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<LightColorValues> AddressableLightTransformer::apply() {
|
optional<LightColorValues> AddressableLightTransformer::apply() {
|
||||||
// Don't try to transition over running effects, instead immediately use the target values. write_state() and the
|
float smoothed_progress = LightTransitionTransformer::smoothed_progress(this->get_progress_());
|
||||||
// effects pick up the change from current_values.
|
|
||||||
|
// When running an output-buffer modifying effect, don't try to transition individual LEDs, but instead just fade the
|
||||||
|
// LightColorValues. write_state() then picks up the change in brightness, and the color change is picked up by the
|
||||||
|
// effects which respect it.
|
||||||
if (this->light_.is_effect_active())
|
if (this->light_.is_effect_active())
|
||||||
return this->target_values_;
|
return LightColorValues::lerp(this->get_start_values(), this->get_target_values(), smoothed_progress);
|
||||||
|
|
||||||
// Use a specialized transition for addressable lights: instead of using a unified transition for
|
// Use a specialized transition for addressable lights: instead of using a unified transition for
|
||||||
// all LEDs, we use the current state of each LED as the start.
|
// all LEDs, we use the current state of each LED as the start.
|
||||||
|
@ -75,8 +78,6 @@ optional<LightColorValues> AddressableLightTransformer::apply() {
|
||||||
// Instead, we "fake" the look of the LERP by using an exponential average over time and using
|
// Instead, we "fake" the look of the LERP by using an exponential average over time and using
|
||||||
// dynamically-calculated alpha values to match the look.
|
// dynamically-calculated alpha values to match the look.
|
||||||
|
|
||||||
float smoothed_progress = LightTransitionTransformer::smoothed_progress(this->get_progress_());
|
|
||||||
|
|
||||||
float denom = (1.0f - smoothed_progress);
|
float denom = (1.0f - smoothed_progress);
|
||||||
float alpha = denom == 0.0f ? 0.0f : (smoothed_progress - this->last_transition_progress_) / denom;
|
float alpha = denom == 0.0f ? 0.0f : (smoothed_progress - this->last_transition_progress_) / denom;
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,9 @@ void LightState::loop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->transformer_->is_finished()) {
|
if (this->transformer_->is_finished()) {
|
||||||
|
// if the transition has written directly to the output, current_values is outdated, so update it
|
||||||
|
this->current_values = this->transformer_->get_target_values();
|
||||||
|
|
||||||
this->transformer_->stop();
|
this->transformer_->stop();
|
||||||
this->transformer_ = nullptr;
|
this->transformer_ = nullptr;
|
||||||
this->target_state_reached_callback_.call();
|
this->target_state_reached_callback_.call();
|
||||||
|
|
|
@ -12,12 +12,18 @@ namespace light {
|
||||||
class LightTransitionTransformer : public LightTransformer {
|
class LightTransitionTransformer : public LightTransformer {
|
||||||
public:
|
public:
|
||||||
void start() override {
|
void start() override {
|
||||||
// When turning light on from off state, use colors from target state.
|
// When turning light on from off state, use target state and only increase brightness from zero.
|
||||||
if (!this->start_values_.is_on() && this->target_values_.is_on()) {
|
if (!this->start_values_.is_on() && this->target_values_.is_on()) {
|
||||||
this->start_values_ = LightColorValues(this->target_values_);
|
this->start_values_ = LightColorValues(this->target_values_);
|
||||||
this->start_values_.set_brightness(0.0f);
|
this->start_values_.set_brightness(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When turning light off from on state, use source state and only decrease brightness to zero.
|
||||||
|
if (this->start_values_.is_on() && !this->target_values_.is_on()) {
|
||||||
|
this->target_values_ = LightColorValues(this->start_values_);
|
||||||
|
this->target_values_.set_brightness(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
// When changing color mode, go through off state, as color modes are orthogonal and there can't be two active.
|
// When changing color mode, go through off state, as color modes are orthogonal and there can't be two active.
|
||||||
if (this->start_values_.get_color_mode() != this->target_values_.get_color_mode()) {
|
if (this->start_values_.get_color_mode() != this->target_values_.get_color_mode()) {
|
||||||
this->changing_color_mode_ = true;
|
this->changing_color_mode_ = true;
|
||||||
|
|
Loading…
Reference in a new issue