/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.dmx.internal.action; import org.openhab.binding.dmx.internal.core.DmxChannel; import org.openhab.binding.dmx.internal.core.DmxUtil; /** * Fade action. Fades a given channel from its current state to the requested * state in the given amount of time. After the fade, the new state is held for * a given or indefinite time. * * @author Davy Vanherbergen * @since 1.2.0 */ public class FadeAction extends BaseAction { /** Time in ms to hold the target value. -1 is indefinite */ private long holdTime; /** Time in ms to fade from current value to new target value */ private long fadeTime; /** Channel output value on action start. **/ private int startValue; /** Desired channel output value. **/ private int targetValue; private long stepDuration; private FadeDirection fadeDirection; /** * Create new fading action. * * @param fadeTime * time in ms to fade from the current value to the new value. * @param targetValue * new value 0-255 for this channel. * @param holdTime * time in ms to hold the color before moving to the next action. * -1 is indefinite. */ public FadeAction(int fadeTime, int targetValue, int holdTime) { super(); this.fadeTime = fadeTime; this.targetValue = DmxUtil.capDmxValue(targetValue); this.holdTime = holdTime; if (holdTime < -1) { this.holdTime = -1; } if (fadeTime < 0) { this.fadeTime = 0; } } /** * {@inheritDoc} */ @Override protected int calculateNewValue(DmxChannel channel, long currentTime) { int newValue = channel.getValue(); if (startTime == 0) { startTime = currentTime; if (fadeTime != 0) { startValue = channel.getValue(); // calculate fade details if (startValue == targetValue) { stepDuration = 1; } else if (startValue > targetValue) { fadeDirection = FadeDirection.down; stepDuration = fadeTime / (startValue - targetValue); } else { fadeDirection = FadeDirection.up; stepDuration = fadeTime / (targetValue - startValue); } } else { newValue = targetValue; } } long duration = currentTime - startTime; if (fadeTime != 0 && newValue != targetValue) { // calculate new fade value if (stepDuration == 0) { stepDuration = 1; } int currentStep = (int) (duration / stepDuration); if (fadeDirection == FadeDirection.up) { newValue = DmxUtil.capDmxValue(startValue + currentStep); if (newValue > targetValue) { newValue = targetValue; } } else { newValue = DmxUtil.capDmxValue(startValue - currentStep); if (newValue < targetValue) { newValue = targetValue; } } } if (newValue == targetValue && holdTime > -1) { // we reached the target already, check if we need to hold longer if (((holdTime > 0 || fadeTime > 0) && (duration >= fadeTime + holdTime)) || (holdTime == 0 && fadeTime == 0)) { // mark action as completed completed = true; } } return newValue; } } enum FadeDirection { up, down }