diff --git a/index.html b/index.html index bb9960e..392040a 100644 --- a/index.html +++ b/index.html @@ -233,6 +233,9 @@

Actions

+ diff --git a/sketch.js b/sketch.js index 34955f7..26b31eb 100644 --- a/sketch.js +++ b/sketch.js @@ -90,7 +90,13 @@ function init() { if (resetButton) { resetButton.addEventListener('click', resetAllParameters); } - + + // Bouton de randomize + const randomizeButton = document.getElementById("randomizeButton"); + if (randomizeButton) { + randomizeButton.addEventListener("click", randomizeAllParameters); + } + // Démarrer le rendu une fois le shader chargé startRender(); }).catch(error => { @@ -517,6 +523,305 @@ const defaultParams = { exportResolution: 4096 }; +// Randomiser tous les paramètres +function randomizeAllParameters() { + // Générer des valeurs aléatoires pour chaque paramètre (sauf COLOR et EFFECTS sections) + shaderParams.scale = Math.random() * 21; // 0-20 + shaderParams.phaseX = Math.random() * 2; // 0-2 + shaderParams.velocity = Math.random() * 5; // 0-5 + shaderParams.mode1Detail = Math.floor(Math.random() * 991 + 10); // 10-1000 + shaderParams.mode1Twist = Math.floor(Math.random() * 101); // 0-100 + shaderParams.mode2Speed = Math.random() * 10; // 0-10 + shaderParams.movementMode = Math.floor(Math.random() * 8); // 0-7 + + // Mettre à jour tous les sliders + const scaleSlider = document.getElementById("scale"); + if (scaleSlider) { + scaleSlider.value = shaderParams.scale; + document.getElementById("scaleValue").textContent = shaderParams.scale.toFixed(2); + } + + const phaseXSlider = document.getElementById("phaseX"); + if (phaseXSlider) { + phaseXSlider.value = shaderParams.phaseX; + document.getElementById("phaseXValue").textContent = shaderParams.phaseX.toFixed(2); + } + + const velocityYSlider = document.getElementById("velocityY"); + if (velocityYSlider) { + velocityYSlider.value = shaderParams.velocity; + document.getElementById("velocityYValue").textContent = shaderParams.velocity.toFixed(2); + } + + const mode1DetailSlider = document.getElementById("mode1Detail"); + if (mode1DetailSlider) { + mode1DetailSlider.value = shaderParams.mode1Detail; + document.getElementById("mode1DetailValue").textContent = shaderParams.mode1Detail.toFixed(2); + } + + const mode1TwistSlider = document.getElementById("mode1Twist"); + if (mode1TwistSlider) { + mode1TwistSlider.value = shaderParams.mode1Twist; + document.getElementById("mode1TwistValue").textContent = shaderParams.mode1Twist.toFixed(2); + } + + const mode2SpeedSlider = document.getElementById("mode2Speed"); + if (mode2SpeedSlider) { + mode2SpeedSlider.value = shaderParams.mode2Speed; + document.getElementById("mode2SpeedValue").textContent = shaderParams.mode2Speed.toFixed(2); + } + + const movementModeSelect = document.getElementById("movementMode"); + if (movementModeSelect) { + movementModeSelect.value = shaderParams.movementMode.toString(); + } + + // Randomiser les couleurs du gradient (2-6 couleurs) + const gradientContainer = document.getElementById("gradientColorsContainer"); + if (gradientContainer) { + const numColors = Math.floor(Math.random() * 5) + 2; // 2-6 colors + const colors = []; + + // Supprimer tous les champs existants + gradientContainer.innerHTML = ""; + + // Variable partagée pour le drag & drop + let draggedElement = null; + + // Fonction helper pour mettre à jour les couleurs + const updateGradientColors = () => { + const inputs = gradientContainer.querySelectorAll(".hex-color-input"); + const newColors = []; + + inputs.forEach((input) => { + const hex = input.value.trim(); + if (hex.length === 7 && /^#[0-9A-Fa-f]{6}$/.test(hex)) { + const rgb = hexToRgb(hex); + if (rgb) { + newColors.push(rgb); + } + } + }); + + shaderParams.gradientColors = newColors; + updateShaderParams(); + }; + + // Fonction helper pour ajouter un nouveau champ + const addGradientColorInput = () => { + const group = document.createElement("div"); + group.className = "color-input-group"; + group.draggable = true; + + const input = document.createElement("input"); + input.type = "text"; + input.className = "hex-color-input"; + input.placeholder = "#000000"; + input.maxLength = 7; + input.pattern = "#[0-9A-Fa-f]{6}"; + + input.addEventListener("mousedown", (e) => { + e.stopPropagation(); + }); + + const preview = document.createElement("div"); + preview.className = "color-preview"; + + const colorPicker = document.createElement("input"); + colorPicker.type = "color"; + colorPicker.style.position = "absolute"; + colorPicker.style.opacity = "0"; + colorPicker.style.width = "0"; + colorPicker.style.height = "0"; + colorPicker.style.pointerEvents = "none"; + + preview.addEventListener("dblclick", (e) => { + e.preventDefault(); + e.stopPropagation(); + const currentHex = input.value; + if (currentHex && /^#[0-9A-Fa-f]{6}$/.test(currentHex)) { + colorPicker.value = currentHex; + } else { + colorPicker.value = "#000000"; + } + colorPicker.click(); + }); + + colorPicker.addEventListener("input", (e) => { + const hex = e.target.value.toUpperCase(); + input.value = hex; + input.dispatchEvent(new Event("input", {bubbles: true})); + }); + + if (!document.getElementById("hiddenColorPickers")) { + const hiddenContainer = document.createElement("div"); + hiddenContainer.id = "hiddenColorPickers"; + hiddenContainer.style.position = "absolute"; + hiddenContainer.style.top = "-9999px"; + hiddenContainer.style.left = "-9999px"; + document.body.appendChild(hiddenContainer); + } + document.getElementById("hiddenColorPickers").appendChild(colorPicker); + + // Drag & Drop handlers + group.addEventListener("dragstart", (e) => { + draggedElement = group; + group.style.opacity = "0.5"; + e.dataTransfer.effectAllowed = "move"; + e.dataTransfer.setData("text/html", group.innerHTML); + }); + + group.addEventListener("dragend", (e) => { + group.style.opacity = ""; + draggedElement = null; + gradientContainer.querySelectorAll(".color-input-group").forEach((g) => { + g.classList.remove("drag-over"); + }); + }); + + group.addEventListener("dragover", (e) => { + e.preventDefault(); + e.dataTransfer.dropEffect = "move"; + + if (draggedElement && draggedElement !== group) { + const allGroups = Array.from(gradientContainer.querySelectorAll(".color-input-group")); + const draggedIndex = allGroups.indexOf(draggedElement); + const currentIndex = allGroups.indexOf(group); + + allGroups.forEach((g) => g.classList.remove("drag-over")); + + if (draggedIndex !== currentIndex) { + group.classList.add("drag-over"); + } + } + }); + + group.addEventListener("dragleave", (e) => { + if (!group.contains(e.relatedTarget)) { + group.classList.remove("drag-over"); + } + }); + + group.addEventListener("drop", (e) => { + e.preventDefault(); + group.classList.remove("drag-over"); + + if (draggedElement && draggedElement !== group) { + const allGroups = Array.from(gradientContainer.querySelectorAll(".color-input-group")); + const draggedIndex = allGroups.indexOf(draggedElement); + const currentIndex = allGroups.indexOf(group); + + if (draggedIndex !== currentIndex) { + if (draggedIndex < currentIndex) { + gradientContainer.insertBefore(draggedElement, group.nextSibling); + } else { + gradientContainer.insertBefore(draggedElement, group); + } + updateGradientColors(); + } + } + draggedElement = null; + }); + + // Input event handler + input.addEventListener("input", (e) => { + const hex = e.target.value; + if (hex.length === 7 && /^#[0-9A-Fa-f]{6}$/.test(hex)) { + preview.style.backgroundColor = hex; + preview.classList.add("has-color"); + + const allGroups = gradientContainer.querySelectorAll(".color-input-group"); + if (group === allGroups[allGroups.length - 1]) { + addGradientColorInput(); + } + + updateGradientColors(); + } else { + preview.style.backgroundColor = ""; + preview.classList.remove("has-color"); + updateGradientColors(); + } + }); + + // Blur handler + input.addEventListener("blur", () => { + const allGroups = gradientContainer.querySelectorAll(".color-input-group"); + if (allGroups.length > 1 && !input.value) { + const inputs = gradientContainer.querySelectorAll(".hex-color-input"); + const hasValue = Array.from(inputs).some((inp) => inp.value && inp !== input); + if (hasValue) { + group.remove(); + updateGradientColors(); + } + } + }); + + // Delete button + const deleteBtn = document.createElement("button"); + deleteBtn.className = "color-delete-btn"; + deleteBtn.innerHTML = "×"; + deleteBtn.type = "button"; + deleteBtn.title = "Supprimer cette couleur"; + deleteBtn.addEventListener("click", (e) => { + e.preventDefault(); + e.stopPropagation(); + const allGroups = gradientContainer.querySelectorAll(".color-input-group"); + if (allGroups.length > 1) { + group.remove(); + updateGradientColors(); + } + }); + + group.appendChild(input); + group.appendChild(preview); + group.appendChild(deleteBtn); + gradientContainer.appendChild(group); + + return {group, input, preview}; + }; + + // Créer les champs de couleur avec les valeurs aléatoires + for (let i = 0; i < numColors; i++) { + const r = Math.floor(Math.random() * 256); + const g = Math.floor(Math.random() * 256); + const b = Math.floor(Math.random() * 256); + const hex = + "#" + + [r, g, b] + .map((x) => { + const hex = x.toString(16); + return hex.length === 1 ? "0" + hex : hex; + }) + .join(""); + + colors.push([r / 255.0, g / 255.0, b / 255.0]); + + // Créer le groupe avec tous les handlers + const {input, preview} = addGradientColorInput(); + input.value = hex; + preview.style.backgroundColor = hex; + preview.classList.add("has-color"); + } + + // Ajouter un champ vide à la fin pour permettre d'ajouter plus de couleurs + addGradientColorInput(); + + // Mettre à jour directement les couleurs du gradient + shaderParams.gradientColors = colors; + updateGradientColors(); + } + + // Recharger le shader pour appliquer les nouveaux paramètres + loadShaders() + .then(() => { + console.log("Paramètres randomisés"); + updateShaderParams(); + }) + .catch((error) => { + console.error("Erreur lors de la randomisation:", error); + }); +} + // Réinitialiser tous les paramètres function resetAllParameters() { // Restaurer les valeurs par défaut @@ -2449,4 +2754,3 @@ function renderPass(program, targetFramebuffer, textures, writeTexture = null) { // Démarrer l'application init(); - diff --git a/styles.css b/styles.css index 991cc8d..09e4664 100644 --- a/styles.css +++ b/styles.css @@ -243,6 +243,34 @@ body { box-shadow: none; } +.randomize-button { + width: 100%; + padding: 8px 12px; + background: var(--bg-tertiary); + border: 1px solid var(--border); + border-radius: 4px; + color: var(--text-primary); + font-size: 11px; + font-weight: 600; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + transition: all 0.2s ease; + margin-top: 8px; + font-family: 'BergenMono', monospace; +} + +.randomize-button:hover { + background: var(--bg-hover); + border-color: var(--accent); +} + +.randomize-button:active { + transform: translateY(0); +} + .reset-button { width: 100%; padding: 8px 12px;