memoscan
← all memos

Memo 0xf0402064…172204 on Ethereum

form); } svgDrawArtifactFrame(); } function svgDrawArtifactFrame() { if (!artifactFrame || !artifactFrameLayer) return; artifactFrameLayer.textContent = ""; const color = SIGNAL_RITUAL_ENGINE.visualRenderer.background === "#f7f7f2" ? "#08090b" : "#f3f0e8"; const corner = artifactFrame.borderGlyphs?.corner || "+"; const horizontal = artifactFrame.borderGlyphs?.horizontal || "-"; const vertical = artifactFrame.borderGlyphs?.vertical || "|"; function addText(text, column, row) { const node = document.createElementNS(svgNs, "text"); node.setAttribute("class", "cell"); node.setAttribute("x", column * cell + cell / 2); node.setAttribute("y", row * cell + cell / 2); node.setAttribute("font-size", Math.round(cell * 1.18)); node.setAttribute("font-weight", "700"); node.setAttribute("fill", color); node.setAttribute("opacity", "0.92"); node.textContent = text; artifactFrameLayer.appendChild(node); } svgDrawBorderLine(0, color, corner, horizontal, [ { text: artifactFrame.collectionName || "Signal Rituals", align: "left", max: Math.floor(artifactFrameColumns * 0.38) }, { text: artifactFrame.artworkName || "Untitled", align: "right", max: Math.floor(artifactFrameColumns * 0.48) }, ]); svgDrawBorderLine(artifactFrameRows - 1, color, corner, horizontal, [ { text: "Seed: " + (artifactFrame.seed || "-"), align: "right", max: Math.floor(artifactFrameColumns * 0.44) }, ]); for (let row = 1; row < artifactFrameRows - 1; row += 1) { addText(vertical, 0, row); addText(vertical, artifactFrameColumns - 1, row); } } function svgFrameText(text, maxLength) { text = String(text || "").replace(/[^\x20-\x7E]/g, "").replace(/\s+/g, " ").trim(); if (text.length <= maxLength) return text; return maxLength <= 3 ? text.slice(0, maxLength) : text.slice(0, maxLength - 3) + "..."; } function svgDrawBorderLine(row, color, corner, horizontal, segments = []) { const line = new Array(artifactFrameColumns).fill(horizontal); for (let column = 0; column < artifactFrameColumns; column += 1) { if (column === 0 || column === artifactFrameColumns - 1) line[column] = corner; } const occupied = new Array(artifactFrameColumns).fill(false); occupied[0] = true; occupied[artifactFrameColumns - 1] = true; for (const segment of segments) { const text = " " + svgFrameText(segment.text, Math.max(0, segment.max || artifactFrameColumns - 4)) + " "; let start = 2; if (segment.align === "center") start = Math.floor((artifactFrameColumns - text.length) / 2); if (segment.align === "right") start = artifactFrameColumns - text.length - 2; start = Math.max(1, Math.min(artifactFrameColumns - text.length - 1, start)); for (let index = 0; index < text.length; index += 1) { const column = start + index; if (column <= 0 || column >= artifactFrameColumns - 1 || occupied[column]) continue; line[column] = text[index]; occupied[column] = true; } } for (let column = 0; column < artifactFrameColumns; column += 1) { const node = document.createElementNS(svgNs, "text"); node.setAttribute("class", "cell"); node.setAttribute("x", column * cell + cell / 2); node.setAttribute("y", row * cell + cell / 2); node.setAttribute("font-size", Math.round(cell * 1.18)); node.setAttribute("font-weight", "700"); node.setAttribute("fill", color); node.setAttribute("opacity", "0.92"); node.textContent = line[column]; artifactFrameLayer.appendChild(node); } } function createCellNodes(parent, output) { for (let row = 0; row < rows; row += 1) { for (let column = 0; column < columns; column += 1) { output.push(svgCreateCellNode(parent, column, row)); } } } function svgCreateCellNode(parent, column, row) { const tuning = SIGNAL_RITUAL_ENGINE.visualRenderer.rendererTuning || {}; const glyphScale = tuning.glyphScale ?? 1.25; const text = document.createElementNS(svgNs, "text"); text.setAttribute("class", "cell"); text.setAttribute("x", column * cell + cell / 2); text.setAttribute("y", row * cell + cell / 2); text.setAttribute("font-size", Math.round(cell * glyphScale)); text.textContent = " "; parent.appendChild(text); return text; } function svgRowGlitchOffset(row, frame) { const effects = grEffectSettings(); const passes = grActiveGlitchPasses(frame); const fullWidth = columns * cell; const rowY = row * cell; let offset = 0; for (const pass of passes) { const seed = frame * 4099 + pass.index * 10007 + 101; const time = frame * (0.016 + pass.speed * 0.3); if (pass.index === 0) { const bandCount = Math.max(1, Math.round(3 + pass.strength * 14)); for (let band = 0; band < bandCount; band += 1) { const bandSeed = seed + band * 977; const y = Math.floor(grSmoothRandom(bandSeed, time * 0.82) * rows * cell); const bandHeight = Math.max(1, Math.floor((grSmoothRandom(bandSeed + 37, time * 0.45) * 10 + 2) * pass.strength)); if (rowY < y || rowY > y + bandHeight) continue; offset += Math.round((grSmoothRandom(bandSeed + 73, time) - 0.5) * fullWidth * 0.16 * pass.strength); } } else { const slices = pass.index === 1 ? 5 : 10; const sliceHeight = Math.max(1, Math.ceil(rows / slices)); const slice = Math.floor(row / sliceHeight); const sliceSeed = seed + slice * 557; const direction = grSmoothRandom(sliceSeed, time * 0.5) * 2 - 1; const travel = 0.025 + grSmoothRandom(sliceSeed + 89, time * 0.42) * (slices === 5 ? 0.18 : 0.26); offset += Math.round(direction * travel * fullWidth * pass.strength); } } const brokenRows = (effects.brokenRows || 0) / 100; const misregistration = (effects.misregistration || 0) / 100; if (brokenRows > 0 || misregistration > 0) { const tears = Math.round(1 + brokenRows * 10 + misregistration * 5); for (let i = 0; i < tears; i += 1) { const active = grSmoothRandom(i * 379 + 73, frame * 0.12) < brokenRows * 0.85 + misregistration * 0.35; if (!active) continue; const y = Math.floor(grSmoothRandom(i * 701 + 17, frame * 0.1) * rows); const bandHeight = Math.max(1, Math.round(1 + grSmoothRandom(i * 313 + 29, frame * 0.07) * (2 + brokenRows * 18))); if (row < y || row > y + bandHeight) continue; offset += Math.round((grSmoothRandom(i * 997 + 41, frame * 0.16) - 0.5) * fullWidth * (brokenRows * 0.14 + misregistration * 0.08)); } } return offset; } function svgComputeRowOffsets(frame) { for (let row = 0; row < rows; row += 1) rowOffsets[row] = svgRowGlitchOffset(row, frame); } function svgClearCell(node) { if (node._grText !== "") { node.textContent = ""; node._grText = ""; } node._grTone = 0; } function grToneAt(toneLines, column, row) { const line = toneLines[Math.max(0, Math.min(rows - 1, row))] || ""; return toneValueMap[line[Math.max(0, Math.min(columns - 1, column))] || "0"] ?? 0; } function grAdaptiveCellScale(toneLines, column, row) { const effects = grEffectSettings(); if (!effects.asciiAdaptiveSize) return 1; const blockColumn = column - (column % 2); const blockRow = row - (row % 2); const a = grToneAt(toneLines, blockColumn, blockRow); const b = grToneAt(toneLines, blockColumn + 1, blockRow); const c = grToneAt(toneLines, blockColumn, blockRow + 1); const d = grToneAt(toneLines, blockColumn + 1, blockRow + 1); const maxTone = Math.max(a, b, c, d); const minTone = Math.min(a, b, c, d); if (maxTone > 0.68) return 1; if (maxTone - minTone > 0.24) return 1; return Math.max(1, Math.min(1.18, 1 + ((effects.asciiLargeScale || 2) - 1) * 0.12)); } function grAdaptiveClearedNeighborCount(styleLines, column, row) { let clearedNeighbors = 0; for (let y = row - 1; y <= row + 1; y += 1) { const line = styleLines[Math.max(0, Math.min(rows - 1, y))] || ""; for (let x = column - 1; x <= column + 1; x += 1) { if (x === column && y === row) continue; if ((line[Math.max(0, Math.min(columns - 1, x))] || "0") === "1") clearedNeighbors += 1; } } return clearedNeighbors; } function grRecoveredAdaptiveDenseAnchor(styleLines, column, row, style) { return grIsDenseHighlightStyle(style) && grAdaptiveClearedNeighborCount(styleLines, column, row) >= 2; } function grStoredAnchorScale(styleLines, column, row, style) { const canBeAdaptiveAnchor = style === "2" || style === "3" || grIsDenseHighlightStyle(style); if (!canBeAdaptiveAnchor) return 1; const clearedNeighbors = grAdaptiveClearedNeighborCount(styleLines, column, row); if (style !== "2" && clearedNeighbors < 2) return 1; const tuning = SIGNAL_RITUAL_ENGINE.visualRenderer.rendererTuning || {}; return Math.min(3, Math.max(1.35, (grEffectSettings().asciiLargeScale || 2) * (tuning.largeAnchorScaleMultiplier ?? 0.95))); } function grIsAdaptiveAnchorStyle(style) { return style === "2" || style === "3" || style === "4" || grIsDenseHighlightStyle(style) || grIsEdgeStyle(style); } function grAdaptiveBlockSpec(styleLines, column, row, style) { const effects = grEffectSettings(); if (!effects.asciiAdaptiveSize || !grIsAdaptiveAnchorStyle(style)) return null; const maxBlockSize = Math.max(2, Math.min(4, Math.round(effects.asciiLargeScale || 2))); for (let blockSize = maxBlockSize; blockSize >= 2; blockSize -= 1) { const startColumn = column - Math.floor(blockSize / 2); const startRow = row - Math.floor(blockSize / 2); const endColumn = startColumn + blockSize; const endRow = startRow + blockSize; if (startColumn < 0 || startRow < 0 || endColumn > columns || endRow > rows) continue; let helperCells = 0; let valid = true; for (let y = startRow; y < endRow && valid; y += 1) { const line = styleLines[y] || ""; for (let x = startColumn; x < endColumn; x += 1) { if (x === column && y === row) continue; if ((line[x] || "0") !== "1") { valid = false; break; } helperCells += 1; } } if (!valid || helperCells === 0) continue; const blockCenterX = (startColumn + blockSize / 2) * cell; const blockCenterY = (startRow + blockSize / 2) * cell; const anchorCenterX = (column + 0.5) * cell; const anchorCenterY = (row + 0.5) * cell; return { scale: blockSize, offsetX: blockCenterX - anchorCenterX, offsetY: blockCenterY - anchorCenterY, recoveredDenseAnchor: grIsDenseHighlightStyle(style), }; } return null; } function grAdaptiveAnchorOffset(styleLines, column, row, style) { const canBeAdaptiveAnchor = style === "2" || style === "3" || grIsDenseHighlightStyle(style); if (!canBeAdaptiveAnchor) return [0, 0]; let minX = 0; let maxX = 0; let minY = 0; let maxY = 0; let hasClear = false; for (let y = row - 1; y <= row + 1; y += 1) { const line = styleLines[Math.max(0, Math.min(rows - 1, y))] || ""; for (let x = column - 1; x <= column + 1; x += 1) { if ((line[Math.max(0, Math.min(columns - 1, x))] || "0") !== "1") continue; const dx = x - column; const dy = y - row; minX = Math.min(minX, dx); maxX = Math.max(maxX, dx); minY = Math.min(minY, dy); maxY = Math.max(maxY, dy); hasClear = true; } } if (!hasClear) return [0, 0]; return [((minX + maxX) / 2) * cell, ((minY + maxY) / 2) * cell]; } function grShouldGlowCell(tone, style, highlightFill, column, row, frame) { if (!RENDER_GLOW_ENABLED) return false; const isLargeAnchor = style === "2"; const isHighlightMark = style === "3"; const isHeavyInk = style === "4" || grIsDenseHighlightStyle(style); const highlightThreshold = (grEffectSettings().asciiHighlightThreshold || 65) / 100; const glowToneFloor = Math.max(0.42, highlightThreshold - 0.24); const eligible = isLargeAnchor || isHighlightMark || isHeavyInk || highlightFill > 0.08 || tone >= glowToneFloor; if (!eligible) return false; const strong = Math