import { clamp, rand } from "./math.js"
import { deprecate } from "../logger/index.js"
/**
* A color manipulation class.
*/
export class Color {
/**
* @param {number} [r=0] - red component [0 .. 255]
* @param {number} [g=0] - green component [0 .. 255]
* @param {number} [b=0] - blue component [0 .. 255]
* @param {number} [alpha=1.0] - alpha value [0.0 .. 1.0]
*/
constructor(r = 0, g = 0, b = 0, alpha = 1.0) {
this.set(r, g, b, alpha);
}
/**
* @deprecate
* Set this color to the specified value.
* @param {number} r - red component [0 .. 255]
* @param {number} g - green component [0 .. 255]
* @param {number} b - blue component [0 .. 255]
* @param {number} [alpha=1.0] - alpha value [0.0 .. 1.0]
* @returns {Color} Reference to this object for method chaining
*/
set(r, g, b, alpha = 1.0) {
deprecate("Color().set()", "Color.set()")
return Color.set(this, r, g, b, alpha)
}
/**
* @deprecate
* Create a new copy of this color object.
* @returns {Color} Reference to the newly cloned object
*/
clone() {
deprecate("Color().clone()", "Color.copy()")
return Color.copy(this);
}
/**
* @deprecate
* Copy a color object or CSS color into this one.
* @param {Color} color
* @returns {Color} Reference to this object for method chaining
*/
copy(color) {
deprecate("Color().copy()", "Color.copy()")
return Color.copy(color, this)
}
/**
* Blend this color with the given one using addition.
*
* @deprecated
* @param {Color} color
* @returns {Color} Reference to this object for method chaining
*/
add(color) {
deprecate("Color().add()", "Color.add()")
this.r = clamp(this.r + color.r, 0, 255);
this.g = clamp(this.g + color.g, 0, 255);
this.b = clamp(this.b + color.b, 0, 255);
this.a = (this.a + color.a) / 2;
return this;
}
/**
* Darken this color value by 0..1
*
* @deprecated
* @param {number} scale
* @returns {Color} Reference to this object for method chaining
*/
darken(scale) {
deprecate("Color().darken()", "Color.darken()")
scale = clamp(scale, 0, 1);
this.r *= scale;
this.g *= scale;
this.b *= scale;
return this;
}
/**
* Lighten this color value by 0..1
*
* @deprecated
* @param {number} scale
* @returns {Color} Reference to this object for method chaining
*/
lighten(scale) {
deprecate("Color().lighten()", "Color.lighten()")
scale = clamp(scale, 0, 1);
this.r = clamp(this.r + (1 - this.r) * scale, 0, 1);
this.g = clamp(this.g + (1 - this.g) * scale, 0, 1);
this.b = clamp(this.b + (1 - this.b) * scale, 0, 1);
return this;
}
/**
* Linearly interpolate between this color and the given one.
* @deprecated
* @param {Color} color
* @param {number} alpha - with alpha = 0 being this color, and alpha = 1 being the given one.
* @returns {Color} Reference to this object for method chaining
*/
lerp(color, alpha) {
deprecate("Color().lerp()", "Color.lerp()")
alpha = clamp(alpha, 0, 1);
this.r += (color.r - this.r) * alpha;
this.g += (color.g - this.g) * alpha;
this.b += (color.b - this.b) * alpha;
return this;
}
/**
* Generate random r,g,b values for this color object
* @deprecated
* @param {number} [min=0] - minimum value for the random range
* @param {number} [max=255] - maxmium value for the random range
* @returns {Color} Reference to this object for method chaining
*/
random(min = 0, max = 255) {
deprecate("Color().random()", "Color.random()")
if (min < 0) {
min = 0;
}
if (max > 255) {
max = 255;
}
return this.set(
rand(min, max),
rand(min, max),
rand(min, max),
this.a
);
}
/**
* @param {number[]} array
*/
toArray(array, offset = 0) {
deprecate("Color().toArray()")
array[offset] = this.r
array[offset + 1] = this.g
array[offset + 2] = this.b
array[offset + 3] = this.a
return array
}
static random(min = 0, max = 255, out = new Color()) {
return Color.set(
out,
rand(min, max),
rand(min, max),
rand(min, max)
);
}
/**
* @param {Color} color
* @param {number} r
* @param {number} g
* @param {number} b
*/
static set(color, r, g, b, a = 1.0) {
color.r = r;
color.g = g;
color.b = b;
color.a = a;
return color;
}
/**
* @param {Color} color
*/
static copy(color, out = new Color()) {
return Color.set(out, color.r, color.g, color.b, color.a)
}
/**
* @param {Color} color1
* @param {Color} color2
*/
static add(color1, color2, out = new Color()) {
out.r = clamp(color1.r + color2.r, 0, 255);
out.g = clamp(color1.g + color2.g, 0, 255);
out.b = clamp(color1.b + color2.b, 0, 255);
out.a = (color1.a + color2.a) / 2;
return out;
}
/**
* @param {Color} color1
* @param {Color} color2
*/
static sub(color1, color2, out = new Color()) {
out.r = clamp(color1.r - color2.r, 0, 255);
out.g = clamp(color1.g - color2.g, 0, 255);
out.b = clamp(color1.b - color2.b, 0, 255);
out.a = (color1.a + color2.a) / 2;
return out;
}
/**
* @param {Color} color
* @param {number} scale
*/
static darken(color, scale, out = new Color()) {
scale = clamp(scale, 0, 1)
out.r = color.r * scale;
out.g = color.g * scale;
out.b = color.b * scale;
out.a = color.a
return this;
}
/**
* @param {Color} color
* @param {number} scale
*/
static lighten(color, scale, out = new Color()) {
scale = clamp(scale, 0, 1);
out.r = clamp(color.r + (1 - color.r) * scale, 0, 1);
out.g = clamp(color.g + (1 - color.g) * scale, 0, 1);
out.b = clamp(color.b + (1 - color.b) * scale, 0, 1);
return out;
}
/**
* @param {Color} color1
* @param {Color} color2
* @param {number} t
*/
static lerp(color1, color2, t, out = new Color()) {
out.r += color1.r + (color1.r - color2.r) * t;
out.g += color1.g + (color1.g - color2.g) * t;
out.b += color1.b + (color1.b - color2.b) * t;
out.a = color1.a + (color1.a - color2.a) * t;
return out
}
}