From 95f35a1fa0632a7158fe3557ca26664302a69c57 Mon Sep 17 00:00:00 2001 From: Sam <34695753+SamEyeBam@users.noreply.github.com> Date: Wed, 31 Dec 2025 13:47:16 +1300 Subject: [PATCH] Shape variable fixes --- docs/index.html | 3 +- docs/js/presets.js | 93 +++++++++++-------- docs/js/shapes/EyePrototype.js | 71 ++++++++------ docs/js/shapes/FloralPhyllo.js | 12 ++- docs/js/shapes/Nodal.js | 56 +++++++++++ docs/js/shapes/Nodal_expanding.js | 10 +- .../shapes/{Spiral1.js => SpiralWormhole.js} | 5 +- docs/js/utils/helpers.js | 68 ++++++++++++++ 8 files changed, 238 insertions(+), 80 deletions(-) create mode 100644 docs/js/shapes/Nodal.js rename docs/js/shapes/{Spiral1.js => SpiralWormhole.js} (93%) diff --git a/docs/index.html b/docs/index.html index 64a9f75..e9fe447 100644 --- a/docs/index.html +++ b/docs/index.html @@ -51,9 +51,10 @@ - + + diff --git a/docs/js/presets.js b/docs/js/presets.js index b4e552e..204d83b 100644 --- a/docs/js/presets.js +++ b/docs/js/presets.js @@ -7,52 +7,71 @@ const BUILT_IN_PRESETS = [ { - name: "Poly Twist Rainbow", - description: "hexagon bby", + name: "Minds Eye is Full Of Flowers", + description: "Look at me", builtIn: true, data: { version: 1, layers: [ { - name: "PolyTwistColourWidth", - visible: true, - paused: false, - collapsed: true, - values: { - sides: 6, - width: 500, - line_width: 2, - depth: 80, - rotation: 0, - colour1: "#ff0066", - colour2: "#00ffff" - }, - filters: {} - } - ] - } - }, - { - name: "Expanding Nodes", - description: "Pulsing nodal pattern", - builtIn: true, - data: { - version: 1, - layers: [ - { - name: "Nodal_expanding", + name: "FloralPhyllo", visible: true, paused: false, collapsed: false, values: { - expand: 2, - points: 550, - start: 0, - line_width: 4, - colour1: "#ffffff", - colour2: "#4a9eff", - colour_change: 3, - speedMultiplier: 535 + width_start: 30, + width_scale: 333, + depth: 200, + start: 625, + colour1: [ + 66, + 135, + 245 + ], + colour2: [ + 252, + 3, + 98 + ], + speedMultiplier: 500 + }, + filters: {}, + controlBounds: {} + }, + { + name: "EyePrototype", + visible: true, + paused: false, + collapsed: false, + values: { + x: 0, + y: 0, + rotate: 0, + flip: 0, + width: 531, + blink_speed: 27, + draw_spiral: 0, + spiral_full: 1, + draw_pupil: 0, + draw_expand: 0, + draw_hypno: 1, + line_width: 1, + colourPupil: [ + 0, + 255, + 251 + ], + colourSpiral: [ + 255, + 0, + 0 + ], + colourExpand: [ + 0, + 255, + 251 + ], + speedMultiplier: 100 }, filters: {}, controlBounds: {} diff --git a/docs/js/shapes/EyePrototype.js b/docs/js/shapes/EyePrototype.js index 97d2b2b..c08008f 100644 --- a/docs/js/shapes/EyePrototype.js +++ b/docs/js/shapes/EyePrototype.js @@ -3,25 +3,30 @@ */ class EyePrototype extends BaseShape { static config = [ + { type: 'header', text: '---Position---' }, { type: 'range', min: -400, max: 400, defaultValue: 0, property: 'x' }, { type: 'range', min: -400, max: 400, defaultValue: 0, property: 'y' }, { type: 'range', min: -180, max: 180, defaultValue: 0, property: 'rotate' }, - { type: 'range', min: 0, max: 1, defaultValue: 1, property: 'flip' }, + { type: 'checkbox', defaultValue: false, property: 'flip' }, + { type: 'header', text: '--General---' }, { type: 'range', min: 1, max: 800, defaultValue: 400, property: 'width' }, - { type: 'range', min: 1, max: 100, defaultValue: 5, property: 'blink_speed' }, - { type: 'range', min: 0, max: 1, defaultValue: 0, property: 'draw_spiral' }, - { type: 'range', min: 0, max: 1, defaultValue: 1, property: 'spiral_full' }, - { type: 'range', min: 0, max: 1, defaultValue: 0, property: 'draw_pupil' }, - { 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: 'range', min: 1, max: 100, defaultValue: 30, property: 'blink_speed' }, + { type: 'range', min: 1, max: 10, defaultValue: 5, property: 'line_width' }, + { type: 'color', defaultValue: [66, 135, 245], property: 'outline_colour' }, + { type: 'checkbox', defaultValue: true, property: 'draw_eyelid' }, + { type: 'header', text: '--Effects---' }, + { type: 'checkbox', defaultValue: false, property: 'draw_spiral' }, + { type: 'checkbox', defaultValue: true, property: 'spiral_full' }, + { type: 'checkbox', defaultValue: false, property: 'draw_pupil' }, + { type: 'checkbox', defaultValue: false, property: 'draw_expand' }, + { type: 'checkbox', defaultValue: false, property: 'draw_hypno' }, + { type: 'checkbox', defaultValue: true, property: 'draw_wormhole' }, { 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' }, ]; - constructor(x, y, rotate, flip, width, blink_speed, draw_spiral, spiral_full, draw_pupil, draw_expand, draw_hypno, line_width, colourPupil, colourSpiral, colourExpand) { + constructor(x, y, rotate, flip, width, blink_speed, line_width, outline_colour, draw_eyelid, draw_spiral, spiral_full, draw_pupil, draw_expand, draw_hypno, draw_wormhole, colourPupil, colourSpiral, colourExpand) { super(); this.x = x; this.y = y; @@ -30,32 +35,37 @@ class EyePrototype extends BaseShape { this.width = width; this.blink_speed = blink_speed; this.line_width = line_width; - this.step = 0; - this.opening = true; - this.counter = 0; - this.cooldown = 0; + this.outline_colour = outline_colour; + this.draw_eyelid = draw_eyelid; this.draw_spiral = draw_spiral; this.spiral_full = spiral_full; this.draw_pupil = draw_pupil; this.draw_expand = draw_expand; this.draw_hypno = draw_hypno; + this.draw_wormhole = draw_wormhole; this.colourPupil = colourPupil; this.colourSpiral = colourSpiral; this.colourExpand = colourExpand; + this.step = 0; + this.opening = true; + this.counter = 0; + this.cooldown = 0; this.centerPulse = new CircleExpand(10, 30, 1, 0, [45, 129, 252], [252, 3, 98]); + this.wormhole = new SpiralWormhole(20, 120, [66, 135, 245]); } - drawEyelid(rotation) { - ctx.strokeStyle = "orange"; + drawEyelid(rotation, lineWidth) { + ctx.strokeStyle = "black"; const relCenterX = centerX + this.x; const relCenterY = centerY + this.y; rotation *= (this.speedMultiplier / 100); - ctx.lineWidth = 1; + ctx.lineWidth = lineWidth; + ctx.strokeStyle = colourToText(this.outline_colour); ctx.beginPath(); let newPoint = 0; let newPoint1 = 0; const addedRotate = this.flip ? 90 : 0; - + newPoint = rotatePoint(-this.width / 2, 0, this.rotate + addedRotate); ctx.moveTo(relCenterX + newPoint[0], relCenterY + newPoint[1]); newPoint = rotatePoint(0, -rotation / 400 * this.width, this.rotate + addedRotate); @@ -76,7 +86,7 @@ class EyePrototype extends BaseShape { let newPoint = 0; let newPoint1 = 0; const addedRotate = this.flip ? 90 : 0; - + const squarePath = new Path2D(); newPoint = rotatePoint(-this.width / 2, 0, this.rotate + addedRotate); squarePath.moveTo(relCenterX + newPoint[0], relCenterY + newPoint[1]); @@ -116,7 +126,7 @@ class EyePrototype extends BaseShape { ctx.moveTo(centerX, centerY); ctx.beginPath(); const max = this.spiral_full ? this.width : this.width / 2; - + for (let i = 0; i < max; i++) { const angle = 0.1 * i; const x = centerX + (a + b * angle) * Math.cos(angle + step / 2); @@ -160,28 +170,31 @@ class EyePrototype extends BaseShape { ctx.fillStyle = "black"; ctx.save(); - this.drawEyelid(outputRotation); + this.drawEyelid(outputRotation, this.line_width); this.eyelidCut(outputRotation); - + if (Math.floor(this.counter % (this.width / 4)) === 0) { this.counter = 0; } - + ctx.fillStyle = "black"; ctx.fillRect(this.x - this.width / 2 + centerX, 0, this.width, ctx.canvas.height); - - if (this.draw_expand) { - this.drawGrowEye(this.width / 4 + this.counter); - } if (this.draw_hypno) { this.centerPulse.draw(elapsed); } - + if (this.draw_wormhole) { + this.wormhole.draw(elapsed); + } + + if (this.draw_expand) { + this.drawGrowEye(this.width / 4 + this.counter); + } + if (this.draw_spiral) { this.drawSpiral(elapsed); } - + if (this.draw_pupil) { this.drawCircle(this.width / 4); } diff --git a/docs/js/shapes/FloralPhyllo.js b/docs/js/shapes/FloralPhyllo.js index 90b39b8..793e5a1 100644 --- a/docs/js/shapes/FloralPhyllo.js +++ b/docs/js/shapes/FloralPhyllo.js @@ -3,16 +3,18 @@ */ class FloralPhyllo extends BaseShape { static config = [ - { type: 'range', min: 1, max: 600, defaultValue: 300, property: 'width' }, - { type: 'range', min: 1, max: 300, defaultValue: 150, property: 'depth' }, + { type: 'range', min: 1, max: 100, defaultValue: 60, property: 'width_start' }, + { type: 'range', min: 1, max: 1000, defaultValue: 650, property: 'width_scale' }, + { type: 'range', min: 1, max: 1000, defaultValue: 200, property: 'depth' }, { type: 'range', min: 0, max: 3141, defaultValue: 0, property: 'start' }, { type: 'color', defaultValue: [66, 135, 245], property: 'colour1' }, { type: 'color', defaultValue: [252, 3, 98], property: 'colour2' }, ]; - constructor(width, depth, start, colour1, colour2) { + constructor(width_start,width_scale, depth, start, colour1, colour2) { super(); - this.width = width; + this.width_start = width_start; + this.width_scale = width_scale; this.depth = depth; this.start = start; this.colour1 = colour1; @@ -32,7 +34,7 @@ class FloralPhyllo extends BaseShape { const x = r * Math.cos(a) + centerX; const y = r * Math.sin(a) + centerY; - drawEyelid(n * 2.4 + 40, x, y, ncolour); + drawPetal(n * this.width_scale/100 + this.width_start, x, y, ncolour); } } } diff --git a/docs/js/shapes/Nodal.js b/docs/js/shapes/Nodal.js new file mode 100644 index 0000000..28db7c2 --- /dev/null +++ b/docs/js/shapes/Nodal.js @@ -0,0 +1,56 @@ + + +class Nodal extends BaseShape { + static config = [ + { type: 'range', min: 0, max: 360, defaultValue: 0, property: 'shift' }, + { type: 'range', min: 10, max: 800, defaultValue: 400, property: 'radius' }, + { type: 'range', min: 3, max: 500, defaultValue: 100, property: 'points' }, + { type: 'range', min: 1, max: 250, defaultValue: 41, property: 'step' }, + { type: 'range', min: 1, max: 20, defaultValue: 2, property: 'lineWidth' }, + { type: 'color', defaultValue: [64, 199, 119], property: 'colour' }, + ]; + + constructor(shift, radius, points, step, lineWidth, colour) { + super(); + this.shift = shift; + this.radius = radius; + this.points = points; + this.step = step; + this.lineWidth = lineWidth; + this.colour = colour; + } + + draw(elapsed) { + const rotation = elapsed * (this.speedMultiplier / 100) + this.shift; + const angle = 360 / this.points * this.step; + + ctx.beginPath(); + ctx.moveTo( + centerX + Math.cos(this.rad(angle + rotation)) * this.radius, + centerY + Math.sin(this.rad(angle + rotation)) * this.radius + ); + + let totalMoves = 1; + while ((totalMoves * this.step) % this.points !== 0) { + totalMoves++; + } + totalMoves++; + + for (let z = 1; z <= totalMoves; z++) { + ctx.lineTo( + centerX + Math.cos(this.rad(angle * z + rotation)) * this.radius, + centerY + Math.sin(this.rad(angle * z + rotation)) * this.radius + ); + } + + ctx.strokeStyle = colourToText(this.colour); + ctx.lineWidth = this.lineWidth; + ctx.stroke(); + } + + rad(degrees) { + return degrees * (Math.PI / 180); + } +} +console.log('Nodal shape loaded'); +shapeRegistry.register('Nodal', Nodal); \ No newline at end of file diff --git a/docs/js/shapes/Nodal_expanding.js b/docs/js/shapes/Nodal_expanding.js index fc876d1..0099275 100644 --- a/docs/js/shapes/Nodal_expanding.js +++ b/docs/js/shapes/Nodal_expanding.js @@ -3,16 +3,15 @@ */ class Nodal_expanding extends BaseShape { static config = [ - { 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: 0, max: 100, defaultValue: 1, property: 'expand' }, + { type: 'range', min: 1, max: 10000, defaultValue: 1000, property: 'points' }, + { type: 'range', min: 1, max: 360, defaultValue: 32, property: 'start' }, { type: 'range', min: 1, max: 10, defaultValue: 6, property: 'line_width' }, { 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' }, ]; - constructor(expand, points, start, line_width, colour1, colour2, colour_change) { + constructor(expand, points, start, line_width, colour1, colour2) { super(); this.expand = expand; this.points = points; @@ -20,7 +19,6 @@ class Nodal_expanding extends BaseShape { this.line_width = line_width; this.colour1 = colour1; this.colour2 = colour2; - this.colour_change = colour_change; } draw(elapsed) { diff --git a/docs/js/shapes/Spiral1.js b/docs/js/shapes/SpiralWormhole.js similarity index 93% rename from docs/js/shapes/Spiral1.js rename to docs/js/shapes/SpiralWormhole.js index e2e5646..98c13b1 100644 --- a/docs/js/shapes/Spiral1.js +++ b/docs/js/shapes/SpiralWormhole.js @@ -1,7 +1,7 @@ /** * Spiral1 - Dual-direction spiral pattern */ -class Spiral1 extends BaseShape { +class SpiralWormhole extends BaseShape { static config = [ { type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' }, { type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' }, @@ -16,6 +16,7 @@ class Spiral1 extends BaseShape { } draw(elapsed) { + elapsed *= 10 this.updateFilters(elapsed); const rotation = elapsed * (this.speedMultiplier / 100); const rot = Math.round((this.sides - 2) * 180 / this.sides * 2); @@ -57,4 +58,4 @@ class Spiral1 extends BaseShape { } } -shapeRegistry.register('Spiral1', Spiral1); +shapeRegistry.register('SpiralWormhole', SpiralWormhole); diff --git a/docs/js/utils/helpers.js b/docs/js/utils/helpers.js index 2e2bdcf..c7a0ce3 100644 --- a/docs/js/utils/helpers.js +++ b/docs/js/utils/helpers.js @@ -53,6 +53,74 @@ function rgbArrayToHex(rgb) { return "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1); } +/** + * Cached petal path for efficient reuse (created once, transformed many times) + * @type {Path2D|null} + */ +let _petalPathCache = null; + +/** + * Get or create the cached petal path (unit size, pointing right from origin) + * @returns {Path2D} + */ +function getPetalPath() { + if (!_petalPathCache) { + _petalPathCache = new Path2D(); + _petalPathCache.moveTo(0, 0); + _petalPathCache.quadraticCurveTo(0.5, 0.5, 1, 0); + _petalPathCache.quadraticCurveTo(0.5, -0.5, 0, 0); + } + return _petalPathCache; +} + +/** + * Draw a petal shape efficiently using canvas transforms + * Much faster than drawEyelid - uses cached path and transforms + * @param {number} width - Width/length of the petal + * @param {number} x - X position + * @param {number} y - Y position + * @param {string} colour - Fill color (CSS string) + */ +function drawPetal(width, x, y, colour, line_width = 2) { + const angle = Math.atan2(y - centerY, x - centerX); + + ctx.save(); + ctx.translate(x, y); + ctx.rotate(angle); + ctx.scale(width, width); + + ctx.fillStyle = colour; + ctx.fill(getPetalPath()); + + ctx.lineWidth = 2 / width; // Scale line width inversely so it stays consistent + ctx.strokeStyle = "black"; + ctx.stroke(getPetalPath()); + + ctx.restore(); +} + +/** + * Draw multiple petals efficiently by batching transforms + * Even faster for large numbers - minimizes state changes + * @param {Array<{width: number, x: number, y: number, colour: string}>} petals + */ +function drawPetalsBatch(petals) { + const path = getPetalPath(); + + for (let i = 0; i < petals.length; i++) { + const p = petals[i]; + const angle = Math.atan2(p.y - centerY, p.x - centerX); + + ctx.save(); + ctx.translate(p.x, p.y); + ctx.rotate(angle); + ctx.scale(p.width, p.width); + ctx.fillStyle = p.colour; + ctx.fill(path); + ctx.restore(); + } +} + /** * Linear interpolation between two hex colors * @param {string} a - Start hex color