Spaces:
Running on Zero
Running on Zero
update app [cleaned] ✅
#2
by prithivMLmods - opened
app.py
CHANGED
|
@@ -114,7 +114,6 @@ def infer_bbox_task(
|
|
| 114 |
global loaded_adapters, current_adapter
|
| 115 |
progress = gr.Progress(track_tqdm=True)
|
| 116 |
|
| 117 |
-
# --- Prompt validation ---
|
| 118 |
if not prompt or prompt.strip() == "":
|
| 119 |
raise gr.Error("⚠ Prompt cannot be empty. Please enter a prompt describing the edit you want.")
|
| 120 |
|
|
@@ -136,7 +135,6 @@ def infer_bbox_task(
|
|
| 136 |
if not boxes:
|
| 137 |
raise gr.Error("Please draw at least one bounding box on the image.")
|
| 138 |
|
| 139 |
-
# --- Object-Mover: exactly 2 boxes ---
|
| 140 |
if adapter_choice == "Object-Mover":
|
| 141 |
if len(boxes) != 2:
|
| 142 |
raise gr.Error(
|
|
@@ -249,9 +247,11 @@ footer{display:none!important}
|
|
| 249 |
font-size:13px;
|
| 250 |
line-height:1.5;
|
| 251 |
color:#e4e4e7;
|
|
|
|
|
|
|
| 252 |
backdrop-filter:blur(16px);
|
| 253 |
box-shadow:0 8px 32px rgba(0,0,0,.5),
|
| 254 |
-
0 0 0 1px rgba(255,
|
| 255 |
animation:toastSlideIn .35s cubic-bezier(.21,1.02,.73,1) forwards;
|
| 256 |
transform:translateX(120%);
|
| 257 |
opacity:0;
|
|
@@ -268,31 +268,32 @@ footer{display:none!important}
|
|
| 268 |
to{transform:translateX(120%);opacity:0}
|
| 269 |
}
|
| 270 |
.toast-warning{
|
| 271 |
-
background:rgba(30,
|
| 272 |
-
border-left:4px solid #
|
| 273 |
}
|
| 274 |
.toast-error{
|
| 275 |
-
background:rgba(30,15,
|
| 276 |
-
border-left:4px solid #
|
| 277 |
}
|
| 278 |
.toast-success{
|
| 279 |
-
background:rgba(
|
| 280 |
-
border-left:4px solid #
|
| 281 |
}
|
| 282 |
.toast-info{
|
| 283 |
-
background:rgba(
|
| 284 |
-
border-left:4px solid #
|
| 285 |
}
|
| 286 |
.toast-icon{
|
| 287 |
font-size:18px;
|
| 288 |
line-height:1;
|
| 289 |
flex-shrink:0;
|
| 290 |
margin-top:1px;
|
|
|
|
| 291 |
}
|
| 292 |
-
.toast-warning .toast-icon{color:#
|
| 293 |
-
.toast-error .toast-icon{color:#
|
| 294 |
-
.toast-success .toast-icon{color:#
|
| 295 |
-
.toast-info .toast-icon{color:#
|
| 296 |
.toast-body{
|
| 297 |
display:flex;
|
| 298 |
flex-direction:column;
|
|
@@ -303,11 +304,12 @@ footer{display:none!important}
|
|
| 303 |
.toast-title{
|
| 304 |
font-weight:700;
|
| 305 |
font-size:13px;
|
|
|
|
| 306 |
}
|
| 307 |
-
.toast-warning .toast-title{color:#
|
| 308 |
-
.toast-error .toast-title{color:#
|
| 309 |
-
.toast-success .toast-title{color:#
|
| 310 |
-
.toast-info .toast-title{color:#
|
| 311 |
.toast-msg{
|
| 312 |
font-size:12.5px;
|
| 313 |
color:#a1a1aa;
|
|
@@ -324,7 +326,7 @@ footer{display:none!important}
|
|
| 324 |
padding:0 0 0 4px;
|
| 325 |
transition:color .15s;
|
| 326 |
}
|
| 327 |
-
.toast-close:hover{color:#
|
| 328 |
|
| 329 |
/* ── Main Container ── */
|
| 330 |
.app-shell{
|
|
@@ -519,13 +521,13 @@ footer{display:none!important}
|
|
| 519 |
#bbox-count{
|
| 520 |
position:absolute;top:12px;right:12px;
|
| 521 |
background:rgba(24,24,27,.9);
|
| 522 |
-
color:#
|
| 523 |
padding:4px 12px;
|
| 524 |
font-family:'JetBrains Mono',monospace;
|
| 525 |
font-size:12px;
|
| 526 |
font-weight:600;
|
| 527 |
border-radius:6px;
|
| 528 |
-
border:1px solid rgba(255,
|
| 529 |
z-index:10;display:none;
|
| 530 |
backdrop-filter:blur(8px);
|
| 531 |
}
|
|
@@ -535,13 +537,13 @@ footer{display:none!important}
|
|
| 535 |
position:absolute;bottom:12px;left:50%;
|
| 536 |
transform:translateX(-50%);
|
| 537 |
background:rgba(24,24,27,.92);
|
| 538 |
-
color:#
|
| 539 |
padding:6px 16px;
|
| 540 |
font-family:'JetBrains Mono',monospace;
|
| 541 |
font-size:12px;
|
| 542 |
font-weight:600;
|
| 543 |
border-radius:8px;
|
| 544 |
-
border:1px solid rgba(
|
| 545 |
z-index:10;display:none;
|
| 546 |
pointer-events:none;
|
| 547 |
backdrop-filter:blur(8px);
|
|
@@ -604,12 +606,12 @@ footer{display:none!important}
|
|
| 604 |
.hint-bar .hint-mover-tag{
|
| 605 |
display:inline-block;
|
| 606 |
padding:1px 8px;
|
| 607 |
-
background:rgba(
|
| 608 |
-
border:1px solid rgba(
|
| 609 |
border-radius:4px;
|
| 610 |
font-size:11px;
|
| 611 |
font-weight:600;
|
| 612 |
-
color:#
|
| 613 |
}
|
| 614 |
|
| 615 |
/* ── JSON Panel ── */
|
|
@@ -709,8 +711,8 @@ footer{display:none!important}
|
|
| 709 |
}
|
| 710 |
.modern-textarea::placeholder{color:#3f3f46}
|
| 711 |
.modern-textarea.prompt-error{
|
| 712 |
-
border-color:#
|
| 713 |
-
box-shadow:0 0 0 3px rgba(
|
| 714 |
animation:promptShake .4s ease;
|
| 715 |
}
|
| 716 |
@keyframes promptShake{
|
|
@@ -798,15 +800,15 @@ footer{display:none!important}
|
|
| 798 |
}
|
| 799 |
|
| 800 |
.btn-run.mover-mode{
|
| 801 |
-
background:linear-gradient(135deg,#
|
| 802 |
-
box-shadow:0 4px 16px rgba(
|
| 803 |
inset 0 1px 0 rgba(255,255,255,.1)!important;
|
| 804 |
color:#ffffff!important;
|
| 805 |
-webkit-text-fill-color:#ffffff!important;
|
| 806 |
}
|
| 807 |
.btn-run.mover-mode:hover{
|
| 808 |
-
background:linear-gradient(135deg,#
|
| 809 |
-
box-shadow:0 6px 24px rgba(
|
| 810 |
inset 0 1px 0 rgba(255,255,255,.15)!important;
|
| 811 |
color:#ffffff!important;
|
| 812 |
-webkit-text-fill-color:#ffffff!important;
|
|
@@ -1108,10 +1110,6 @@ footer{display:none!important}
|
|
| 1108 |
font-family:'JetBrains Mono',monospace;
|
| 1109 |
font-size:12px;
|
| 1110 |
}
|
| 1111 |
-
.app-statusbar .sb-mode.sb-mode-mover{
|
| 1112 |
-
background:rgba(245,158,11,.12);
|
| 1113 |
-
color:#F59E0B;
|
| 1114 |
-
}
|
| 1115 |
|
| 1116 |
#gradio-run-btn{
|
| 1117 |
position:absolute;
|
|
@@ -1306,9 +1304,9 @@ function initCanvasBbox() {
|
|
| 1306 |
};
|
| 1307 |
|
| 1308 |
const HINT_TEXTS = {
|
| 1309 |
-
'Object-Remover': '<b>Draw:</b> Click & drag to create selection boxes
|
| 1310 |
-
'Design-Adder': '<b>Draw:</b> Click & drag to create selection boxes
|
| 1311 |
-
'Object-Mover': '<span class="hint-mover-tag">MOVER</span>
|
| 1312 |
};
|
| 1313 |
|
| 1314 |
/* ── Toast System ── */
|
|
@@ -1434,13 +1432,13 @@ function initCanvasBbox() {
|
|
| 1434 |
moverHint.style.display = 'block';
|
| 1435 |
if (boxes.length === 0) {
|
| 1436 |
moverHint.textContent = '\u25a0 Draw Box 1: Select the SOURCE object';
|
| 1437 |
-
moverHint.style.color = '#
|
| 1438 |
} else if (boxes.length === 1) {
|
| 1439 |
moverHint.textContent = '\u25a1 Draw Box 2: Mark the TARGET location';
|
| 1440 |
-
moverHint.style.color = '#
|
| 1441 |
} else {
|
| 1442 |
moverHint.textContent = '\u2714 Both boxes ready \u2014 Source + Target defined';
|
| 1443 |
-
moverHint.style.color = '#
|
| 1444 |
}
|
| 1445 |
}
|
| 1446 |
|
|
@@ -1470,19 +1468,19 @@ function initCanvasBbox() {
|
|
| 1470 |
if (promptInput) promptInput.value = DEFAULT_PROMPTS['Object-Remover'];
|
| 1471 |
if (runBtnEl) { runBtnEl.classList.remove('design-mode','mover-mode'); }
|
| 1472 |
if (runBtnLabel) runBtnLabel.textContent = 'Remove Object';
|
| 1473 |
-
if (statusMode)
|
| 1474 |
} else if (taskMode === 'Design-Adder') {
|
| 1475 |
if (modeDesigner) modeDesigner.classList.add('active');
|
| 1476 |
if (promptInput) promptInput.value = DEFAULT_PROMPTS['Design-Adder'];
|
| 1477 |
if (runBtnEl) { runBtnEl.classList.remove('mover-mode'); runBtnEl.classList.add('design-mode'); }
|
| 1478 |
if (runBtnLabel) runBtnLabel.textContent = 'Add Design';
|
| 1479 |
-
if (statusMode)
|
| 1480 |
} else if (taskMode === 'Object-Mover') {
|
| 1481 |
if (modeMover) modeMover.classList.add('active');
|
| 1482 |
if (promptInput) promptInput.value = DEFAULT_PROMPTS['Object-Mover'];
|
| 1483 |
if (runBtnEl) { runBtnEl.classList.remove('design-mode'); runBtnEl.classList.add('mover-mode'); }
|
| 1484 |
if (runBtnLabel) runBtnLabel.textContent = 'Move Object';
|
| 1485 |
-
if (statusMode)
|
| 1486 |
if (boxes.length > 2) {
|
| 1487 |
window.showToast(
|
| 1488 |
'Object Mover requires exactly 2 boxes (Source + Target). You have ' + boxes.length + ' boxes. Please clear extra boxes before running.',
|
|
@@ -1518,13 +1516,6 @@ function initCanvasBbox() {
|
|
| 1518 |
return '#'+(index+1);
|
| 1519 |
}
|
| 1520 |
|
| 1521 |
-
function getBoxLabelColor(index) {
|
| 1522 |
-
if (window.__currentTaskMode === 'Object-Mover') {
|
| 1523 |
-
return index === 0 ? '#F59E0B' : '#3B82F6';
|
| 1524 |
-
}
|
| 1525 |
-
return '#FF0000';
|
| 1526 |
-
}
|
| 1527 |
-
|
| 1528 |
function redraw(tempRect) {
|
| 1529 |
ctx.clearRect(0,0,dispW,dispH);
|
| 1530 |
if (!baseImg) {
|
|
@@ -1536,7 +1527,6 @@ function initCanvasBbox() {
|
|
| 1536 |
boxes.forEach((b,i) => {
|
| 1537 |
const p = n2px(b);
|
| 1538 |
const lx=p.x1, ty=p.y1, w=p.x2-p.x1, h=p.y2-p.y1;
|
| 1539 |
-
const boxColor = getBoxLabelColor(i);
|
| 1540 |
if (i === selectedIdx) {
|
| 1541 |
ctx.strokeStyle = SEL_STROKE;
|
| 1542 |
ctx.lineWidth = RED_STROKE_WIDTH + 1;
|
|
@@ -1550,8 +1540,7 @@ function initCanvasBbox() {
|
|
| 1550 |
ctx.setLineDash([]);
|
| 1551 |
|
| 1552 |
const label = getBoxLabel(i);
|
| 1553 |
-
|
| 1554 |
-
ctx.fillStyle = labelBg;
|
| 1555 |
ctx.font = 'bold 11px Inter,system-ui,sans-serif';
|
| 1556 |
ctx.textAlign = 'left'; ctx.textBaseline = 'top';
|
| 1557 |
const tw = ctx.measureText(label).width;
|
|
@@ -1627,18 +1616,16 @@ function initCanvasBbox() {
|
|
| 1627 |
}
|
| 1628 |
|
| 1629 |
function updateBadge() {
|
| 1630 |
-
const isMover = window.__currentTaskMode === 'Object-Mover';
|
| 1631 |
if (boxes.length > 0) {
|
| 1632 |
badge.style.display = 'block';
|
|
|
|
| 1633 |
if (isMover) {
|
| 1634 |
badge.textContent = boxes.length + '/2 box' + (boxes.length>1?'es':'');
|
| 1635 |
-
badge.style.color = boxes.length === 2 ? '#22C55E' : '#F59E0B';
|
| 1636 |
-
badge.style.borderColor = boxes.length === 2 ? 'rgba(34,197,94,.3)' : 'rgba(245,158,11,.3)';
|
| 1637 |
} else {
|
| 1638 |
badge.textContent = boxes.length + ' box' + (boxes.length>1?'es':'');
|
| 1639 |
-
badge.style.color = '#FF0000';
|
| 1640 |
-
badge.style.borderColor = 'rgba(255,0,0,.3)';
|
| 1641 |
}
|
|
|
|
|
|
|
| 1642 |
} else {
|
| 1643 |
badge.style.display = 'none';
|
| 1644 |
}
|
|
@@ -1681,7 +1668,6 @@ function initCanvasBbox() {
|
|
| 1681 |
e.preventDefault();
|
| 1682 |
const {x, y} = canvasXY(e);
|
| 1683 |
if (mode === 'draw') {
|
| 1684 |
-
/* Enforce 2-box limit for Object-Mover before starting the drag */
|
| 1685 |
if (window.__currentTaskMode === 'Object-Mover' && boxes.length >= 2) {
|
| 1686 |
window.showToast(
|
| 1687 |
'Object Mover allows exactly <b>2 boxes</b> (Source + Target). Clear existing boxes to redraw.',
|
|
@@ -1974,13 +1960,11 @@ function initCanvasBbox() {
|
|
| 1974 |
const pInput = document.getElementById('custom-prompt-input');
|
| 1975 |
const promptVal = pInput ? pInput.value.trim() : '';
|
| 1976 |
|
| 1977 |
-
/* ── Validation: Image ── */
|
| 1978 |
if (!baseImg) {
|
| 1979 |
window.showToast('Please upload an image first before processing.', 'error', 'No Image');
|
| 1980 |
return;
|
| 1981 |
}
|
| 1982 |
|
| 1983 |
-
/* ── Validation: Prompt ── */
|
| 1984 |
if (!promptVal) {
|
| 1985 |
window.showToast('Prompt cannot be empty. Please describe the edit you want to perform.', 'warning', 'Empty Prompt');
|
| 1986 |
if (pInput) {
|
|
@@ -1991,13 +1975,11 @@ function initCanvasBbox() {
|
|
| 1991 |
return;
|
| 1992 |
}
|
| 1993 |
|
| 1994 |
-
/* ── Validation: Boxes ── */
|
| 1995 |
if (boxes.length === 0) {
|
| 1996 |
window.showToast('Please draw at least one bounding box on the image.', 'warning', 'No Boxes');
|
| 1997 |
return;
|
| 1998 |
}
|
| 1999 |
|
| 2000 |
-
/* ── Validation: Object-Mover requires exactly 2 boxes ── */
|
| 2001 |
if (window.__currentTaskMode === 'Object-Mover') {
|
| 2002 |
if (boxes.length < 2) {
|
| 2003 |
window.showToast(
|
|
|
|
| 114 |
global loaded_adapters, current_adapter
|
| 115 |
progress = gr.Progress(track_tqdm=True)
|
| 116 |
|
|
|
|
| 117 |
if not prompt or prompt.strip() == "":
|
| 118 |
raise gr.Error("⚠ Prompt cannot be empty. Please enter a prompt describing the edit you want.")
|
| 119 |
|
|
|
|
| 135 |
if not boxes:
|
| 136 |
raise gr.Error("Please draw at least one bounding box on the image.")
|
| 137 |
|
|
|
|
| 138 |
if adapter_choice == "Object-Mover":
|
| 139 |
if len(boxes) != 2:
|
| 140 |
raise gr.Error(
|
|
|
|
| 247 |
font-size:13px;
|
| 248 |
line-height:1.5;
|
| 249 |
color:#e4e4e7;
|
| 250 |
+
background:rgba(30,18,28,.95);
|
| 251 |
+
border-left:4px solid #FF1493;
|
| 252 |
backdrop-filter:blur(16px);
|
| 253 |
box-shadow:0 8px 32px rgba(0,0,0,.5),
|
| 254 |
+
0 0 0 1px rgba(255,20,147,.1);
|
| 255 |
animation:toastSlideIn .35s cubic-bezier(.21,1.02,.73,1) forwards;
|
| 256 |
transform:translateX(120%);
|
| 257 |
opacity:0;
|
|
|
|
| 268 |
to{transform:translateX(120%);opacity:0}
|
| 269 |
}
|
| 270 |
.toast-warning{
|
| 271 |
+
background:rgba(30,18,28,.95);
|
| 272 |
+
border-left:4px solid #FF69B4;
|
| 273 |
}
|
| 274 |
.toast-error{
|
| 275 |
+
background:rgba(30,15,20,.95);
|
| 276 |
+
border-left:4px solid #FF1493;
|
| 277 |
}
|
| 278 |
.toast-success{
|
| 279 |
+
background:rgba(20,22,28,.95);
|
| 280 |
+
border-left:4px solid #FFB6C1;
|
| 281 |
}
|
| 282 |
.toast-info{
|
| 283 |
+
background:rgba(25,18,30,.95);
|
| 284 |
+
border-left:4px solid #FF69B4;
|
| 285 |
}
|
| 286 |
.toast-icon{
|
| 287 |
font-size:18px;
|
| 288 |
line-height:1;
|
| 289 |
flex-shrink:0;
|
| 290 |
margin-top:1px;
|
| 291 |
+
color:#FF69B4;
|
| 292 |
}
|
| 293 |
+
.toast-warning .toast-icon{color:#FF69B4}
|
| 294 |
+
.toast-error .toast-icon{color:#FF1493}
|
| 295 |
+
.toast-success .toast-icon{color:#FFB6C1}
|
| 296 |
+
.toast-info .toast-icon{color:#FF69B4}
|
| 297 |
.toast-body{
|
| 298 |
display:flex;
|
| 299 |
flex-direction:column;
|
|
|
|
| 304 |
.toast-title{
|
| 305 |
font-weight:700;
|
| 306 |
font-size:13px;
|
| 307 |
+
color:#FF69B4;
|
| 308 |
}
|
| 309 |
+
.toast-warning .toast-title{color:#FF69B4}
|
| 310 |
+
.toast-error .toast-title{color:#FF1493}
|
| 311 |
+
.toast-success .toast-title{color:#FFB6C1}
|
| 312 |
+
.toast-info .toast-title{color:#FF69B4}
|
| 313 |
.toast-msg{
|
| 314 |
font-size:12.5px;
|
| 315 |
color:#a1a1aa;
|
|
|
|
| 326 |
padding:0 0 0 4px;
|
| 327 |
transition:color .15s;
|
| 328 |
}
|
| 329 |
+
.toast-close:hover{color:#FF69B4}
|
| 330 |
|
| 331 |
/* ── Main Container ── */
|
| 332 |
.app-shell{
|
|
|
|
| 521 |
#bbox-count{
|
| 522 |
position:absolute;top:12px;right:12px;
|
| 523 |
background:rgba(24,24,27,.9);
|
| 524 |
+
color:#FF1493;
|
| 525 |
padding:4px 12px;
|
| 526 |
font-family:'JetBrains Mono',monospace;
|
| 527 |
font-size:12px;
|
| 528 |
font-weight:600;
|
| 529 |
border-radius:6px;
|
| 530 |
+
border:1px solid rgba(255,20,147,.3);
|
| 531 |
z-index:10;display:none;
|
| 532 |
backdrop-filter:blur(8px);
|
| 533 |
}
|
|
|
|
| 537 |
position:absolute;bottom:12px;left:50%;
|
| 538 |
transform:translateX(-50%);
|
| 539 |
background:rgba(24,24,27,.92);
|
| 540 |
+
color:#FF69B4;
|
| 541 |
padding:6px 16px;
|
| 542 |
font-family:'JetBrains Mono',monospace;
|
| 543 |
font-size:12px;
|
| 544 |
font-weight:600;
|
| 545 |
border-radius:8px;
|
| 546 |
+
border:1px solid rgba(255,20,147,.3);
|
| 547 |
z-index:10;display:none;
|
| 548 |
pointer-events:none;
|
| 549 |
backdrop-filter:blur(8px);
|
|
|
|
| 606 |
.hint-bar .hint-mover-tag{
|
| 607 |
display:inline-block;
|
| 608 |
padding:1px 8px;
|
| 609 |
+
background:rgba(255,20,147,.15);
|
| 610 |
+
border:1px solid rgba(255,20,147,.3);
|
| 611 |
border-radius:4px;
|
| 612 |
font-size:11px;
|
| 613 |
font-weight:600;
|
| 614 |
+
color:#FF69B4;
|
| 615 |
}
|
| 616 |
|
| 617 |
/* ── JSON Panel ── */
|
|
|
|
| 711 |
}
|
| 712 |
.modern-textarea::placeholder{color:#3f3f46}
|
| 713 |
.modern-textarea.prompt-error{
|
| 714 |
+
border-color:#FF1493!important;
|
| 715 |
+
box-shadow:0 0 0 3px rgba(255,20,147,.25)!important;
|
| 716 |
animation:promptShake .4s ease;
|
| 717 |
}
|
| 718 |
@keyframes promptShake{
|
|
|
|
| 800 |
}
|
| 801 |
|
| 802 |
.btn-run.mover-mode{
|
| 803 |
+
background:linear-gradient(135deg,#C71585,#FF1493)!important;
|
| 804 |
+
box-shadow:0 4px 16px rgba(255,20,147,.3),
|
| 805 |
inset 0 1px 0 rgba(255,255,255,.1)!important;
|
| 806 |
color:#ffffff!important;
|
| 807 |
-webkit-text-fill-color:#ffffff!important;
|
| 808 |
}
|
| 809 |
.btn-run.mover-mode:hover{
|
| 810 |
+
background:linear-gradient(135deg,#FF69B4,#C71585)!important;
|
| 811 |
+
box-shadow:0 6px 24px rgba(255,20,147,.45),
|
| 812 |
inset 0 1px 0 rgba(255,255,255,.15)!important;
|
| 813 |
color:#ffffff!important;
|
| 814 |
-webkit-text-fill-color:#ffffff!important;
|
|
|
|
| 1110 |
font-family:'JetBrains Mono',monospace;
|
| 1111 |
font-size:12px;
|
| 1112 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1113 |
|
| 1114 |
#gradio-run-btn{
|
| 1115 |
position:absolute;
|
|
|
|
| 1304 |
};
|
| 1305 |
|
| 1306 |
const HINT_TEXTS = {
|
| 1307 |
+
'Object-Remover': '<b>Draw:</b> Click & drag to create selection boxes \u00b7 <b>Select:</b> Click a box to move or resize \u00b7 <kbd>Delete</kbd> removes selected \u00b7 <kbd>Clear</kbd> removes all \u00b7 <kbd>Reset</kbd> removes image',
|
| 1308 |
+
'Design-Adder': '<b>Draw:</b> Click & drag to create selection boxes \u00b7 <b>Select:</b> Click a box to move or resize \u00b7 <kbd>Delete</kbd> removes selected \u00b7 <kbd>Clear</kbd> removes all \u00b7 <kbd>Reset</kbd> removes image',
|
| 1309 |
+
'Object-Mover': '<span class="hint-mover-tag">MOVER</span> Draw <b>exactly 2</b> boxes: <b>Box 1 (SRC)</b> = the object to move \u00b7 <b>Box 2 (DST)</b> = the target location \u00b7 <kbd>Clear</kbd> to redraw \u00b7 Only 2 boxes allowed'
|
| 1310 |
};
|
| 1311 |
|
| 1312 |
/* ── Toast System ── */
|
|
|
|
| 1432 |
moverHint.style.display = 'block';
|
| 1433 |
if (boxes.length === 0) {
|
| 1434 |
moverHint.textContent = '\u25a0 Draw Box 1: Select the SOURCE object';
|
| 1435 |
+
moverHint.style.color = '#FF69B4';
|
| 1436 |
} else if (boxes.length === 1) {
|
| 1437 |
moverHint.textContent = '\u25a1 Draw Box 2: Mark the TARGET location';
|
| 1438 |
+
moverHint.style.color = '#FFB6C1';
|
| 1439 |
} else {
|
| 1440 |
moverHint.textContent = '\u2714 Both boxes ready \u2014 Source + Target defined';
|
| 1441 |
+
moverHint.style.color = '#FF69B4';
|
| 1442 |
}
|
| 1443 |
}
|
| 1444 |
|
|
|
|
| 1468 |
if (promptInput) promptInput.value = DEFAULT_PROMPTS['Object-Remover'];
|
| 1469 |
if (runBtnEl) { runBtnEl.classList.remove('design-mode','mover-mode'); }
|
| 1470 |
if (runBtnLabel) runBtnLabel.textContent = 'Remove Object';
|
| 1471 |
+
if (statusMode) statusMode.textContent = 'Object Remover';
|
| 1472 |
} else if (taskMode === 'Design-Adder') {
|
| 1473 |
if (modeDesigner) modeDesigner.classList.add('active');
|
| 1474 |
if (promptInput) promptInput.value = DEFAULT_PROMPTS['Design-Adder'];
|
| 1475 |
if (runBtnEl) { runBtnEl.classList.remove('mover-mode'); runBtnEl.classList.add('design-mode'); }
|
| 1476 |
if (runBtnLabel) runBtnLabel.textContent = 'Add Design';
|
| 1477 |
+
if (statusMode) statusMode.textContent = 'Design Adder';
|
| 1478 |
} else if (taskMode === 'Object-Mover') {
|
| 1479 |
if (modeMover) modeMover.classList.add('active');
|
| 1480 |
if (promptInput) promptInput.value = DEFAULT_PROMPTS['Object-Mover'];
|
| 1481 |
if (runBtnEl) { runBtnEl.classList.remove('design-mode'); runBtnEl.classList.add('mover-mode'); }
|
| 1482 |
if (runBtnLabel) runBtnLabel.textContent = 'Move Object';
|
| 1483 |
+
if (statusMode) statusMode.textContent = 'Object Mover';
|
| 1484 |
if (boxes.length > 2) {
|
| 1485 |
window.showToast(
|
| 1486 |
'Object Mover requires exactly 2 boxes (Source + Target). You have ' + boxes.length + ' boxes. Please clear extra boxes before running.',
|
|
|
|
| 1516 |
return '#'+(index+1);
|
| 1517 |
}
|
| 1518 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1519 |
function redraw(tempRect) {
|
| 1520 |
ctx.clearRect(0,0,dispW,dispH);
|
| 1521 |
if (!baseImg) {
|
|
|
|
| 1527 |
boxes.forEach((b,i) => {
|
| 1528 |
const p = n2px(b);
|
| 1529 |
const lx=p.x1, ty=p.y1, w=p.x2-p.x1, h=p.y2-p.y1;
|
|
|
|
| 1530 |
if (i === selectedIdx) {
|
| 1531 |
ctx.strokeStyle = SEL_STROKE;
|
| 1532 |
ctx.lineWidth = RED_STROKE_WIDTH + 1;
|
|
|
|
| 1540 |
ctx.setLineDash([]);
|
| 1541 |
|
| 1542 |
const label = getBoxLabel(i);
|
| 1543 |
+
ctx.fillStyle = '#FF0000';
|
|
|
|
| 1544 |
ctx.font = 'bold 11px Inter,system-ui,sans-serif';
|
| 1545 |
ctx.textAlign = 'left'; ctx.textBaseline = 'top';
|
| 1546 |
const tw = ctx.measureText(label).width;
|
|
|
|
| 1616 |
}
|
| 1617 |
|
| 1618 |
function updateBadge() {
|
|
|
|
| 1619 |
if (boxes.length > 0) {
|
| 1620 |
badge.style.display = 'block';
|
| 1621 |
+
const isMover = window.__currentTaskMode === 'Object-Mover';
|
| 1622 |
if (isMover) {
|
| 1623 |
badge.textContent = boxes.length + '/2 box' + (boxes.length>1?'es':'');
|
|
|
|
|
|
|
| 1624 |
} else {
|
| 1625 |
badge.textContent = boxes.length + ' box' + (boxes.length>1?'es':'');
|
|
|
|
|
|
|
| 1626 |
}
|
| 1627 |
+
badge.style.color = '#FF1493';
|
| 1628 |
+
badge.style.borderColor = 'rgba(255,20,147,.3)';
|
| 1629 |
} else {
|
| 1630 |
badge.style.display = 'none';
|
| 1631 |
}
|
|
|
|
| 1668 |
e.preventDefault();
|
| 1669 |
const {x, y} = canvasXY(e);
|
| 1670 |
if (mode === 'draw') {
|
|
|
|
| 1671 |
if (window.__currentTaskMode === 'Object-Mover' && boxes.length >= 2) {
|
| 1672 |
window.showToast(
|
| 1673 |
'Object Mover allows exactly <b>2 boxes</b> (Source + Target). Clear existing boxes to redraw.',
|
|
|
|
| 1960 |
const pInput = document.getElementById('custom-prompt-input');
|
| 1961 |
const promptVal = pInput ? pInput.value.trim() : '';
|
| 1962 |
|
|
|
|
| 1963 |
if (!baseImg) {
|
| 1964 |
window.showToast('Please upload an image first before processing.', 'error', 'No Image');
|
| 1965 |
return;
|
| 1966 |
}
|
| 1967 |
|
|
|
|
| 1968 |
if (!promptVal) {
|
| 1969 |
window.showToast('Prompt cannot be empty. Please describe the edit you want to perform.', 'warning', 'Empty Prompt');
|
| 1970 |
if (pInput) {
|
|
|
|
| 1975 |
return;
|
| 1976 |
}
|
| 1977 |
|
|
|
|
| 1978 |
if (boxes.length === 0) {
|
| 1979 |
window.showToast('Please draw at least one bounding box on the image.', 'warning', 'No Boxes');
|
| 1980 |
return;
|
| 1981 |
}
|
| 1982 |
|
|
|
|
| 1983 |
if (window.__currentTaskMode === 'Object-Mover') {
|
| 1984 |
if (boxes.length < 2) {
|
| 1985 |
window.showToast(
|