|
import { api } from "../../scripts/api.js"; |
|
import { wait } from "../../rgthree/common/shared_utils.js"; |
|
import { rgthree } from "./rgthree.js"; |
|
export class PowerPrompt { |
|
constructor(node, nodeData) { |
|
this.combos = {}; |
|
this.combosValues = {}; |
|
this.configuring = false; |
|
this.node = node; |
|
this.node.properties = this.node.properties || {}; |
|
this.node.properties["combos_filter"] = ""; |
|
this.nodeData = nodeData; |
|
this.isSimple = this.nodeData.name.includes("Simple"); |
|
this.promptEl = node.widgets[0].inputEl; |
|
this.addAndHandleKeyboardLoraEditWeight(); |
|
this.patchNodeRefresh(); |
|
const oldConfigure = this.node.configure; |
|
this.node.configure = (info) => { |
|
this.configuring = true; |
|
oldConfigure === null || oldConfigure === void 0 ? void 0 : oldConfigure.apply(this.node, [info]); |
|
this.configuring = false; |
|
}; |
|
const oldOnConnectionsChange = this.node.onConnectionsChange; |
|
this.node.onConnectionsChange = (type, slotIndex, isConnected, link_info, _ioSlot) => { |
|
oldOnConnectionsChange === null || oldOnConnectionsChange === void 0 ? void 0 : oldOnConnectionsChange.apply(this.node, [type, slotIndex, isConnected, link_info, _ioSlot]); |
|
this.onNodeConnectionsChange(type, slotIndex, isConnected, link_info, _ioSlot); |
|
}; |
|
const oldOnConnectInput = this.node.onConnectInput; |
|
this.node.onConnectInput = (inputIndex, outputType, outputSlot, outputNode, outputIndex) => { |
|
let canConnect = true; |
|
if (oldOnConnectInput) { |
|
canConnect = oldOnConnectInput.apply(this.node, [ |
|
inputIndex, |
|
outputType, |
|
outputSlot, |
|
outputNode, |
|
outputIndex, |
|
]); |
|
} |
|
return (this.configuring || |
|
rgthree.loadingApiJson || |
|
(canConnect && !this.node.inputs[inputIndex].disabled)); |
|
}; |
|
const oldOnConnectOutput = this.node.onConnectOutput; |
|
this.node.onConnectOutput = (outputIndex, inputType, inputSlot, inputNode, inputIndex) => { |
|
let canConnect = true; |
|
if (oldOnConnectOutput) { |
|
canConnect = oldOnConnectOutput === null || oldOnConnectOutput === void 0 ? void 0 : oldOnConnectOutput.apply(this.node, [ |
|
outputIndex, |
|
inputType, |
|
inputSlot, |
|
inputNode, |
|
inputIndex, |
|
]); |
|
} |
|
return (this.configuring || |
|
rgthree.loadingApiJson || |
|
(canConnect && !this.node.outputs[outputIndex].disabled)); |
|
}; |
|
const onPropertyChanged = this.node.onPropertyChanged; |
|
this.node.onPropertyChanged = (property, value, prevValue) => { |
|
onPropertyChanged && onPropertyChanged.call(this, property, value, prevValue); |
|
if (property === "combos_filter") { |
|
this.refreshCombos(this.nodeData); |
|
} |
|
}; |
|
for (let i = this.node.widgets.length - 1; i >= 0; i--) { |
|
if (this.shouldRemoveServerWidget(this.node.widgets[i])) { |
|
this.node.widgets.splice(i, 1); |
|
} |
|
} |
|
this.refreshCombos(nodeData); |
|
setTimeout(() => { |
|
this.stabilizeInputsOutputs(); |
|
}, 32); |
|
} |
|
onNodeConnectionsChange(_type, _slotIndex, _isConnected, _linkInfo, _ioSlot) { |
|
this.stabilizeInputsOutputs(); |
|
} |
|
stabilizeInputsOutputs() { |
|
if (this.configuring || rgthree.loadingApiJson) { |
|
return; |
|
} |
|
const clipLinked = this.node.inputs.some((i) => i.name.includes("clip") && !!i.link); |
|
const modelLinked = this.node.inputs.some((i) => i.name.includes("model") && !!i.link); |
|
for (const output of this.node.outputs) { |
|
const type = output.type.toLowerCase(); |
|
if (type.includes("model")) { |
|
output.disabled = !modelLinked; |
|
} |
|
else if (type.includes("conditioning")) { |
|
output.disabled = !clipLinked; |
|
} |
|
else if (type.includes("clip")) { |
|
output.disabled = !clipLinked; |
|
} |
|
else if (type.includes("string")) { |
|
output.color_off = "#7F7"; |
|
output.color_on = "#7F7"; |
|
} |
|
if (output.disabled) { |
|
} |
|
} |
|
} |
|
onFreshNodeDefs(event) { |
|
this.refreshCombos(event.detail[this.nodeData.name]); |
|
} |
|
shouldRemoveServerWidget(widget) { |
|
var _a, _b, _c, _d; |
|
return (((_a = widget.name) === null || _a === void 0 ? void 0 : _a.startsWith("insert_")) || |
|
((_b = widget.name) === null || _b === void 0 ? void 0 : _b.startsWith("target_")) || |
|
((_c = widget.name) === null || _c === void 0 ? void 0 : _c.startsWith("crop_")) || |
|
((_d = widget.name) === null || _d === void 0 ? void 0 : _d.startsWith("values_"))); |
|
} |
|
refreshCombos(nodeData) { |
|
var _a, _b, _c; |
|
this.nodeData = nodeData; |
|
let filter = null; |
|
if ((_a = this.node.properties["combos_filter"]) === null || _a === void 0 ? void 0 : _a.trim()) { |
|
try { |
|
filter = new RegExp(this.node.properties["combos_filter"].trim(), "i"); |
|
} |
|
catch (e) { |
|
console.error(`Could not parse "${filter}" for Regular Expression`, e); |
|
filter = null; |
|
} |
|
} |
|
let data = Object.assign({}, ((_b = this.nodeData.input) === null || _b === void 0 ? void 0 : _b.optional) || {}, ((_c = this.nodeData.input) === null || _c === void 0 ? void 0 : _c.hidden) || {}); |
|
for (const [key, value] of Object.entries(data)) { |
|
if (Array.isArray(value[0])) { |
|
let values = value[0]; |
|
if (key.startsWith("insert")) { |
|
values = filter |
|
? values.filter((v, i) => i < 1 || (i == 1 && v.match(/^disable\s[a-z]/i)) || (filter === null || filter === void 0 ? void 0 : filter.test(v))) |
|
: values; |
|
const shouldShow = values.length > 2 || (values.length > 1 && !values[1].match(/^disable\s[a-z]/i)); |
|
if (shouldShow) { |
|
if (!this.combos[key]) { |
|
this.combos[key] = this.node.addWidget("combo", key, values, (selected) => { |
|
if (selected !== values[0] && !selected.match(/^disable\s[a-z]/i)) { |
|
wait().then(() => { |
|
if (key.includes("embedding")) { |
|
this.insertSelectionText(`embedding:${selected}`); |
|
} |
|
else if (key.includes("saved")) { |
|
this.insertSelectionText(this.combosValues[`values_${key}`][values.indexOf(selected)]); |
|
} |
|
else if (key.includes("lora")) { |
|
this.insertSelectionText(`<lora:${selected}:1.0>`); |
|
} |
|
this.combos[key].value = values[0]; |
|
}); |
|
} |
|
}, { |
|
values, |
|
serialize: true, |
|
}); |
|
this.combos[key].oldComputeSize = this.combos[key].computeSize; |
|
let node = this.node; |
|
this.combos[key].computeSize = function (width) { |
|
var _a, _b; |
|
const size = ((_b = (_a = this).oldComputeSize) === null || _b === void 0 ? void 0 : _b.call(_a, width)) || [ |
|
width, |
|
LiteGraph.NODE_WIDGET_HEIGHT, |
|
]; |
|
if (this === node.widgets[node.widgets.length - 1]) { |
|
size[1] += 10; |
|
} |
|
return size; |
|
}; |
|
} |
|
this.combos[key].options.values = values; |
|
this.combos[key].value = values[0]; |
|
} |
|
else if (!shouldShow && this.combos[key]) { |
|
this.node.widgets.splice(this.node.widgets.indexOf(this.combos[key]), 1); |
|
delete this.combos[key]; |
|
} |
|
} |
|
else if (key.startsWith("values")) { |
|
this.combosValues[key] = values; |
|
} |
|
} |
|
} |
|
} |
|
insertSelectionText(text) { |
|
if (!this.promptEl) { |
|
console.error("Asked to insert text, but no textbox found."); |
|
return; |
|
} |
|
let prompt = this.promptEl.value; |
|
let first = prompt.substring(0, this.promptEl.selectionEnd).replace(/ +$/, ""); |
|
first = first + (["\n"].includes(first[first.length - 1]) ? "" : first.length ? " " : ""); |
|
let second = prompt.substring(this.promptEl.selectionEnd).replace(/^ +/, ""); |
|
second = (["\n"].includes(second[0]) ? "" : second.length ? " " : "") + second; |
|
this.promptEl.value = first + text + second; |
|
this.promptEl.focus(); |
|
this.promptEl.selectionStart = first.length; |
|
this.promptEl.selectionEnd = first.length + text.length; |
|
} |
|
addAndHandleKeyboardLoraEditWeight() { |
|
this.promptEl.addEventListener("keydown", (event) => { |
|
var _a, _b; |
|
if (!(event.key === "ArrowUp" || event.key === "ArrowDown")) |
|
return; |
|
if (!event.ctrlKey && !event.metaKey) |
|
return; |
|
const delta = event.shiftKey ? 0.01 : 0.1; |
|
let start = this.promptEl.selectionStart; |
|
let end = this.promptEl.selectionEnd; |
|
let fullText = this.promptEl.value; |
|
let selectedText = fullText.substring(start, end); |
|
if (!selectedText) { |
|
const stopOn = "<>()\r\n\t"; |
|
if (fullText[start] == ">") { |
|
start -= 2; |
|
end -= 2; |
|
} |
|
if (fullText[end - 1] == "<") { |
|
start += 2; |
|
end += 2; |
|
} |
|
while (!stopOn.includes(fullText[start]) && start > 0) { |
|
start--; |
|
} |
|
while (!stopOn.includes(fullText[end - 1]) && end < fullText.length) { |
|
end++; |
|
} |
|
selectedText = fullText.substring(start, end); |
|
} |
|
if (!selectedText.startsWith("<lora:") || !selectedText.endsWith(">")) { |
|
return; |
|
} |
|
let weight = (_b = Number((_a = selectedText.match(/:(-?\d*(\.\d*)?)>$/)) === null || _a === void 0 ? void 0 : _a[1])) !== null && _b !== void 0 ? _b : 1; |
|
weight += event.key === "ArrowUp" ? delta : -delta; |
|
const updatedText = selectedText.replace(/(:-?\d*(\.\d*)?)?>$/, `:${weight.toFixed(2)}>`); |
|
this.promptEl.setRangeText(updatedText, start, end, "select"); |
|
event.preventDefault(); |
|
event.stopPropagation(); |
|
}); |
|
} |
|
patchNodeRefresh() { |
|
this.boundOnFreshNodeDefs = this.onFreshNodeDefs.bind(this); |
|
api.addEventListener("fresh-node-defs", this.boundOnFreshNodeDefs); |
|
const oldNodeRemoved = this.node.onRemoved; |
|
this.node.onRemoved = () => { |
|
oldNodeRemoved === null || oldNodeRemoved === void 0 ? void 0 : oldNodeRemoved.call(this.node); |
|
api.removeEventListener("fresh-node-defs", this.boundOnFreshNodeDefs); |
|
}; |
|
} |
|
} |
|
|