diff --git a/docs/js/controls/ControlFactory.js b/docs/js/controls/ControlFactory.js index 8f2a234..105a43d 100644 --- a/docs/js/controls/ControlFactory.js +++ b/docs/js/controls/ControlFactory.js @@ -302,13 +302,24 @@ class ControlFactory { input.type = 'color'; input.className = 'control control-color'; input.id = `el${config.property}`; - input.value = instance[config.property] ?? config.defaultValue; + + // Handle both RGB array and hex string for initial value + const currentValue = instance[config.property] ?? config.defaultValue; + if (Array.isArray(currentValue)) { + input.value = rgbArrayToHex(currentValue); + } else { + input.value = currentValue; + // Also convert the instance value to RGB array if it's hex + instance[config.property] = hexToRgbArray(currentValue); + } const listener = (event) => { - const newValue = event.target.value; - instance[config.property] = newValue; + const hexValue = event.target.value; + // Convert hex to RGB array for internal use + const rgbValue = hexToRgbArray(hexValue); + instance[config.property] = rgbValue; if (config.callback) { - config.callback(instance, newValue); + config.callback(instance, rgbValue); } }; input.addEventListener('input', listener); diff --git a/docs/js/shapes/CircleExpand.js b/docs/js/shapes/CircleExpand.js index 5649772..addc84d 100644 --- a/docs/js/shapes/CircleExpand.js +++ b/docs/js/shapes/CircleExpand.js @@ -7,8 +7,8 @@ class CircleExpand extends BaseShape { { type: 'range', min: 50, max: 150, defaultValue: 150, property: 'gap' }, { type: 'range', min: 0, max: 1, defaultValue: 1, property: 'linear' }, { type: 'range', min: 0, max: 1, defaultValue: 1, property: 'heart' }, - { type: 'color', defaultValue: '#fc03cf', property: 'colour1' }, - { type: 'color', defaultValue: '#00fffb', property: 'colour2' }, + { type: 'color', defaultValue: [252, 3, 207], property: 'colour1' }, + { type: 'color', defaultValue: [0, 255, 251], property: 'colour2' }, ]; constructor(nCircles, gap, linear, heart, colour1, colour2) { @@ -21,17 +21,6 @@ class CircleExpand extends BaseShape { this.colour2 = colour2; } - lerpColor(a, b, amount) { - const ah = +a.replace('#', '0x'); - const ar = ah >> 16, ag = ah >> 8 & 0xff, ab = ah & 0xff; - const bh = +b.replace('#', '0x'); - const br = bh >> 16, bg = bh >> 8 & 0xff, bb = bh & 0xff; - const rr = ar + amount * (br - ar); - const rg = ag + amount * (bg - ag); - const rb = ab + amount * (bb - ab); - return '#' + ((1 << 24) + (rr << 16) + (rg << 8) + rb | 0).toString(16).slice(1); - } - arraySort(x, y) { if (x.r > y.r) return 1; if (x.r < y.r) return -1; @@ -80,7 +69,7 @@ class CircleExpand extends BaseShape { const newArr = arrOfWidths.sort(this.arraySort); for (let i = this.nCircles - 1; i >= 0; i--) { - const newColour = this.lerpColor(this.colour1, this.colour2, newArr[i].c); + const newColour = colourToText(lerpRGB(this.colour1, this.colour2, newArr[i].c)); if (this.heart) { this.drawHeart(newArr[i].r, newColour); diff --git a/docs/js/shapes/Countdown.js b/docs/js/shapes/Countdown.js index c105d21..8faa3a1 100644 --- a/docs/js/shapes/Countdown.js +++ b/docs/js/shapes/Countdown.js @@ -48,7 +48,7 @@ class Countdown extends BaseShape { ctx.fillStyle = "white"; ctx.textAlign = "center"; - const futureDate = '2025-06-01T04:30:00'; + const futureDate = '2026-12-31T04:30:00'; const seconds = this.secondsUntilDate(futureDate); const minutes = Math.floor(seconds / 60); const hours = Math.floor(seconds / 3600); diff --git a/docs/js/shapes/EyePrototype.js b/docs/js/shapes/EyePrototype.js index c48cf72..97d2b2b 100644 --- a/docs/js/shapes/EyePrototype.js +++ b/docs/js/shapes/EyePrototype.js @@ -15,9 +15,9 @@ class EyePrototype extends BaseShape { { type: 'range', min: 0, max: 1, defaultValue: 0, property: 'draw_expand' }, { type: 'range', min: 0, max: 1, defaultValue: 1, property: 'draw_hypno' }, { type: 'range', min: 1, max: 10, defaultValue: 1, property: 'line_width' }, - { type: 'color', defaultValue: '#00fffb', property: 'colourPupil' }, - { type: 'color', defaultValue: '#ff0000', property: 'colourSpiral' }, - { type: 'color', defaultValue: '#00fffb', property: 'colourExpand' }, + { type: 'color', defaultValue: [0, 255, 251], property: 'colourPupil' }, + { type: 'color', defaultValue: [255, 0, 0], property: 'colourSpiral' }, + { type: 'color', defaultValue: [0, 255, 251], property: 'colourExpand' }, { type: 'range', min: 0, max: 1, defaultValue: 1, property: 'draw_eyelid' }, ]; @@ -42,7 +42,7 @@ class EyePrototype extends BaseShape { this.colourPupil = colourPupil; this.colourSpiral = colourSpiral; this.colourExpand = colourExpand; - this.centerPulse = new CircleExpand(10, 30, 1, 0, "#2D81FC", "#FC0362"); + this.centerPulse = new CircleExpand(10, 30, 1, 0, [45, 129, 252], [252, 3, 98]); } drawEyelid(rotation) { @@ -94,7 +94,7 @@ class EyePrototype extends BaseShape { } drawGrowEye(step) { - ctx.strokeStyle = this.colourExpand; + ctx.strokeStyle = colourToText(this.colourExpand); ctx.beginPath(); ctx.lineWidth = 5; ctx.arc(centerX + this.x, centerY + this.y, step, 0, 2 * Math.PI); @@ -102,7 +102,7 @@ class EyePrototype extends BaseShape { } drawCircle(step) { - ctx.strokeStyle = this.colourPupil; + ctx.strokeStyle = colourToText(this.colourPupil); ctx.beginPath(); ctx.lineWidth = 5; ctx.arc(centerX + this.x, centerY + this.y, step, 0, 2 * Math.PI); @@ -110,7 +110,7 @@ class EyePrototype extends BaseShape { } drawSpiral(step) { - ctx.strokeStyle = this.colourSpiral; + ctx.strokeStyle = colourToText(this.colourSpiral); const a = 1; const b = 5; ctx.moveTo(centerX, centerY); diff --git a/docs/js/shapes/FloralAccident.js b/docs/js/shapes/FloralAccident.js index a2d3faf..d93ac92 100644 --- a/docs/js/shapes/FloralAccident.js +++ b/docs/js/shapes/FloralAccident.js @@ -5,7 +5,7 @@ class FloralAccident extends BaseShape { static config = [ { type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' }, { type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' }, - { type: 'color', defaultValue: '#4287f5', property: 'colour' }, + { type: 'color', defaultValue: [66, 135, 245], property: 'colour' }, ]; constructor(sides, width, colour) { @@ -36,7 +36,7 @@ class FloralAccident extends BaseShape { end + rad(n), 0 ); - ctx.strokeStyle = this.colour; + ctx.strokeStyle = colourToText(this.colour); ctx.stroke(); ctx.beginPath(); @@ -48,7 +48,7 @@ class FloralAccident extends BaseShape { end - (end - stt - rad(rotation)) / 2 + rad(n), 0 ); - ctx.strokeStyle = this.colour; + ctx.strokeStyle = colourToText(this.colour); ctx.stroke(); stt = end + -(rad(rot - piv)); diff --git a/docs/js/shapes/FloralPhyllo.js b/docs/js/shapes/FloralPhyllo.js index 706bd5a..90b39b8 100644 --- a/docs/js/shapes/FloralPhyllo.js +++ b/docs/js/shapes/FloralPhyllo.js @@ -6,8 +6,8 @@ class FloralPhyllo extends BaseShape { { type: 'range', min: 1, max: 600, defaultValue: 300, property: 'width' }, { type: 'range', min: 1, max: 300, defaultValue: 150, property: 'depth' }, { type: 'range', min: 0, max: 3141, defaultValue: 0, property: 'start' }, - { type: 'color', defaultValue: '#4287f5', property: 'colour1' }, - { type: 'color', defaultValue: '#FC0362', property: 'colour2' }, + { type: 'color', defaultValue: [66, 135, 245], property: 'colour1' }, + { type: 'color', defaultValue: [252, 3, 98], property: 'colour2' }, ]; constructor(width, depth, start, colour1, colour2) { @@ -26,7 +26,7 @@ class FloralPhyllo extends BaseShape { const c = 1; for (let n = this.depth; n > 0; n -= 1) { - const ncolour = LerpHex(this.colour1, this.colour2, n / this.depth); + const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, n / this.depth)); const a = n * rotation / 1000; const r = c * Math.sqrt(n); const x = r * Math.cos(a) + centerX; diff --git a/docs/js/shapes/FloralPhyllo_Accident.js b/docs/js/shapes/FloralPhyllo_Accident.js index acad0fa..f31d408 100644 --- a/docs/js/shapes/FloralPhyllo_Accident.js +++ b/docs/js/shapes/FloralPhyllo_Accident.js @@ -5,8 +5,8 @@ class FloralPhyllo_Accident extends BaseShape { static config = [ { type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' }, { type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' }, - { type: 'color', defaultValue: '#2D81FC', property: 'colour1' }, - { type: 'color', defaultValue: '#FC0362', property: 'colour2' }, + { type: 'color', defaultValue: [45, 129, 252], property: 'colour1' }, + { type: 'color', defaultValue: [252, 3, 98], property: 'colour2' }, ]; constructor(sides, width, colour1, colour2) { @@ -23,7 +23,7 @@ class FloralPhyllo_Accident extends BaseShape { const c = 24; for (let n = 0; n < 300; n += 1) { - const ncolour = LerpHex(this.colour1, this.colour2, Math.cos(rad(n / 2))); + const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, Math.cos(rad(n / 2)))); const a = n * (rotation / 1000 + 100); const r = c * Math.sqrt(n); const x = r * Math.cos(a) + centerX; diff --git a/docs/js/shapes/MaryFace.js b/docs/js/shapes/MaryFace.js index 30d7265..918d3da 100644 --- a/docs/js/shapes/MaryFace.js +++ b/docs/js/shapes/MaryFace.js @@ -23,9 +23,9 @@ class MaryFace extends BaseShape { this.y2 = y2; this.rotate2 = rotate2; this.width2 = width2; - this.eye1 = new EyePrototype(x1, y1, rotate1, 0, width1, 10, 1, 1, 0, 0, 0, 1, "#00fffb", "#00fffb", "#00fffb"); - this.eye2 = new EyePrototype(x2, y2, rotate2, 0, width2, 10, 1, 1, 0, 0, 0, 1, "#00fffb", "#00fffb", "#00fffb"); - this.eye3 = new EyePrototype(110, -280, rotate2 + 2, 1, width2, 10, 1, 1, 0, 0, 0, 1, "#00fffb", "#00fffb", "#00fffb"); + this.eye1 = new EyePrototype(x1, y1, rotate1, 0, width1, 10, 1, 1, 0, 0, 0, 1, [0, 255, 251], [0, 255, 251], [0, 255, 251]); + this.eye2 = new EyePrototype(x2, y2, rotate2, 0, width2, 10, 1, 1, 0, 0, 0, 1, [0, 255, 251], [0, 255, 251], [0, 255, 251]); + this.eye3 = new EyePrototype(110, -280, rotate2 + 2, 1, width2, 10, 1, 1, 0, 0, 0, 1, [0, 255, 251], [0, 255, 251], [0, 255, 251]); } draw(elapsed) { diff --git a/docs/js/shapes/Nodal_expanding.js b/docs/js/shapes/Nodal_expanding.js index 826524b..fc876d1 100644 --- a/docs/js/shapes/Nodal_expanding.js +++ b/docs/js/shapes/Nodal_expanding.js @@ -3,12 +3,12 @@ */ class Nodal_expanding extends BaseShape { static config = [ - { type: 'range', min: 1, max: 100, defaultValue: 5, property: 'expand' }, + { type: 'range', min: 0, max: 100, defaultValue: 0.1, property: 'expand' }, { type: 'range', min: 1, max: 1000, defaultValue: 150, property: 'points' }, { type: 'range', min: 1, max: 360, defaultValue: 0, property: 'start' }, { type: 'range', min: 1, max: 10, defaultValue: 6, property: 'line_width' }, - { type: 'color', defaultValue: '#2D81FC', property: 'colour1' }, - { type: 'color', defaultValue: '#FC0362', property: 'colour2' }, + { type: 'color', defaultValue: [45, 129, 252], property: 'colour1' }, + { type: 'color', defaultValue: [252, 3, 98], property: 'colour2' }, { type: 'range', min: 0, max: 10, defaultValue: 5, property: 'colour_change' }, ]; @@ -31,7 +31,7 @@ class Nodal_expanding extends BaseShape { for (let z = 1; z <= this.points; z++) { ctx.beginPath(); - const ncolour = LerpHex(this.colour1, this.colour2, z / this.points); + const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, z / this.points)); ctx.moveTo( centerX + (Math.cos(rad(angle * (z - 1) + 0)) * (length - this.expand)), diff --git a/docs/js/shapes/PhylloCone.js b/docs/js/shapes/PhylloCone.js index 25e91b9..90aa7c2 100644 --- a/docs/js/shapes/PhylloCone.js +++ b/docs/js/shapes/PhylloCone.js @@ -9,8 +9,8 @@ class PhylloCone extends BaseShape { { type: 'range', min: 1, max: 2000, defaultValue: 1000, property: 'iterations' }, { type: 'range', min: 1, max: 10, defaultValue: 2, property: 'distance' }, { type: 'range', min: 1, max: 10, defaultValue: 2, property: 'line_width' }, - { type: 'color', defaultValue: '#2D81FC', property: 'colour1' }, - { type: 'color', defaultValue: '#FC0362', property: 'colour2' }, + { type: 'color', defaultValue: [45, 129, 252], property: 'colour1' }, + { type: 'color', defaultValue: [252, 3, 98], property: 'colour2' }, ]; @@ -43,7 +43,7 @@ class PhylloCone extends BaseShape { ctx.lineTo(xCoord, yCoord); } ctx.lineWidth = this.line_width; - ctx.strokeStyle = this.colour1; + ctx.strokeStyle = colourToText(this.colour1); ctx.stroke(); console.log(this.line_width); } diff --git a/docs/js/shapes/Phyllotaxis.js b/docs/js/shapes/Phyllotaxis.js index d382af0..23af94d 100644 --- a/docs/js/shapes/Phyllotaxis.js +++ b/docs/js/shapes/Phyllotaxis.js @@ -9,8 +9,8 @@ class Phyllotaxis extends BaseShape { { type: 'range', min: 0, max: 3141, defaultValue: 0, property: 'start' }, { type: 'range', min: 1, max: 10000, defaultValue: 300, property: 'nMax' }, { type: 'checkbox', defaultValue: false, property: 'giggle' }, - { type: 'color', defaultValue: '#2D81FC', property: 'colour1' }, - { type: 'color', defaultValue: '#FC0362', property: 'colour2' }, + { type: 'color', defaultValue: [45, 129, 252], property: 'colour1' }, + { type: 'color', defaultValue: [252, 3, 98], property: 'colour2' }, ]; constructor(width, size, sizeMin, start, nMax, giggle, colour1, colour2) { @@ -32,7 +32,7 @@ class Phyllotaxis extends BaseShape { for (let n = 0; n < maxIterations; n++) { ctx.beginPath(); - const ncolour = LerpHex(this.colour1, this.colour2, n / this.nMax); + const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, n / this.nMax)); const nAngle = n * angle + Math.sin(rad(n * 1 + angle * 40000)) / 2; const radius = distanceMultiplier * n; const xCoord = radius * Math.cos(nAngle) + centerX; @@ -52,7 +52,7 @@ class Phyllotaxis extends BaseShape { this.drawGiggle(rotation); } else { for (let n = 0; n < this.nMax; n += 1) { - const ncolour = LerpHex(this.colour1, this.colour2, n / this.nMax); + const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, n / this.nMax)); const a = n * (rotation / 1000); const r = this.width * Math.sqrt(n); const x = r * Math.cos(a) + centerX; diff --git a/docs/js/shapes/PolyTwistColourWidth.js b/docs/js/shapes/PolyTwistColourWidth.js index 03eff46..e7b7509 100644 --- a/docs/js/shapes/PolyTwistColourWidth.js +++ b/docs/js/shapes/PolyTwistColourWidth.js @@ -8,8 +8,8 @@ class PolyTwistColourWidth extends BaseShape { { type: 'range', min: 2, max: 5, defaultValue: 5, property: 'line_width' }, { type: 'range', min: 1, max: 100, defaultValue: 50, property: 'depth' }, { type: 'range', min: -180, max: 180, defaultValue: -90, property: 'rotation' }, - { type: 'color', defaultValue: '#4287f5', property: 'colour1' }, - { type: 'color', defaultValue: '#42f57b', property: 'colour2' }, + { type: 'color', defaultValue: [66, 135, 245], property: 'colour1' }, + { type: 'color', defaultValue: [66, 245, 123], property: 'colour2' }, ]; constructor(sides, width, line_width, depth, rotation, colour1, colour2) { @@ -41,7 +41,7 @@ class PolyTwistColourWidth extends BaseShape { for (let i = 0; i < this.depth; i++) { const fraction = i / this.depth; - const ncolour = LerpHex(this.colour1, this.colour2, fraction); + const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, fraction)); DrawPolygon(this.sides, this.width * widthMultiplier ** i, out_angle * i + this.rotation, ncolour, this.line_width); } } diff --git a/docs/js/shapes/RaysInShape.js b/docs/js/shapes/RaysInShape.js index e6569bc..98b6c0c 100644 --- a/docs/js/shapes/RaysInShape.js +++ b/docs/js/shapes/RaysInShape.js @@ -14,8 +14,8 @@ class RaysInShape extends BaseShape { { type: 'range', min: 1, max: 80, defaultValue: 5, property: 'trailLength' }, { type: 'range', min: 1, max: 500, defaultValue: 5, property: 'lineWidth' }, { type: 'checkbox', defaultValue: false, property: 'fade' }, - { type: 'color', defaultValue: '#43dbad', property: 'colourFree' }, - { type: 'color', defaultValue: '#f05c79', property: 'colourContained' }, + { type: 'color', defaultValue: [67, 219, 173], property: 'colourFree' }, + { type: 'color', defaultValue: [240, 92, 121], property: 'colourContained' }, { type: 'header', text: '--CollisionBox---' }, { type: 'checkbox', defaultValue: false, property: 'boxVisible' }, ]; @@ -134,8 +134,8 @@ class RaysInShape extends BaseShape { ctx.moveTo(prev.x, prev.y); ctx.lineTo(curr.x, curr.y); - const col = hexToRgb(this.colourFree); - ctx.strokeStyle = `rgba(${col.r}, ${col.g}, ${col.b}, ${alpha})`; + const col = this.colourFree; + ctx.strokeStyle = `rgba(${col[0]}, ${col[1]}, ${col[2]}, ${alpha})`; ctx.stroke(); } } @@ -274,8 +274,8 @@ class RaysInShape extends BaseShape { if (curr.collision) { ctx.strokeStyle = `rgba(255, 255, 0, ${alpha})`; } else { - const col = hexToRgb(this.colourContained); - ctx.strokeStyle = `rgba(${col.r}, ${col.g}, ${col.b}, ${alpha})`; + const col = this.colourContained; + ctx.strokeStyle = `rgba(${col[0]}, ${col[1]}, ${col[2]}, ${alpha})`; } ctx.stroke(); diff --git a/docs/js/shapes/Spiral1.js b/docs/js/shapes/Spiral1.js index f6bf22d..e2e5646 100644 --- a/docs/js/shapes/Spiral1.js +++ b/docs/js/shapes/Spiral1.js @@ -5,7 +5,7 @@ class Spiral1 extends BaseShape { static config = [ { type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' }, { type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' }, - { type: 'color', defaultValue: '#4287f5', property: 'colour' }, + { type: 'color', defaultValue: [66, 135, 245], property: 'colour' }, ]; constructor(sides, width, colour) { @@ -37,7 +37,7 @@ class Spiral1 extends BaseShape { end + rad(rotation) + rad(n), 0 ); - ctx.strokeStyle = this.colour; + ctx.strokeStyle = colourToText(this.colour); ctx.stroke(); ctx.beginPath(); @@ -49,7 +49,7 @@ class Spiral1 extends BaseShape { end - (end - stt) / 2 + rad(n) - rad(rotation), 0 ); - ctx.strokeStyle = this.colour; + ctx.strokeStyle = colourToText(this.colour); ctx.stroke(); stt = end + -(rad(rot - piv)); diff --git a/docs/js/shapes/SquareTwist_angle.js b/docs/js/shapes/SquareTwist_angle.js index b2a65d9..28c9bf0 100644 --- a/docs/js/shapes/SquareTwist_angle.js +++ b/docs/js/shapes/SquareTwist_angle.js @@ -5,7 +5,7 @@ class SquareTwist_angle extends BaseShape { static config = [ { type: 'range', min: 1, max: 800, defaultValue: 400, property: 'width' }, { type: 'range', min: 1, max: 10, defaultValue: 1, property: 'line_width' }, - { type: 'color', defaultValue: '#2D81FC', property: 'colour1' }, + { type: 'color', defaultValue: [45, 129, 252], property: 'colour1' }, ]; constructor(width, line_width, colour1) { @@ -20,7 +20,7 @@ class SquareTwist_angle extends BaseShape { ctx.translate(centerX, centerY); ctx.rotate(rad(angle + 180)); ctx.beginPath(); - ctx.strokeStyle = colour; + ctx.strokeStyle = colourToText(colour); ctx.lineWidth = this.line_width; ctx.rect(-size / 2, -size / 2, size, size); ctx.stroke(); diff --git a/docs/js/utils/helpers.js b/docs/js/utils/helpers.js index c49327f..2e2bdcf 100644 --- a/docs/js/utils/helpers.js +++ b/docs/js/utils/helpers.js @@ -21,18 +21,36 @@ function colourToText(colour) { return "rgb(" + colour[0] + "," + colour[1] + "," + colour[2] + ")"; } + /** - * Convert hex color to RGB object - * @param {string} hex - Hex color string (e.g., '#ff0000') - * @returns {{r: number, g: number, b: number}|null} RGB object or null + * Convert hex color to RGB array + * @param {string} hex - Hex color string (with or without #) + * @returns {number[]} RGB array [r, g, b] + */ +function hexToRgbArray(hex) { + // supports "#RRGGBB" (you can add "#RGB" if needed) + if (hex[0] === "#") hex = hex.slice(1); + const n = parseInt(hex, 16); + return [(n >> 16) & 255, (n >> 8) & 255, n & 255]; +} + +/** + * Convert hex color to RGB object (for backward compatibility) + * @param {string} hex - Hex color string (with or without #) + * @returns {{r: number, g: number, b: number}} RGB object */ function hexToRgb(hex) { - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result ? { - r: parseInt(result[1], 16), - g: parseInt(result[2], 16), - b: parseInt(result[3], 16) - } : null; + const arr = hexToRgbArray(hex); + return { r: arr[0], g: arr[1], b: arr[2] }; +} + +/** + * Convert RGB array to hex color string + * @param {number[]} rgb - RGB array [r, g, b] + * @returns {string} Hex color string with # + */ +function rgbArrayToHex(rgb) { + return "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1); } /** @@ -73,23 +91,6 @@ function lerpRGB(a, b, t) { return result; } -/** - * Legacy LerpRGB function (handles negative t) - * @param {number[]} a - Start RGB array - * @param {number[]} b - End RGB array - * @param {number} t - Interpolation amount - * @returns {number[]} Interpolated RGB array - */ -function LerpRGB(a, b, t) { - if (t < 0) { - t *= -1; - } - const newColor = [0, 0, 0]; - newColor[0] = a[0] + (b[0] - a[0]) * t; - newColor[1] = a[1] + (b[1] - a[1]) * t; - newColor[2] = a[2] + (b[2] - a[2]) * t; - return newColor; -} /** * Generate a wave-normalized value (0-1 range using sine)