Skip to content

Commit 38d472b

Browse files
committed
Add Vue Nodes 2.0 compatibility support
- Replace direct app.graph.setDirtyCanvas(true) calls with centralized requestCanvasUpdate() and requestVueCompatWidgetDraw() methods - Install custom widget in Vue nodes mode to render the node interface inside the Vue-compatible canvas, with auto-sizing and layout management - Normalize pointer events for Vue nodes so interaction methods receive consistent canvas coordinates - Bind canvas pointer events in Vue mode and keep header controls in sync with collapsed/expanded state - Adjust info text placement and compact toggle behavior for Vue nodes - Pass icon load callback into loadIcons so canvas updates after SVG load - Bump legacy scaling section minimum height to match new layout
1 parent 44b7c2a commit 38d472b

8 files changed

Lines changed: 504 additions & 33 deletions

js/auto_detect/auto_detect_methods.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ export const autoDetectMethods = {
489489
this.manuallySetByAutoFit = false;
490490
this.setAutoDetectSource(dimensions.source === 'frontend' ? 'frontend' : 'backend');
491491
this.setRawAutoDetectDimensions(dimensions);
492-
this.app?.graph?.setDirtyCanvas(true);
492+
this.requestCanvasUpdate(true);
493493
return;
494494
}
495495
}
@@ -527,7 +527,7 @@ export const autoDetectMethods = {
527527
this.setDimensions(this.detectedDimensions.width, this.detectedDimensions.height);
528528
}
529529

