reorder
This commit is contained in:
@@ -2305,8 +2305,22 @@
|
||||
|
||||
// --- HYDRATION_START ---
|
||||
const PRELOADED_IMAGES = [
|
||||
"_turntable/cg_7ec17537/views/20260628_054328_sc_dup_20260628_033600_dup_view_000_000deg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_053717_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_053620_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_053533_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_053337_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"20260628_053000_image.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_052745_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_052516_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_052422_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_052318_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_052216_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_052123_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_051801_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_050826_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_050349_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"20260628_045734_image.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_045628_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_044252_sc_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_043545_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_043148_pad_20260628_035257_dup_20260628_033600_dup_view_000_000deg.nobg.nobg.nobg.png",
|
||||
@@ -3477,8 +3491,8 @@
|
||||
"_turntable/cg_7ec17537/views/view_002_030deg.png",
|
||||
"_turntable/cg_7ec17537/views/view_001_015deg.png",
|
||||
"_turntable/cg_7ec17537/views/view_000_000deg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_033600_dup_view_000_000deg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_033831_dup_20260628_033600_dup_view_000_000deg.png",
|
||||
"_turntable/cg_7ec17537/views/20260628_033600_dup_view_000_000deg.png",
|
||||
"_turntable/up_154b502c/views/view_023_345deg.png",
|
||||
"_turntable/up_154b502c/views/view_022_330deg.png",
|
||||
"_turntable/up_154b502c/views/view_021_315deg.png",
|
||||
@@ -4133,8 +4147,8 @@
|
||||
"20260626_234431_crop_20260626_231655_sc_image.nobg.png",
|
||||
"20260626_231655_sc_image.nobg.png",
|
||||
"20260618_181600_image.png_face.png",
|
||||
"20260626_231655_sc_image.png",
|
||||
"20260626_234334_dup_20260626_231655_sc_image.png",
|
||||
"20260626_231655_sc_image.png",
|
||||
"20260626_231349_sc_image.png",
|
||||
"20260626_231127_image.png",
|
||||
"_turntable/up_624995c3/views/view_011_330deg.png",
|
||||
@@ -4932,8 +4946,8 @@
|
||||
"20260625_024438_dup_20260624_165109_0_20260622_091731_image.nobg.png",
|
||||
"20260625_023536_dup_20260624_165109_0_20260622_091731_image.nobg.png",
|
||||
"20260624_165109_0_20260622_091731_image.nobg.png",
|
||||
"20260624_165109_0_20260622_091731_image.png",
|
||||
"20260625_023536_dup_20260624_165109_0_20260622_091731_image.png",
|
||||
"20260624_165109_0_20260622_091731_image.png",
|
||||
"up_ab858b0a_face.png",
|
||||
"20260625_022332_dup_20260625_022250_sc_image.png",
|
||||
"20260625_022250_sc_image.png",
|
||||
@@ -5241,8 +5255,8 @@
|
||||
"20260624_152038_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_152027_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_143523_Screenshot_From_2026-06-17_07-41-27.nobg.png",
|
||||
"20260624_143523_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_151746_dup_20260624_143523_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_143523_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_151501_dup_20260624_143523_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_151439_dup_20260624_143523_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_151250_Screenshot_From_2026-06-17_07-41-27.nobg.png",
|
||||
@@ -5258,8 +5272,8 @@
|
||||
"20260624_143700_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_143647_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_143635_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_151613_dup_20260624_143523_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_144952_dup_20260624_143523_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_151613_dup_20260624_143523_Screenshot_From_2026-06-17_07-41-27.png",
|
||||
"20260624_143024_mr_image.png",
|
||||
"20260624_142959_mr_image.png",
|
||||
"20260624_142923_mr_image.png",
|
||||
@@ -6839,8 +6853,8 @@
|
||||
"t159zr-1.png",
|
||||
"kbk99v.png",
|
||||
"kk563t.png",
|
||||
"20260626_003137_dup_20260626_003125_dup_Pasted image (9).png",
|
||||
"Pasted image (9).png",
|
||||
"20260626_003137_dup_20260626_003125_dup_Pasted image (9).png",
|
||||
"Pasted image (4).png",
|
||||
"Pasted image (3).png",
|
||||
"Pasted image.png",
|
||||
@@ -10984,8 +10998,15 @@
|
||||
// Custom prompt field - positioned above poses and under wireframe
|
||||
html += `<div class="sb-label" style="display:flex;justify-content:space-between;align-items:center">
|
||||
<span>Custom prompt</span>
|
||||
<button class="sb-btn" id="sbRefineBtn" style="font-size:9px;padding:2px 6px;margin:0"
|
||||
onclick="refineSbPrompt()" title="AI prompt refinement">✨ Refine</button>
|
||||
<div style="display:flex;align-items:center;gap:4px">
|
||||
<select id="sbLoadPoseSelect" onchange="sbLoadPoseToCustomPrompt(this.value)"
|
||||
style="background:#111;border:1px solid #2a2a2a;border-radius:4px;color:#aaa;font-size:10px;padding:2px 4px;max-width:130px;cursor:pointer">
|
||||
<option value="">— Load pose —</option>
|
||||
${Object.keys(availablePoses).sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'})).map(name => `<option value="${escHtml(name)}">${escHtml(name)}</option>`).join('')}
|
||||
</select>
|
||||
<button class="sb-btn" id="sbRefineBtn" style="font-size:9px;padding:2px 6px;margin:0"
|
||||
onclick="refineSbPrompt()" title="AI prompt refinement">✨ Refine</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sb-prompt-wrap" style="position:relative;margin-bottom:10px">
|
||||
<textarea class="sb-input" id="sbGenPromptInput" rows="2" autocomplete="off"
|
||||
@@ -11035,6 +11056,7 @@
|
||||
<div style="display:flex;align-items:center;gap:6px;margin-bottom:3px">
|
||||
<span style="font-size:11px;color:#888;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${escHtml(name)}</span>
|
||||
<label style="font-size:10px;color:#777;display:flex;align-items:center;gap:3px;cursor:pointer"><input type="checkbox" class="sb-pose-beta" ${isBeta?'checked':''}>beta</label>
|
||||
<button class="sb-btn" style="padding:2px 8px;font-size:10px;background:#1e1b4b;color:#a5b4fc;border-color:#312e81" onclick="refinePosePrompt(this)" title="Refine pose prompt via LLM">✨ Refine</button>
|
||||
<button class="sb-btn" style="padding:2px 8px;font-size:10px" onclick="savePoseToServer(this)">Save</button>
|
||||
<button class="sb-btn danger" style="padding:2px 8px;font-size:10px" onclick="deletePoseFromServer(this)">Delete</button>
|
||||
</div>
|
||||
@@ -11446,6 +11468,63 @@
|
||||
}
|
||||
}
|
||||
|
||||
function sbLoadPoseToCustomPrompt(poseName) {
|
||||
if (!poseName) return;
|
||||
const el = document.getElementById('sbGenPromptInput');
|
||||
if (!el) return;
|
||||
const poseText = availablePoses[poseName]?.text ?? availablePoses[poseName];
|
||||
if (poseText) {
|
||||
el.value = String(poseText).trim();
|
||||
autoGrowPrompt(el);
|
||||
updateSbGenBtn();
|
||||
showToast(`Pose "${poseName}" loaded into custom prompt`, 'success');
|
||||
}
|
||||
// Reset dropdown select back to default
|
||||
const select = document.getElementById('sbLoadPoseSelect');
|
||||
if (select) select.value = "";
|
||||
}
|
||||
|
||||
async function refinePosePrompt(btn) {
|
||||
const box = btn.closest('.sb-pose-edit');
|
||||
if (!box) return;
|
||||
const name = box.dataset.pose;
|
||||
const textarea = box.querySelector('.sb-pose-text');
|
||||
if (!textarea) return;
|
||||
let prompt = textarea.value.trim();
|
||||
if (!prompt) {
|
||||
showToast('No prompt to refine.', 'info');
|
||||
return;
|
||||
}
|
||||
|
||||
const oldHtml = btn.innerHTML;
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<span class="sb-spinner" style="width:10px;height:10px;border-width:2px;margin:0"></span> Refining…';
|
||||
|
||||
try {
|
||||
const r = await fetch(`${API}/refine-prompt`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ prompt })
|
||||
});
|
||||
if (r.ok) {
|
||||
const { refined } = await r.json();
|
||||
textarea.value = refined;
|
||||
_sbPoseEdits[name] = refined;
|
||||
textarea.style.height = 'auto';
|
||||
textarea.style.height = textarea.scrollHeight + 'px';
|
||||
updateSbGenBtn();
|
||||
showToast(`Pose "${name}" refined`, 'success');
|
||||
} else {
|
||||
showToast('Refinement failed: ' + await r.text(), 'error');
|
||||
}
|
||||
} catch (e) {
|
||||
showToast('Refinement error: ' + e, 'error');
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = oldHtml;
|
||||
}
|
||||
}
|
||||
|
||||
async function submitSbGenerate() {
|
||||
if (!_fsModelFilename) return;
|
||||
const promptVal = (document.getElementById('sbGenPromptInput')?.value || '').trim();
|
||||
@@ -12146,7 +12225,18 @@
|
||||
const canGen = !!bgRef && !!person && person.kind === 'file'
|
||||
&& (!_sceneRefs[2] || _sceneRefs[2].kind === 'file');
|
||||
html += `<div class="sb-sep"></div>
|
||||
<div class="sb-label">Prompt (optional) <span style="color:#555;font-weight:400;font-size:9px">· history while typing</span></div>
|
||||
<div class="sb-label" style="display:flex;justify-content:space-between;align-items:center">
|
||||
<span>Prompt (optional) <span style="color:#555;font-weight:400;font-size:9px">· history</span></span>
|
||||
<div style="display:flex;align-items:center;gap:4px">
|
||||
<select id="sceneLoadPoseSelect" onchange="sceneLoadPoseToPrompt(this.value)"
|
||||
style="background:#111;border:1px solid #2a2a2a;border-radius:4px;color:#aaa;font-size:10px;padding:2px 4px;max-width:130px;cursor:pointer">
|
||||
<option value="">— Load pose —</option>
|
||||
${Object.keys(availablePoses).sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'})).map(name => `<option value="${escHtml(name)}">${escHtml(name)}</option>`).join('')}
|
||||
</select>
|
||||
<button class="sb-btn" id="sceneRefineBtn" style="font-size:9px;padding:2px 6px;margin:0"
|
||||
onclick="refineScenePrompt()" title="AI prompt refinement">✨ Refine</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sb-prompt-wrap" style="position:relative;margin-bottom:10px">
|
||||
<textarea class="sb-input" id="scenePromptInput" rows="2" autocomplete="off"
|
||||
placeholder="Auto: place person in scene… (type to search history)"
|
||||
@@ -12452,6 +12542,64 @@
|
||||
}
|
||||
}
|
||||
|
||||
function sceneLoadPoseToPrompt(poseName) {
|
||||
if (!poseName) return;
|
||||
const el = document.getElementById('scenePromptInput');
|
||||
if (!el) return;
|
||||
const poseText = availablePoses[poseName]?.text ?? availablePoses[poseName];
|
||||
if (poseText) {
|
||||
el.value = String(poseText).trim();
|
||||
autoGrowPrompt(el);
|
||||
showToast(`Pose "${poseName}" loaded into scenery prompt`, 'success');
|
||||
}
|
||||
// Reset dropdown select back to default
|
||||
const select = document.getElementById('sceneLoadPoseSelect');
|
||||
if (select) select.value = "";
|
||||
}
|
||||
|
||||
async function refineScenePrompt() {
|
||||
const el = document.getElementById('scenePromptInput');
|
||||
if (!el) return;
|
||||
let prompt = el.value.trim();
|
||||
if (!prompt) {
|
||||
// If empty, use current image's prompt if available
|
||||
if (lbIdx >= 0 && lbNames[lbIdx]) {
|
||||
const fn = lbNames[lbIdx];
|
||||
prompt = filePrompts[fn] || '';
|
||||
}
|
||||
}
|
||||
if (!prompt) {
|
||||
showToast('No prompt to refine. Enter one or select an image.', 'info');
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = document.getElementById('sceneRefineBtn');
|
||||
const oldHtml = btn.innerHTML;
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<span class="sb-spinner" style="width:10px;height:10px;border-width:2px;margin:0"></span> Refining…';
|
||||
|
||||
try {
|
||||
const r = await fetch(`${API}/refine-prompt`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ prompt })
|
||||
});
|
||||
if (r.ok) {
|
||||
const { refined } = await r.json();
|
||||
el.value = (el.value.trim() + "\n\n" + refined).trim();
|
||||
autoGrowPrompt(el);
|
||||
showToast('Prompt refined', 'success');
|
||||
} else {
|
||||
showToast('Refinement failed: ' + await r.text(), 'error');
|
||||
}
|
||||
} catch (e) {
|
||||
showToast('Refinement error: ' + e, 'error');
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = oldHtml;
|
||||
}
|
||||
}
|
||||
|
||||
async function submitGenerateScenery() {
|
||||
// Map positional slots → backend contract.
|
||||
const bg = _sceneRefs[0], person = _sceneRefs[1], extra = _sceneRefs[2];
|
||||
|
||||
Reference in New Issue
Block a user