Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Includes 30 custom nodes committed directly, 7 Civitai-exclusive loras stored via Git LFS, and a setup script that installs all dependencies and downloads HuggingFace-hosted models on vast.ai. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
593 lines
25 KiB
JavaScript
593 lines
25 KiB
JavaScript
var _a;
|
||
import { app } from "../../scripts/app.js";
|
||
import { RgthreeBaseServerNode } from "./base_node.js";
|
||
import { rgthree } from "./rgthree.js";
|
||
import { addConnectionLayoutSupport } from "./utils.js";
|
||
import { NodeTypesString } from "./constants.js";
|
||
import { drawInfoIcon, drawNumberWidgetPart, drawRoundedRectangle, drawTogglePart, fitString, isLowQuality, } from "./utils_canvas.js";
|
||
import { RgthreeBaseWidget, RgthreeBetterButtonWidget, RgthreeDividerWidget, } from "./utils_widgets.js";
|
||
import { rgthreeApi } from "../../rgthree/common/rgthree_api.js";
|
||
import { showLoraChooser } from "./utils_menu.js";
|
||
import { moveArrayItem, removeArrayItem } from "../../rgthree/common/shared_utils.js";
|
||
import { RgthreeLoraInfoDialog } from "./dialog_info.js";
|
||
import { LORA_INFO_SERVICE } from "../../rgthree/common/model_info_service.js";
|
||
const PROP_LABEL_SHOW_STRENGTHS = "Show Strengths";
|
||
const PROP_LABEL_SHOW_STRENGTHS_STATIC = `@${PROP_LABEL_SHOW_STRENGTHS}`;
|
||
const PROP_VALUE_SHOW_STRENGTHS_SINGLE = "Single Strength";
|
||
const PROP_VALUE_SHOW_STRENGTHS_SEPARATE = "Separate Model & Clip";
|
||
class RgthreePowerLoraLoader extends RgthreeBaseServerNode {
|
||
constructor(title = NODE_CLASS.title) {
|
||
super(title);
|
||
this.serialize_widgets = true;
|
||
this.logger = rgthree.newLogSession(`[Power Lora Stack]`);
|
||
this.loraWidgetsCounter = 0;
|
||
this.widgetButtonSpacer = null;
|
||
this.properties[PROP_LABEL_SHOW_STRENGTHS] = PROP_VALUE_SHOW_STRENGTHS_SINGLE;
|
||
rgthreeApi.getLoras();
|
||
if (rgthree.loadingApiJson) {
|
||
const fullApiJson = rgthree.loadingApiJson;
|
||
setTimeout(() => {
|
||
this.configureFromApiJson(fullApiJson);
|
||
}, 16);
|
||
}
|
||
}
|
||
configureFromApiJson(fullApiJson) {
|
||
var _b, _c;
|
||
if (this.id == null) {
|
||
const [n, v] = this.logger.errorParts("Cannot load from API JSON without node id.");
|
||
(_b = console[n]) === null || _b === void 0 ? void 0 : _b.call(console, ...v);
|
||
return;
|
||
}
|
||
const nodeData = fullApiJson[this.id] || fullApiJson[String(this.id)] || fullApiJson[Number(this.id)];
|
||
if (nodeData == null) {
|
||
const [n, v] = this.logger.errorParts(`No node found in API JSON for node id ${this.id}.`);
|
||
(_c = console[n]) === null || _c === void 0 ? void 0 : _c.call(console, ...v);
|
||
return;
|
||
}
|
||
this.configure({
|
||
widgets_values: Object.values(nodeData.inputs).filter((input) => typeof (input === null || input === void 0 ? void 0 : input["lora"]) === "string"),
|
||
});
|
||
}
|
||
configure(info) {
|
||
var _b;
|
||
while ((_b = this.widgets) === null || _b === void 0 ? void 0 : _b.length)
|
||
this.removeWidget(0);
|
||
this.widgetButtonSpacer = null;
|
||
if (info.id != null) {
|
||
super.configure(info);
|
||
}
|
||
this._tempWidth = this.size[0];
|
||
this._tempHeight = this.size[1];
|
||
for (const widgetValue of info.widgets_values || []) {
|
||
if ((widgetValue === null || widgetValue === void 0 ? void 0 : widgetValue.lora) !== undefined) {
|
||
const widget = this.addNewLoraWidget();
|
||
widget.value = { ...widgetValue };
|
||
}
|
||
}
|
||
this.addNonLoraWidgets();
|
||
this.size[0] = this._tempWidth;
|
||
this.size[1] = Math.max(this._tempHeight, this.computeSize()[1]);
|
||
}
|
||
onNodeCreated() {
|
||
var _b;
|
||
(_b = super.onNodeCreated) === null || _b === void 0 ? void 0 : _b.call(this);
|
||
this.addNonLoraWidgets();
|
||
const computed = this.computeSize();
|
||
this.size = this.size || [0, 0];
|
||
this.size[0] = Math.max(this.size[0], computed[0]);
|
||
this.size[1] = Math.max(this.size[1], computed[1]);
|
||
this.setDirtyCanvas(true, true);
|
||
}
|
||
addNewLoraWidget(lora) {
|
||
this.loraWidgetsCounter++;
|
||
const widget = this.addCustomWidget(new PowerLoraLoaderWidget("lora_" + this.loraWidgetsCounter));
|
||
if (lora)
|
||
widget.setLora(lora);
|
||
if (this.widgetButtonSpacer) {
|
||
moveArrayItem(this.widgets, widget, this.widgets.indexOf(this.widgetButtonSpacer));
|
||
}
|
||
return widget;
|
||
}
|
||
addNonLoraWidgets() {
|
||
moveArrayItem(this.widgets, this.addCustomWidget(new RgthreeDividerWidget({ marginTop: 4, marginBottom: 0, thickness: 0 })), 0);
|
||
moveArrayItem(this.widgets, this.addCustomWidget(new PowerLoraLoaderHeaderWidget()), 1);
|
||
this.widgetButtonSpacer = this.addCustomWidget(new RgthreeDividerWidget({ marginTop: 4, marginBottom: 0, thickness: 0 }));
|
||
this.addCustomWidget(new RgthreeBetterButtonWidget("➕ Add Lora", (event, pos, node) => {
|
||
rgthreeApi.getLoras().then((lorasDetails) => {
|
||
const loras = lorasDetails.map((l) => l.file);
|
||
showLoraChooser(event, (value) => {
|
||
var _b;
|
||
if (typeof value === "string") {
|
||
if (value.includes("Power Lora Chooser")) {
|
||
}
|
||
else if (value !== "NONE") {
|
||
this.addNewLoraWidget(value);
|
||
const computed = this.computeSize();
|
||
const tempHeight = (_b = this._tempHeight) !== null && _b !== void 0 ? _b : 15;
|
||
this.size[1] = Math.max(tempHeight, computed[1]);
|
||
this.setDirtyCanvas(true, true);
|
||
}
|
||
}
|
||
}, null, [...loras]);
|
||
});
|
||
return true;
|
||
}));
|
||
}
|
||
getSlotInPosition(canvasX, canvasY) {
|
||
var _b;
|
||
const slot = super.getSlotInPosition(canvasX, canvasY);
|
||
if (!slot) {
|
||
let lastWidget = null;
|
||
for (const widget of this.widgets) {
|
||
if (!widget.last_y)
|
||
return;
|
||
if (canvasY > this.pos[1] + widget.last_y) {
|
||
lastWidget = widget;
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
if ((_b = lastWidget === null || lastWidget === void 0 ? void 0 : lastWidget.name) === null || _b === void 0 ? void 0 : _b.startsWith("lora_")) {
|
||
return { widget: lastWidget, output: { type: "LORA WIDGET" } };
|
||
}
|
||
}
|
||
return slot;
|
||
}
|
||
getSlotMenuOptions(slot) {
|
||
var _b, _c, _d, _e, _f, _g;
|
||
if ((_c = (_b = slot === null || slot === void 0 ? void 0 : slot.widget) === null || _b === void 0 ? void 0 : _b.name) === null || _c === void 0 ? void 0 : _c.startsWith("lora_")) {
|
||
const widget = slot.widget;
|
||
const index = this.widgets.indexOf(widget);
|
||
const canMoveUp = !!((_e = (_d = this.widgets[index - 1]) === null || _d === void 0 ? void 0 : _d.name) === null || _e === void 0 ? void 0 : _e.startsWith("lora_"));
|
||
const canMoveDown = !!((_g = (_f = this.widgets[index + 1]) === null || _f === void 0 ? void 0 : _f.name) === null || _g === void 0 ? void 0 : _g.startsWith("lora_"));
|
||
const menuItems = [
|
||
{
|
||
content: `ℹ️ Show Info`,
|
||
callback: () => {
|
||
widget.showLoraInfoDialog();
|
||
},
|
||
},
|
||
null,
|
||
{
|
||
content: `${widget.value.on ? "⚫" : "🟢"} Toggle ${widget.value.on ? "Off" : "On"}`,
|
||
callback: () => {
|
||
widget.value.on = !widget.value.on;
|
||
},
|
||
},
|
||
{
|
||
content: `⬆️ Move Up`,
|
||
disabled: !canMoveUp,
|
||
callback: () => {
|
||
moveArrayItem(this.widgets, widget, index - 1);
|
||
},
|
||
},
|
||
{
|
||
content: `⬇️ Move Down`,
|
||
disabled: !canMoveDown,
|
||
callback: () => {
|
||
moveArrayItem(this.widgets, widget, index + 1);
|
||
},
|
||
},
|
||
{
|
||
content: `🗑️ Remove`,
|
||
callback: () => {
|
||
removeArrayItem(this.widgets, widget);
|
||
},
|
||
},
|
||
];
|
||
new LiteGraph.ContextMenu(menuItems, {
|
||
title: "LORA WIDGET",
|
||
event: rgthree.lastCanvasMouseEvent,
|
||
});
|
||
return undefined;
|
||
}
|
||
return this.defaultGetSlotMenuOptions(slot);
|
||
}
|
||
refreshComboInNode(defs) {
|
||
rgthreeApi.getLoras(true);
|
||
}
|
||
hasLoraWidgets() {
|
||
var _b;
|
||
return !!((_b = this.widgets) === null || _b === void 0 ? void 0 : _b.find((w) => { var _b; return (_b = w.name) === null || _b === void 0 ? void 0 : _b.startsWith("lora_"); }));
|
||
}
|
||
allLorasState() {
|
||
var _b, _c, _d;
|
||
let allOn = true;
|
||
let allOff = true;
|
||
for (const widget of this.widgets) {
|
||
if ((_b = widget.name) === null || _b === void 0 ? void 0 : _b.startsWith("lora_")) {
|
||
const on = (_c = widget.value) === null || _c === void 0 ? void 0 : _c.on;
|
||
allOn = allOn && on === true;
|
||
allOff = allOff && on === false;
|
||
if (!allOn && !allOff) {
|
||
return null;
|
||
}
|
||
}
|
||
}
|
||
return allOn && ((_d = this.widgets) === null || _d === void 0 ? void 0 : _d.length) ? true : false;
|
||
}
|
||
toggleAllLoras() {
|
||
var _b, _c;
|
||
const allOn = this.allLorasState();
|
||
const toggledTo = !allOn ? true : false;
|
||
for (const widget of this.widgets) {
|
||
if (((_b = widget.name) === null || _b === void 0 ? void 0 : _b.startsWith("lora_")) && ((_c = widget.value) === null || _c === void 0 ? void 0 : _c.on) != null) {
|
||
widget.value.on = toggledTo;
|
||
}
|
||
}
|
||
}
|
||
static setUp(comfyClass, nodeData) {
|
||
RgthreeBaseServerNode.registerForOverride(comfyClass, nodeData, NODE_CLASS);
|
||
}
|
||
static onRegisteredForOverride(comfyClass, ctxClass) {
|
||
addConnectionLayoutSupport(NODE_CLASS, app, [
|
||
["Left", "Right"],
|
||
["Right", "Left"],
|
||
]);
|
||
setTimeout(() => {
|
||
NODE_CLASS.category = comfyClass.category;
|
||
});
|
||
}
|
||
getHelp() {
|
||
return `
|
||
<p>
|
||
The ${this.type.replace("(rgthree)", "")} is a powerful node that condenses 100s of pixels
|
||
of functionality in a single, dynamic node that allows you to add loras, change strengths,
|
||
and quickly toggle on/off all without taking up half your screen.
|
||
</p>
|
||
<ul>
|
||
<li><p>
|
||
Add as many Lora's as you would like by clicking the "+ Add Lora" button.
|
||
There's no real limit!
|
||
</p></li>
|
||
<li><p>
|
||
Right-click on a Lora widget for special options to move the lora up or down
|
||
(no image affect, only presentational), toggle it on/off, or delete the row all together.
|
||
</p></li>
|
||
<li>
|
||
<p>
|
||
<strong>Properties.</strong> You can change the following properties (by right-clicking
|
||
on the node, and select "Properties" or "Properties Panel" from the menu):
|
||
</p>
|
||
<ul>
|
||
<li><p>
|
||
<code>${PROP_LABEL_SHOW_STRENGTHS}</code> - Change between showing a single, simple
|
||
strength (which will be used for both model and clip), or a more advanced view with
|
||
both model and clip strengths being modifiable.
|
||
</p></li>
|
||
</ul>
|
||
</li>
|
||
</ul>`;
|
||
}
|
||
}
|
||
_a = PROP_LABEL_SHOW_STRENGTHS_STATIC;
|
||
RgthreePowerLoraLoader.title = NodeTypesString.POWER_LORA_LOADER;
|
||
RgthreePowerLoraLoader.type = NodeTypesString.POWER_LORA_LOADER;
|
||
RgthreePowerLoraLoader.comfyClass = NodeTypesString.POWER_LORA_LOADER;
|
||
RgthreePowerLoraLoader[_a] = {
|
||
type: "combo",
|
||
values: [PROP_VALUE_SHOW_STRENGTHS_SINGLE, PROP_VALUE_SHOW_STRENGTHS_SEPARATE],
|
||
};
|
||
class PowerLoraLoaderHeaderWidget extends RgthreeBaseWidget {
|
||
constructor(name = "PowerLoraLoaderHeaderWidget") {
|
||
super(name);
|
||
this.value = { type: "PowerLoraLoaderHeaderWidget" };
|
||
this.type = "custom";
|
||
this.hitAreas = {
|
||
toggle: { bounds: [0, 0], onDown: this.onToggleDown },
|
||
};
|
||
this.showModelAndClip = null;
|
||
}
|
||
draw(ctx, node, w, posY, height) {
|
||
if (!node.hasLoraWidgets()) {
|
||
return;
|
||
}
|
||
this.showModelAndClip =
|
||
node.properties[PROP_LABEL_SHOW_STRENGTHS] === PROP_VALUE_SHOW_STRENGTHS_SEPARATE;
|
||
const margin = 10;
|
||
const innerMargin = margin * 0.33;
|
||
const lowQuality = isLowQuality();
|
||
const allLoraState = node.allLorasState();
|
||
posY += 2;
|
||
const midY = posY + height * 0.5;
|
||
let posX = 10;
|
||
ctx.save();
|
||
this.hitAreas.toggle.bounds = drawTogglePart(ctx, { posX, posY, height, value: allLoraState });
|
||
if (!lowQuality) {
|
||
posX += this.hitAreas.toggle.bounds[1] + innerMargin;
|
||
ctx.globalAlpha = app.canvas.editor_alpha * 0.55;
|
||
ctx.fillStyle = LiteGraph.WIDGET_TEXT_COLOR;
|
||
ctx.textAlign = "left";
|
||
ctx.textBaseline = "middle";
|
||
ctx.fillText("Toggle All", posX, midY);
|
||
let rposX = node.size[0] - margin - innerMargin - innerMargin;
|
||
ctx.textAlign = "center";
|
||
ctx.fillText(this.showModelAndClip ? "Clip" : "Strength", rposX - drawNumberWidgetPart.WIDTH_TOTAL / 2, midY);
|
||
if (this.showModelAndClip) {
|
||
rposX = rposX - drawNumberWidgetPart.WIDTH_TOTAL - innerMargin * 2;
|
||
ctx.fillText("Model", rposX - drawNumberWidgetPart.WIDTH_TOTAL / 2, midY);
|
||
}
|
||
}
|
||
ctx.restore();
|
||
}
|
||
onToggleDown(event, pos, node) {
|
||
node.toggleAllLoras();
|
||
this.cancelMouseDown();
|
||
return true;
|
||
}
|
||
}
|
||
const DEFAULT_LORA_WIDGET_DATA = {
|
||
on: true,
|
||
lora: null,
|
||
strength: 1,
|
||
strengthTwo: null,
|
||
};
|
||
class PowerLoraLoaderWidget extends RgthreeBaseWidget {
|
||
constructor(name) {
|
||
super(name);
|
||
this.type = "custom";
|
||
this.haveMouseMovedStrength = false;
|
||
this.loraInfoPromise = null;
|
||
this.loraInfo = null;
|
||
this.showModelAndClip = null;
|
||
this.hitAreas = {
|
||
toggle: { bounds: [0, 0], onDown: this.onToggleDown },
|
||
lora: { bounds: [0, 0], onClick: this.onLoraClick },
|
||
strengthDec: { bounds: [0, 0], onClick: this.onStrengthDecDown },
|
||
strengthVal: { bounds: [0, 0], onClick: this.onStrengthValUp },
|
||
strengthInc: { bounds: [0, 0], onClick: this.onStrengthIncDown },
|
||
strengthAny: { bounds: [0, 0], onMove: this.onStrengthAnyMove },
|
||
strengthTwoDec: { bounds: [0, 0], onClick: this.onStrengthTwoDecDown },
|
||
strengthTwoVal: { bounds: [0, 0], onClick: this.onStrengthTwoValUp },
|
||
strengthTwoInc: { bounds: [0, 0], onClick: this.onStrengthTwoIncDown },
|
||
strengthTwoAny: { bounds: [0, 0], onMove: this.onStrengthTwoAnyMove },
|
||
};
|
||
this._value = {
|
||
on: true,
|
||
lora: null,
|
||
strength: 1,
|
||
strengthTwo: null,
|
||
};
|
||
}
|
||
set value(v) {
|
||
this._value = v;
|
||
if (typeof this._value !== "object") {
|
||
this._value = { ...DEFAULT_LORA_WIDGET_DATA };
|
||
if (this.showModelAndClip) {
|
||
this._value.strengthTwo = this._value.strength;
|
||
}
|
||
}
|
||
this.getLoraInfo();
|
||
}
|
||
get value() {
|
||
return this._value;
|
||
}
|
||
setLora(lora) {
|
||
this._value.lora = lora;
|
||
this.getLoraInfo();
|
||
}
|
||
draw(ctx, node, w, posY, height) {
|
||
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
||
let currentShowModelAndClip = node.properties[PROP_LABEL_SHOW_STRENGTHS] === PROP_VALUE_SHOW_STRENGTHS_SEPARATE;
|
||
if (this.showModelAndClip !== currentShowModelAndClip) {
|
||
let oldShowModelAndClip = this.showModelAndClip;
|
||
this.showModelAndClip = currentShowModelAndClip;
|
||
if (this.showModelAndClip) {
|
||
if (oldShowModelAndClip != null) {
|
||
this.value.strengthTwo = (_b = this.value.strength) !== null && _b !== void 0 ? _b : 1;
|
||
}
|
||
}
|
||
else {
|
||
this.value.strengthTwo = null;
|
||
this.hitAreas.strengthTwoDec.bounds = [0, -1];
|
||
this.hitAreas.strengthTwoVal.bounds = [0, -1];
|
||
this.hitAreas.strengthTwoInc.bounds = [0, -1];
|
||
this.hitAreas.strengthTwoAny.bounds = [0, -1];
|
||
}
|
||
}
|
||
ctx.save();
|
||
const margin = 10;
|
||
const innerMargin = margin * 0.33;
|
||
const lowQuality = isLowQuality();
|
||
const midY = posY + height * 0.5;
|
||
let posX = margin;
|
||
drawRoundedRectangle(ctx, { pos: [posX, posY], size: [node.size[0] - margin * 2, height] });
|
||
this.hitAreas.toggle.bounds = drawTogglePart(ctx, { posX, posY, height, value: this.value.on });
|
||
posX += this.hitAreas.toggle.bounds[1] + innerMargin;
|
||
if (lowQuality) {
|
||
ctx.restore();
|
||
return;
|
||
}
|
||
if (!this.value.on) {
|
||
ctx.globalAlpha = app.canvas.editor_alpha * 0.4;
|
||
}
|
||
ctx.fillStyle = LiteGraph.WIDGET_TEXT_COLOR;
|
||
let rposX = node.size[0] - margin - innerMargin - innerMargin;
|
||
const strengthValue = this.showModelAndClip
|
||
? ((_c = this.value.strengthTwo) !== null && _c !== void 0 ? _c : 1)
|
||
: ((_d = this.value.strength) !== null && _d !== void 0 ? _d : 1);
|
||
let textColor = undefined;
|
||
if (((_e = this.loraInfo) === null || _e === void 0 ? void 0 : _e.strengthMax) != null && strengthValue > ((_f = this.loraInfo) === null || _f === void 0 ? void 0 : _f.strengthMax)) {
|
||
textColor = "#c66";
|
||
}
|
||
else if (((_g = this.loraInfo) === null || _g === void 0 ? void 0 : _g.strengthMin) != null && strengthValue < ((_h = this.loraInfo) === null || _h === void 0 ? void 0 : _h.strengthMin)) {
|
||
textColor = "#c66";
|
||
}
|
||
const [leftArrow, text, rightArrow] = drawNumberWidgetPart(ctx, {
|
||
posX: node.size[0] - margin - innerMargin - innerMargin,
|
||
posY,
|
||
height,
|
||
value: strengthValue,
|
||
direction: -1,
|
||
textColor,
|
||
});
|
||
this.hitAreas.strengthDec.bounds = leftArrow;
|
||
this.hitAreas.strengthVal.bounds = text;
|
||
this.hitAreas.strengthInc.bounds = rightArrow;
|
||
this.hitAreas.strengthAny.bounds = [leftArrow[0], rightArrow[0] + rightArrow[1] - leftArrow[0]];
|
||
rposX = leftArrow[0] - innerMargin;
|
||
if (this.showModelAndClip) {
|
||
rposX -= innerMargin;
|
||
this.hitAreas.strengthTwoDec.bounds = this.hitAreas.strengthDec.bounds;
|
||
this.hitAreas.strengthTwoVal.bounds = this.hitAreas.strengthVal.bounds;
|
||
this.hitAreas.strengthTwoInc.bounds = this.hitAreas.strengthInc.bounds;
|
||
this.hitAreas.strengthTwoAny.bounds = this.hitAreas.strengthAny.bounds;
|
||
let textColor = undefined;
|
||
if (((_j = this.loraInfo) === null || _j === void 0 ? void 0 : _j.strengthMax) != null && this.value.strength > ((_k = this.loraInfo) === null || _k === void 0 ? void 0 : _k.strengthMax)) {
|
||
textColor = "#c66";
|
||
}
|
||
else if (((_l = this.loraInfo) === null || _l === void 0 ? void 0 : _l.strengthMin) != null &&
|
||
this.value.strength < ((_m = this.loraInfo) === null || _m === void 0 ? void 0 : _m.strengthMin)) {
|
||
textColor = "#c66";
|
||
}
|
||
const [leftArrow, text, rightArrow] = drawNumberWidgetPart(ctx, {
|
||
posX: rposX,
|
||
posY,
|
||
height,
|
||
value: (_o = this.value.strength) !== null && _o !== void 0 ? _o : 1,
|
||
direction: -1,
|
||
textColor,
|
||
});
|
||
this.hitAreas.strengthDec.bounds = leftArrow;
|
||
this.hitAreas.strengthVal.bounds = text;
|
||
this.hitAreas.strengthInc.bounds = rightArrow;
|
||
this.hitAreas.strengthAny.bounds = [
|
||
leftArrow[0],
|
||
rightArrow[0] + rightArrow[1] - leftArrow[0],
|
||
];
|
||
rposX = leftArrow[0] - innerMargin;
|
||
}
|
||
const infoIconSize = height * 0.66;
|
||
const infoWidth = infoIconSize + innerMargin + innerMargin;
|
||
if (this.hitAreas["info"]) {
|
||
rposX -= innerMargin;
|
||
drawInfoIcon(ctx, rposX - infoIconSize, posY + (height - infoIconSize) / 2, infoIconSize);
|
||
this.hitAreas.info.bounds = [rposX - infoIconSize, infoWidth];
|
||
rposX = rposX - infoIconSize - innerMargin;
|
||
}
|
||
const loraWidth = rposX - posX;
|
||
ctx.textAlign = "left";
|
||
ctx.textBaseline = "middle";
|
||
const loraLabel = String(((_p = this.value) === null || _p === void 0 ? void 0 : _p.lora) || "None");
|
||
ctx.fillText(fitString(ctx, loraLabel, loraWidth), posX, midY);
|
||
this.hitAreas.lora.bounds = [posX, loraWidth];
|
||
posX += loraWidth + innerMargin;
|
||
ctx.globalAlpha = app.canvas.editor_alpha;
|
||
ctx.restore();
|
||
}
|
||
serializeValue(node, index) {
|
||
var _b;
|
||
const v = { ...this.value };
|
||
if (!this.showModelAndClip) {
|
||
delete v.strengthTwo;
|
||
}
|
||
else {
|
||
this.value.strengthTwo = (_b = this.value.strengthTwo) !== null && _b !== void 0 ? _b : 1;
|
||
v.strengthTwo = this.value.strengthTwo;
|
||
}
|
||
return v;
|
||
}
|
||
onToggleDown(event, pos, node) {
|
||
this.value.on = !this.value.on;
|
||
this.cancelMouseDown();
|
||
return true;
|
||
}
|
||
onInfoDown(event, pos, node) {
|
||
this.showLoraInfoDialog();
|
||
}
|
||
onLoraClick(event, pos, node) {
|
||
showLoraChooser(event, (value) => {
|
||
if (typeof value === "string") {
|
||
this.value.lora = value;
|
||
this.loraInfo = null;
|
||
this.getLoraInfo();
|
||
}
|
||
node.setDirtyCanvas(true, true);
|
||
});
|
||
this.cancelMouseDown();
|
||
}
|
||
onStrengthDecDown(event, pos, node) {
|
||
this.stepStrength(-1, false);
|
||
}
|
||
onStrengthIncDown(event, pos, node) {
|
||
this.stepStrength(1, false);
|
||
}
|
||
onStrengthTwoDecDown(event, pos, node) {
|
||
this.stepStrength(-1, true);
|
||
}
|
||
onStrengthTwoIncDown(event, pos, node) {
|
||
this.stepStrength(1, true);
|
||
}
|
||
onStrengthAnyMove(event, pos, node) {
|
||
this.doOnStrengthAnyMove(event, false);
|
||
}
|
||
onStrengthTwoAnyMove(event, pos, node) {
|
||
this.doOnStrengthAnyMove(event, true);
|
||
}
|
||
doOnStrengthAnyMove(event, isTwo = false) {
|
||
var _b;
|
||
if (event.deltaX) {
|
||
let prop = isTwo ? "strengthTwo" : "strength";
|
||
this.haveMouseMovedStrength = true;
|
||
this.value[prop] = ((_b = this.value[prop]) !== null && _b !== void 0 ? _b : 1) + event.deltaX * 0.05;
|
||
}
|
||
}
|
||
onStrengthValUp(event, pos, node) {
|
||
this.doOnStrengthValUp(event, false);
|
||
}
|
||
onStrengthTwoValUp(event, pos, node) {
|
||
this.doOnStrengthValUp(event, true);
|
||
}
|
||
doOnStrengthValUp(event, isTwo = false) {
|
||
if (this.haveMouseMovedStrength)
|
||
return;
|
||
let prop = isTwo ? "strengthTwo" : "strength";
|
||
const canvas = app.canvas;
|
||
canvas.prompt("Value", this.value[prop], (v) => (this.value[prop] = Number(v)), event);
|
||
}
|
||
onMouseUp(event, pos, node) {
|
||
super.onMouseUp(event, pos, node);
|
||
this.haveMouseMovedStrength = false;
|
||
}
|
||
showLoraInfoDialog() {
|
||
if (!this.value.lora || this.value.lora === "None") {
|
||
return;
|
||
}
|
||
const infoDialog = new RgthreeLoraInfoDialog(this.value.lora).show();
|
||
infoDialog.addEventListener("close", ((e) => {
|
||
if (e.detail.dirty) {
|
||
this.getLoraInfo(true);
|
||
}
|
||
}));
|
||
}
|
||
stepStrength(direction, isTwo = false) {
|
||
var _b;
|
||
let step = 0.05;
|
||
let prop = isTwo ? "strengthTwo" : "strength";
|
||
let strength = ((_b = this.value[prop]) !== null && _b !== void 0 ? _b : 1) + step * direction;
|
||
this.value[prop] = Math.round(strength * 100) / 100;
|
||
}
|
||
getLoraInfo(force = false) {
|
||
if (!this.loraInfoPromise || force == true) {
|
||
let promise;
|
||
if (this.value.lora && this.value.lora != "None") {
|
||
promise = LORA_INFO_SERVICE.getInfo(this.value.lora, force, true);
|
||
}
|
||
else {
|
||
promise = Promise.resolve(null);
|
||
}
|
||
this.loraInfoPromise = promise.then((v) => (this.loraInfo = v));
|
||
}
|
||
return this.loraInfoPromise;
|
||
}
|
||
}
|
||
const NODE_CLASS = RgthreePowerLoraLoader;
|
||
app.registerExtension({
|
||
name: "rgthree.PowerLoraLoader",
|
||
async beforeRegisterNodeDef(nodeType, nodeData) {
|
||
if (nodeData.name === NODE_CLASS.type) {
|
||
NODE_CLASS.setUp(nodeType, nodeData);
|
||
}
|
||
},
|
||
});
|