Files
da2el-ai-D2-nodes-ComfyUI/web/D2_PromptConverDialog.js
T

247 lines
7.3 KiB
JavaScript

import { app } from "../../scripts/app.js";
import { D2_FloatContainer } from "./D2_FloatContainer.js";
import { loadCssFile } from "./utils.js";
/**
* プロンプト変換
*/
class D2_PromptConvert {
static RATE = 1.05;
/**
* StableDiffusionのweightをNAI方式に変換
*/
static convertToNai(srcPrompt) {
const tempPrompt = srcPrompt.replace(/\n/g, '');
const convertedPrompt = tempPrompt.replace(/\([^)]+:\s*[0-9.]+\s*\)/g, D2_PromptConvert.$_convertToNai);
return convertedPrompt;
}
static $_convertToNai(prompt) {
const parts = prompt.substring(1, prompt.length - 1).split(':');
const text = parts.slice(0, -1).join(':').trim();
const weightStr = parts[parts.length - 1].trim();
const weight = parseFloat(weightStr);
const n = Math.round(Math.log(weight) / Math.log(D2_PromptConvert.RATE));
const count = Math.abs(n);
let openBra, closeBra;
if (weight < 1) {
openBra = '[';
closeBra = ']';
} else {
openBra = '{';
closeBra = '}';
}
return openBra.repeat(count) + text + closeBra.repeat(count);
}
/**
* NAIのweightをStableDiffusion方式に変換
*/
static convertToSd(srcPrompt) {
let tempPrompt = srcPrompt.replace(/\n/g, '');
let convertedPrompt = tempPrompt.replace(/[\[{]+[^\]}]+[\]}]+/g, D2_PromptConvert.$_convertToSd);
return convertedPrompt;
}
static $_convertToSd(prompt) {
const braType = prompt.substring(0, 1);
const braCount = (prompt.match(/[\[{]/g) || []).length;
let weight = 0;
if (braType === '{') {
weight = 1 * Math.pow(D2_PromptConvert.RATE, braCount);
} else {
weight = 1 * Math.pow(1 / D2_PromptConvert.RATE, braCount);
}
let weightAdjust;
// 四捨五入して小数点2位にするか、
// 四捨五入せず小数点3位で切り捨てるか
weightAdjust = Math.round(weight * 10) / 10;
// if (opts.d2_npc_enable_rounding) {
// weightAdjust = Math.round(weight * 10) / 10;
// } else {
// weightAdjust = Math.floor(weight * 100) / 100;
// }
const text = prompt.replace(/[\[\]{}]+/g, '');
return `(${text}:${weightAdjust})`;
}
}
/////////////////////////////////////////////
/////////////////////////////////////////////
/////////////////////////////////////////////
/**
* プロンプト変換ダイアログ
*/
class D2_PromptConvertDialog {
static CSS_FILEPATH = "./extensions/D2-nodes-ComfyUI/css/D2_PromptConvertDialog.css";
container = undefined;
constructor() {
this._createDialog();
loadCssFile(D2_PromptConvertDialog.CSS_FILEPATH);
}
/**
* モーダルの表示
*/
showModal() {
// this.container.showModal();
this.container.style.display = "block";
}
_createDialog() {
this.container = document.createElement("div");
this.container.classList.add("comfy-modal", "d2-prompt-convert");
document.body.appendChild(this.container);
const content = document.createElement("div");
content.classList.add("d2-prompt-convert__content");
this.container.appendChild(content);
const sdPrompt = D2_PromptConvertDialog.createPromptArea("input StableDiffusion Prompt");
content.appendChild(sdPrompt);
const naiPrompt = D2_PromptConvertDialog.createPromptArea("Input NovelAI Prompt");
content.appendChild(naiPrompt);
// SD > NAI 変換ボタン
const sdToNaiBtn = D2_PromptConvertDialog.createButton("SD to NAI", () => {
const prompt = sdPrompt.value;
const newPrompt = D2_PromptConvert.convertToNai(prompt);
naiPrompt.value = newPrompt;
});
content.appendChild(sdToNaiBtn);
// NAI > SD 変換ボタン
const naiToSdBtn = D2_PromptConvertDialog.createButton("NAI to SD", () => {
const prompt = naiPrompt.value;
const newPrompt = D2_PromptConvert.convertToSd(prompt);
sdPrompt.value = newPrompt;
});
content.appendChild(naiToSdBtn);
// SDクリップボード
const copySdBtn = D2_PromptConvertDialog.createButton("Send SD to Clipboard", () => {
sdPrompt.select();
document.execCommand("copy");
});
content.appendChild(copySdBtn);
// NAIクリップボード
const copyNaiBtn = D2_PromptConvertDialog.createButton("Send NAI to Clipboard", () => {
naiPrompt.select();
document.execCommand("copy");
});
content.appendChild(copyNaiBtn);
// 閉じるボタン
const closeBtn = document.createElement("button");
closeBtn.classList.add("d2-prompt-convert__close-btn");
closeBtn.textContent = "CLOSE";
closeBtn.addEventListener("click", () => {
// container.close();
this.container.style.display = "none";
});
content.appendChild(closeBtn);
}
/**
* プロンプトエリア作成
* @param {string} placeholder
* @returns HTMLElement
*/
static createPromptArea(placeholder) {
const textArea = document.createElement("textarea");
textArea.classList.add("comfy-multiline-input", "d2-prompt-convert__prompt-area");
textArea.placeholder = placeholder;
return textArea;
}
/**
* ボタン作成
* @param {string} text
* @param {function} onClick
* @returns
*/
static createButton(text, onClick) {
const btn = document.createElement("button");
btn.classList.add("d2-prompt-convert__btn");
btn.textContent = text;
btn.addEventListener("click", () => {
onClick();
});
return btn;
}
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
/**
* ダイアログ表示ボタン
*/
class D2_PromptConvertButton {
floatContainer = undefined;
dialog = undefined;
constructor() {
// フロートコンテナ
this.floatContainer = new D2_FloatContainer("D2_PromptConvertBUtton", 50, 100);
// ダイアログ
this.dialog = new D2_PromptConvertDialog();
this._createButton();
// 表示切り替え
const visible = app.ui.settings.getSettingValue("D2.PromptConvertButton.Visible", false);
this.changeVisible(visible);
}
/**
* 表示切り替え
*/
changeVisible(bool) {
this.floatContainer.changeVisible(bool);
}
/**
* ボタン作成
*/
_createButton() {
const button = document.createElement("button");
button.classList.add("p-button");
button.textContent = "Prompt convert";
this.floatContainer.addButton(button);
button.addEventListener("click", () => {
this.dialog.showModal();
});
}
}
(function () {
const promptConvertButton = new D2_PromptConvertButton();
app.ui.settings.addSetting({
id: "D2.PromptConvertButton.Visible",
name: "Show prompt convert button",
type: "boolean",
defaultValue: false,
onChange(value) {
promptConvertButton.changeVisible(value);
},
});
})();