/* ===== Generation Logic ===== */ window.NAIGenerate = { collectParams() { return { model: $('#model-select').value, prompt: $('#prompt-input').value.trim(), quality_prompt: $('#quality-input').value.trim(), negative_prompt: $('#negative-input').value.trim(), sampler: $('#sampler-select').value, cfg_scale: parseFloat($('#cfg-slider').value), steps: parseInt($('#steps-slider').value), seed: parseInt($('#seed-input').value) || -1, width: parseInt($('#width-slider').value), height: parseInt($('#height-slider').value), save_to_cloud: window.NAISettings ? NAISettings.get('saveToCloud') : ($('#save-to-cloud')?.checked ?? true), }; }, collectVibeParams() { const model = $('#model-select').value; const v4 = model.startsWith('nai-diffusion-4'); const strNorm = $('#vibe-str-normalize'); if (v4) { return { mode: 'v4', vibes: NAIState.vibeFiles.map(vf => { const ek = model.endsWith('full') ? 'v4full' : 'v4curated'; const encodings = vf.data.encodings?.[ek] || {}; const firstKey = Object.keys(encodings)[0]; const enc = firstKey ? encodings[firstKey] : null; return { encoding: enc?.encoding || '', info_extract: enc?.params?.information_extracted ?? 1, strength: vf.strength ?? 0.6, }; }).filter(v => v.encoding), normalize_strength: strNorm ? strNorm.checked : true, }; } return { mode: 'legacy', images: NAIState.vibeRefImages.map(ri => ({ b64: NAIUtils.dataUrlToBase64(ri.dataUrl), info_extract: ri.infoExtract, strength: ri.strength, })), normalize_strength: strNorm ? strNorm.checked : true, }; }, startGeneration() { const state = NAIState; if (state.generating || state.vibeEncoding || !state.wsReady) return; // Auto-convert unconverted ref images for v4 if (NAIVibe.isV4Model() && state.vibeRefImages.length > 0) { NAIVibe.startEncode(true); return; } this.doGenerate(); }, doGenerate() { if (NAIState.generating) return; NAIState.generating = true; const btn = $('#btn-generate'); btn.disabled = true; btn.classList.add('generating'); btn.textContent = '生成中...'; NAITimer.start(); const charParams = NAICharacter.collectParams(); const referenceParams = NAIReference.collectParams(); const advParams = NAIAdvanced.collectParams(); NAIWS.send({ action: 'generate', params: this.collectParams(), vibe: this.collectVibeParams(), extra_input: NAIExtraInput.collectParams(), character: charParams, reference: referenceParams, advanced: advParams, }); }, onResult(data) { NAIState.generating = false; const btn = $('#btn-generate'); btn.disabled = false; btn.classList.remove('generating'); btn.textContent = '生成'; NAIWS.updateStatus('生成完成 ✓', false); NAITimer.stop(true); // Refresh anlas after generation NAICost.fetchAnlas(); if (data.image) { const img_area = $('#result-image-area'); img_area.innerHTML = ``; const img = img_area.querySelector('img'); const badge = document.createElement('button'); badge.className = 'download-card-badge'; badge.textContent = '💾'; img_area.appendChild(badge); img.addEventListener('click', () => { if (document.fullscreenElement) { document.exitFullscreen(); } else { img.requestFullscreen(); } }); badge.addEventListener('click', () => { const link = document.createElement('a'); link.href = `data:image/png;base64,${data.image}`; link.download = `nai_image_${Date.now()}.png`; document.body.appendChild(link); link.click(); document.body.removeChild(link); }); } if (data.seed !== undefined) NAIState.lastSeed = data.seed; const params = this.collectParams(); // Save to history with searchable text if (data.image) { NAIHistory.saveWithSearch(data.image, 'generate', { ...params, seed: data.seed, }); } const rows = { Model: params.model, Seed: data.seed, Sampler: params.sampler, 'CFG Scale': params.cfg_scale, Steps: params.steps, Size: `${params.width}x${params.height}`, }; let html = ''; for (const [k, v] of Object.entries(rows)) { html += `
${k}:${v}
`; } $('#result-info-content').innerHTML = html; }, onError(message) { NAIState.generating = false; const btn = $('#btn-generate'); btn.disabled = false; btn.classList.remove('generating'); btn.textContent = '生成'; NAIWS.updateStatus(`错误: ${message}`, false); NAITimer.stop(false); }, };