/**
* Modify this color to be the average between two colors, modifying the first.
*
* @arg other - The other color to average with
* @arg pos - The position (i.e. t) between the two colors.
* @pin pin - Which channels should not change. 1=0,2=1,4=2,etc
*/
void Color::averageInPlace(Color const &other, double pos, unsigned int pin)
{
_average_method_inplace(AverageMethod::Mean, other, pos, pin);
}
/**
* Move towards the other color by the given weight.
*
* @arg other - The other color to move towards with
* @arg pos - The weight to give the other color when mixing.
* @pin pin - Which channels should not change. 1=0,2=1,4=2,etc
*/
void Color::moveTowardsInPlace(Color const &other, double weight, unsigned int pin)
{
_average_method_inplace(AverageMethod::Weight, other, pos, pin);
}
void Color::_average_method_inplace(AverageMethod method, Color const &other, double weight, unsigned int pin)
{
// 1. If other is bad, return without action
if (!other)
return;
// 2. If this is bad, modify to be equal to other
if (_values.empty()) {
_values = other._values;
_space = other._space;
return;
}
// 3. Convert the other's space if it's different
if (_space && other._space != _space)
return _average_method_inplace(method, other.convert(_space), weight, pin);
// 4. Ensure opacity is compatible
if (!hasOpacity() && other.hasOpacity())
addOpacity(1.0); // Enable opacity if needed
// 5. Both are good, so average each channel
for (unsigned int i = 0; i < _values.size(); i++) {
if (pin & (1 << i))
continue;
if (method == AverageMethod::Position) {
// Note, other[i] returns 1.0 if the opacity is not set on other.
_values[i] = _values[i] * (1 - weight) + other[i] * weight;
} else if (method == AverageMethod::Weight) {
// Move towards
_values[i] += (other[i] - _values[i]) * force;
}
}
}
-
Please log in to leave a comment!