530-
this.app?.graph?.setDirtyCanvas(true);
530+
this.requestCanvasUpdate(true);
531531
}
532532
} catch (error) {
533533
log.error('Error checking for image dimensions:', error);

js/canvas/resolution_master_canvas_methods.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export const canvasMethods = {
3232
try {
3333
this._canvasUpdateScheduled = false;
3434
this._pendingCanvasUpdate = false;
35+
this.requestVueCompatWidgetDraw(true);
3536
this.app?.graph?.setDirtyCanvas(true);
3637
} finally {
3738
performanceDiagnostics.end(dirtyToken);

js/dialogs/custom_value_dialog_manager.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ export class CustomValueDialogManager {
299299
}
300300

301301
this.closeCustomInputDialog();
302-
this.app?.graph?.setDirtyCanvas(true);
302+
this.rm.requestCanvasUpdate(true);
303303

304304
log.debug(`Applied custom ${valueType}: ${value}`);
305305
}

js/drawing/resolution_master_draw_methods.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ export const drawingMethods = {
3535
this.draw2DCanvas(ctx, margin, currentY, node.size[0] - margin * 2, canvasHeight, canvasPadding);
3636
currentY += canvasHeight + this.getCanvasInfoGap();
3737

38-
const infoY = this.lastCanvasBounds
39-
? this.lastCanvasBounds.y + this.lastCanvasBounds.h + 18
40-
: currentY;
38+
const infoY = this.isVueNodesMode() && this.collapsedSections.extraControls
39+
? node.size[1]
40+
- this.getVueCompatBottomOverlayClearance()
41+
- this.getManualBottomPadding()
42+
: this.lastCanvasBounds
43+
? this.lastCanvasBounds.y + this.lastCanvasBounds.h + 18
44+
: currentY;
4145
this.drawInfoText(ctx, infoY);
4246
currentY += 15 + spacing;
4347

@@ -133,6 +137,14 @@ export const drawingMethods = {
133137
},
134138

135139
drawCompactToggleButton(ctx) {
140+
if (this.isVueNodesMode()) {
141+
delete this.controls.compactHelpBtn;
142+
delete this.controls.compactToggleBtn;
143+
this.syncVueCompatHeaderControls?.();
144+
return;
145+
}
146+
147+
this.teardownVueCompatHeaderControls?.();
136148
const isActive = this.collapsedSections.extraControls || false;
137149
const buttonSize = 18;
138150
const x = this.node.size[0] - buttonSize - 9;
@@ -449,21 +461,29 @@ export const drawingMethods = {
449461
return this.canvasDotsCache;
450462
},
451463

452-
drawInfoText(ctx, y) {
453-
const node = this.node;
464+
getInfoText() {
454465
if (this.widthWidget && this.heightWidget) {
455466
const width = this.widthWidget.value;
456467
const height = this.heightWidget.value;
457468
const mp = ((width * height) / 1000000).toFixed(2);
458469
const pResolution = formatClosestPResolution(width, height);
459-
460470
const aspectRatio = aspectRatioString(width, height);
461471

472+
return `${width} × ${height} | ${mp} MP ${pResolution} | ${aspectRatio}`;
473+
}
474+
return "";
475+
},
476+
477+
drawInfoText(ctx, y) {
478+
const text = this.getInfoText();
479+
if (text) {
480+
const node = this.node;
481+
462482
ctx.fillStyle = "#bbb";
463483
ctx.font = "12px Arial";
464484
ctx.textAlign = "center";
465-
ctx.fillText(`${width} × ${height} | ${mp} MP ${pResolution} | ${aspectRatio}`,
466-
node.size[0] / 2, y);
485+
ctx.textBaseline = "middle";
486+
ctx.fillText(text, node.size[0] / 2, y);
467487
}
468488
},
469489

js/interaction/resolution_master_interaction_methods.js

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ export const interactionMethods = {
223223
},
224224

225225
scheduleCanvasPointerDrag(eMove, activeCanvas) {
226+
this.normalizeVueCompatPointerEvent?.(eMove);
226227
this._pendingCanvasPointerDragEvent = eMove;
227228
this._pendingCanvasPointerDragCanvas = activeCanvas;
228229
if (this._pendingCanvasPointerDragFrame !== null) return;
@@ -290,12 +291,15 @@ export const interactionMethods = {
290291
|| null;
291292

292293
pointer.onDrag = (eMove) => {
294+
this.normalizeVueCompatPointerEvent?.(eMove);
293295
this.scheduleCanvasPointerDrag(eMove, activeCanvas);
294296
};
295297
pointer.finally = () => {
296298
this.flushCanvasPointerDrag();
297299
if (this.node?.capture) {
298-
this.handleMouseUp(pointer.eUp || pointer.eMove || pointer.eDown);
300+
const finalEvent = pointer.eUp || pointer.eMove || pointer.eDown;
301+
this.normalizeVueCompatPointerEvent?.(finalEvent);
302+
this.handleMouseUp(finalEvent);
299303
}
300304
this._usingCanvasPointerCallbacks = false;
301305
this._capturedPointerCanvas = null;
@@ -507,7 +511,7 @@ export const interactionMethods = {
507511
if (newHover !== this.hoverElement) {
508512
this.hoverElement = newHover;
509513
this.handleTooltipHover(newHover, e);
510-
this.app?.graph?.setDirtyCanvas(true);
514+
this.requestCanvasUpdate(true);
511515
}
512516
},
513517

@@ -519,15 +523,15 @@ export const interactionMethods = {
519523
if (this.showTooltip) {
520524
this.showTooltip = false;
521525
this.tooltipElement = null;
522-
this.app?.graph?.setDirtyCanvas(true);
526+
this.requestCanvasUpdate(true);
523527
}
524528
if (element && this.tooltips[element]) {
525529
const initialMousePos = { x: e.canvasX, y: e.canvasY };
526530
this.tooltipTimer = setTimeout(() => {
527531
this.tooltipElement = element;
528532
this.showTooltip = true;
529533
this.tooltipFixedPos = initialMousePos;
530-
this.app?.graph?.setDirtyCanvas(true);
534+
this.requestCanvasUpdate(true);
531535
}, this.tooltipDelay);
532536
}
533537
},
@@ -711,14 +715,14 @@ export const interactionMethods = {
711715
const widget = this.node.widgets?.find(w => w.name === 'auto_detect');
712716
if (widget) widget.value = props.autoDetect;
713717
this.syncBackendFallbackWidgets();
714-
this.app?.graph?.setDirtyCanvas(true);
718+
this.requestCanvasUpdate(true);
715719
} else if (toggleName === 'smartFitToggle' && props.selectedCategory) {
716720
props.smartFit = !props.smartFit;
717721
this.syncBackendFallbackWidgets();
718-
this.app?.graph?.setDirtyCanvas(true);
722+
this.requestCanvasUpdate(true);
719723
} else if (toggleName === 'calcInfoToggle' && props.selectedCategory) {
720724
props.showCalcInfo = !props.showCalcInfo;
721-
this.app?.graph?.setDirtyCanvas(true);
725+
this.requestCanvasUpdate(true);
722726
}
723727
},
724728

@@ -737,7 +741,7 @@ export const interactionMethods = {
737741
}
738742
this.syncBackendFallbackWidgets();
739743
this.updateRescaleValue();
740-
this.app?.graph?.setDirtyCanvas(true);
744+
this.requestCanvasUpdate(true);
741745
},
742746

743747
handleRadioClick(radioName) {
@@ -749,7 +753,7 @@ export const interactionMethods = {
749753
};
750754
props.rescaleMode = radioMap[radioName];
751755
this.updateRescaleValue();
752-
this.app?.graph?.setDirtyCanvas(true);
756+
this.requestCanvasUpdate(true);
753757
},
754758

755759
handleSectionHeaderClick(headerKey) {
@@ -764,7 +768,7 @@ export const interactionMethods = {
764768
this.userPreferredHeight = this.getStoredPreferredHeight(this.collapsedSections.extraControls);
765769
this.applyCompactSlotLabels();
766770
}
767-
this.app?.graph?.setDirtyCanvas(true, true);
771+
this.requestCanvasUpdate(true);
768772

769773
log.debug(`Section ${sectionKey} ${this.collapsedSections[sectionKey] ? 'collapsed' : 'expanded'}`);
770774
},
@@ -803,7 +807,7 @@ export const interactionMethods = {
803807
}
804808
}
805809

806-
this.app?.graph?.setDirtyCanvas(true);
810+
this.requestCanvasUpdate(true);
807811
},
808812

809813
showPresetSelector(e, mode) {
@@ -884,7 +888,7 @@ export const interactionMethods = {
884888
if (selectedType && this.latentTypeWidget) {
885889
this.latentTypeWidget.value = selectedType.value;
886890
log.debug(`Latent type manually changed to: ${selectedType.value}`);
887-
this.app?.graph?.setDirtyCanvas(true);
891+
this.requestCanvasUpdate(true);
888892
}
889893
}
890894
});
@@ -918,7 +922,7 @@ export const interactionMethods = {
918922
props.selectedPreset = null;
919923
this.syncBackendFallbackWidgets();
920924
this.updateRescaleValue();
921-
this.app?.graph?.setDirtyCanvas(true);
925+
this.requestCanvasUpdate(true);
922926
};
923927
} else if (dropdownName === 'presetDropdown' && props.selectedCategory) {
924928
const selectorMode = props.preset_selector_mode || 'visual';
@@ -935,7 +939,7 @@ export const interactionMethods = {
935939
}
936940
props.targetResolution = parseInt(resolutionValue);
937941
this.updateRescaleValue();
938-
this.app?.graph?.setDirtyCanvas(true);
942+
this.requestCanvasUpdate(true);
939943
};
940944
}
941945

0 commit comments

Comments
 (0)