import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js"; import { RgthreeBaseServerNode } from "./base_node.js"; import { NodeTypesString } from "./constants.js"; import { addConnectionLayoutSupport } from "./utils.js"; import { RgthreeBaseWidget, } from "./utils_widgets.js"; import { measureText } from "./utils_canvas.js"; function imageDataToUrl(data) { return api.apiURL(`/view?filename=${encodeURIComponent(data.filename)}&type=${data.type}&subfolder=${data.subfolder}${app.getPreviewFormatParam()}${app.getRandParam()}`); } export class RgthreeImageComparer extends RgthreeBaseServerNode { constructor(title = RgthreeImageComparer.title) { super(title); this.imageIndex = 0; this.imgs = []; this.serialize_widgets = true; this.isPointerDown = false; this.isPointerOver = false; this.pointerOverPos = [0, 0]; this.canvasWidget = null; this.properties["comparer_mode"] = "Slide"; } onExecuted(output) { var _a; (_a = super.onExecuted) === null || _a === void 0 ? void 0 : _a.call(this, output); if ("images" in output) { this.canvasWidget.value = { images: (output.images || []).map((d, i) => { return { name: i === 0 ? "A" : "B", selected: true, url: imageDataToUrl(d), }; }), }; } else { output.a_images = output.a_images || []; output.b_images = output.b_images || []; const imagesToChoose = []; const multiple = output.a_images.length + output.b_images.length > 2; for (const [i, d] of output.a_images.entries()) { imagesToChoose.push({ name: output.a_images.length > 1 || multiple ? `A${i + 1}` : "A", selected: i === 0, url: imageDataToUrl(d), }); } for (const [i, d] of output.b_images.entries()) { imagesToChoose.push({ name: output.b_images.length > 1 || multiple ? `B${i + 1}` : "B", selected: i === 0, url: imageDataToUrl(d), }); } this.canvasWidget.value = { images: imagesToChoose }; } } onSerialize(o) { var _a; super.onSerialize && super.onSerialize(o); for (let [index, widget_value] of (o.widgets_values || []).entries()) { if (((_a = this.widgets[index]) === null || _a === void 0 ? void 0 : _a.name) === "rgthree_comparer") { o.widgets_values[index] = this.widgets[index].value.images.map((d) => { d = { ...d }; delete d.img; return d; }); } } } onNodeCreated() { this.canvasWidget = this.addCustomWidget(new RgthreeImageComparerWidget("rgthree_comparer", this)); this.setSize(this.computeSize()); this.setDirtyCanvas(true, true); } setIsPointerDown(down = this.isPointerDown) { const newIsDown = down && !!app.canvas.pointer_is_down; if (this.isPointerDown !== newIsDown) { this.isPointerDown = newIsDown; this.setDirtyCanvas(true, false); } this.imageIndex = this.isPointerDown ? 1 : 0; if (this.isPointerDown) { requestAnimationFrame(() => { this.setIsPointerDown(); }); } } onMouseDown(event, pos, graphCanvas) { var _a; (_a = super.onMouseDown) === null || _a === void 0 ? void 0 : _a.call(this, event, pos, graphCanvas); this.setIsPointerDown(true); } onMouseEnter(event, pos, graphCanvas) { var _a; (_a = super.onMouseEnter) === null || _a === void 0 ? void 0 : _a.call(this, event, pos, graphCanvas); this.setIsPointerDown(!!app.canvas.pointer_is_down); this.isPointerOver = true; } onMouseLeave(event, pos, graphCanvas) { var _a; (_a = super.onMouseLeave) === null || _a === void 0 ? void 0 : _a.call(this, event, pos, graphCanvas); this.setIsPointerDown(false); this.isPointerOver = false; } onMouseMove(event, pos, graphCanvas) { var _a; (_a = super.onMouseMove) === null || _a === void 0 ? void 0 : _a.call(this, event, pos, graphCanvas); this.pointerOverPos = [...pos]; this.imageIndex = this.pointerOverPos[0] > this.size[0] / 2 ? 1 : 0; } getHelp() { return `
The ${this.type.replace("(rgthree)", "")} node compares two images on top of each other.
Notes
The right-click menu may show image options (Open Image, Save Image, etc.) which will correspond to the first image (image_a) if clicked on the left-half of the node, or the second image if on the right half of the node.
Inputs
image_a
Optional. The first image to use to compare.
image_a.
image_b
Optional. The second image to use to compare.
Note image_a
and image_b
work best when a single
image is provided. However, if each/either are a batch, you can choose which item
from each batch are chosen to be compared. If either image_a
or
image_b
are not provided, the node will choose the first two from the
provided input if it's a batch, otherwise only show the single image (just as
Preview Image would).
Properties. You can change the following properties (by right-clicking on the node, and select "Properties" or "Properties Panel" from the menu):
comparer_mode
- Choose between "Slide" and "Click". Defaults to "Slide".