Files
Naz dda9030abe 0.8.9 update
0.8.9 update
2025-08-31 14:20:31 +09:00

305 lines
8.6 KiB
JavaScript

import { app } from '../../../../scripts/app.js'
import { $el } from "../../../../scripts/ui.js";
let origProps = {};
export async function fetchJson(fileAddress) {
try {
const response = await fetch(fileAddress);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error(fileAddress + 'JSON 파일을 불러오는 중 오류 발생:', error);
return null;
}
}
export function findWidgetByName(node, widgetName) {
return node.widgets.find(widget => widget.name === widgetName);
}
const doesInputWithNameExist = (node, name) => {
//return node.inputs ? node.inputs.some((input) => input.name === name) : false;
return false;
};
export function updateNodeHeight(node) { node.setSize([node.size[0], node.computeSize()[1]]); }
export function toggleWidget(node, widget, show = false, suffix = "") {
if (!widget || doesInputWithNameExist(node, widget.name)) return;
// Store the original properties of the widget if not already stored
if (!origProps[widget.name]) {
origProps[widget.name] = { origType: widget.type, origComputeSize: widget.computeSize };
}
const origSize = node.size;
// Set the widget type and computeSize based on the show flag
widget.type = show ? origProps[widget.name].origType : "tschide" + suffix;
widget.computeSize = show ? origProps[widget.name].origComputeSize : () => [0, -4];
// Recursively handle linked widgets if they exist
widget.linkedWidgets?.forEach(w => toggleWidget(node, w, ":" + widget.name, show));
// Calculate the new height for the node based on its computeSize method
const height = show ? Math.max(node.computeSize()[1], origSize[1]) : node.size[1];
node.setSize([node.size[0], height]);
}
export function showMessage(short_msg, detail_msg) {
try {
app.extensionManager.toast.add({
severity: short_msg.toLowerCase(),
summary: short_msg,
detail: detail_msg,
life: 3500
});
}
catch {
// do nothing
}
}
export function addStylesheet(url) {
if (url.endsWith(".js")) {
url = url.substr(0, url.length - 2) + "css";
}
$el("link", {
parent: document.head,
rel: "stylesheet",
type: "text/css",
href: url.startsWith("http") ? url : getUrl(url),
});
}
export function getUrl(path, baseUrl) {
if (baseUrl) {
return new URL(path, baseUrl).toString();
} else {
return new URL("../" + path, import.meta.url).toString();
}
}
export async function loadImage(url) {
return new Promise((res, rej) => {
const img = new Image();
img.onload = res;
img.onerror = rej;
img.src = url;
});
}
export function addMenuHandler(nodeType, cb) {
const getOpts = nodeType.prototype.getExtraMenuOptions;
nodeType.prototype.getExtraMenuOptions = function () {
const r = getOpts.apply(this, arguments);
cb.apply(this, arguments);
return r;
};
}
// Utility functions
export function addNode(name, nextTo, options) {
options = { select: true, shiftX: 0, shiftY: 0, before: false, ...(options || {}) };
const node = LiteGraph.createNode(name);
app.graph.add(node);
node.pos = [
nextTo.pos[0] + options.shiftX,
nextTo.pos[1] + options.shiftY,
];
if (options.select) {
app.canvas.selectNode(node, false);
}
return node;
}
////////////////////////////////////////////////////////////////////////// COLOR////////////////////////////////////////////////////////////////////////////
export const hexToRGB = hex => {
// #RGB → #RRGGBB 확장
if (hex.length === 4) {
hex =
"#" +
hex[1] + hex[1] +
hex[2] + hex[2] +
hex[3] + hex[3];
}
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return { r, g, b };
};
export const rgbToHex = ({ r, g, b }, shorten = true) => {
const hex =
"#" +
r.toString(16).padStart(2, "0") +
g.toString(16).padStart(2, "0") +
b.toString(16).padStart(2, "0");
if (shorten) {
if (hex[1] === hex[2] && hex[3] === hex[4] && hex[5] === hex[6]) {
return "#" + hex[1] + hex[3] + hex[5];
}
}
return hex;
};
export function darkenHex(hex, amount = 6) {
const { r, g, b } = hexToRGB(hex);
const newR = Math.max(0, r - amount);
const newG = Math.max(0, g - amount);
const newB = Math.max(0, b - amount);
return rgbToHex({ r: newR, g: newG, b: newB });
}
// HEX → HSL 객체
const hexToHSL = h => {
h = h.replace(/^#/, '');
h = h.length < 6 ? [...h].map(c => c + c).join`` : h;
let r = parseInt(h.slice(0, 2), 16) / 255,
g = parseInt(h.slice(2, 4), 16) / 255,
b = parseInt(h.slice(4, 6), 16) / 255,
m = Math.max(r, g, b),
n = Math.min(r, g, b),
l = (m + n) / 2,
s = 0, H = 0;
if (m !== n) {
let d = m - n;
s = l > 0.5 ? d / (2 - m - n) : d / (m + n);
H = m === r ? (g - b) / d + (g < b ? 6 : 0) : m === g ? (b - r) / d + 2 : (r - g) / d + 4;
H *= 60;
}
return { h: H, s: s * 100, l: l * 100 };
}
// HSL 객체 → HEX
const hslToHex = ({ h, s, l }) => {
s /= 100; l /= 100;
const k = n => (n + h / 30) % 12,
a = s * Math.min(l, 1 - l),
f = n => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1))),
toH = x => x.toString(16).padStart(2, '0');
return `#${toH(Math.round(f(0) * 255))}${toH(Math.round(f(8) * 255))}${toH(Math.round(f(4) * 255))}`;
}
function overrideBackground_color(widget) {
// 이미 오버라이드 되어 있는지 확인
const desc = Object.getOwnPropertyDescriptor(widget, "background_color");
if (desc && (desc.get || desc.set)) {
return; // 이미 오버라이드 된 경우
}
widget._background_color = widget.background_color;
Object.defineProperty(widget, "background_color", {
get() {
return this._background_color;
},
set(value) {
this._background_color = value;
},
configurable: true,
});
}
export function flashWidget(node, widgets, maxL = 50, duration = 2000, delay = 300) {
if (!Array.isArray(widgets) || widgets.length === 0) return;
const orig_bg_list = [];
const minHSLList = [];
widgets.forEach((widget) => {
overrideBackground_color(widget);
orig_bg_list.push(widget.background_color);
minHSLList.push(hexToHSL(widget.background_color));
});
// 각 위젯마다 현재 HSL값 복사
const hslList = minHSLList.map((hsl) => ({ ...hsl }));
const start = performance.now();
// easing 함수
function easeInOutExpo(t) {
if (t === 0) return 0;
if (t === 1) return 1;
return t < 0.5
? Math.pow(2, 20 * t - 10) / 2
: (2 - Math.pow(2, -20 * t + 10)) / 2;
}
function step(time) {
let allDone = true;
widgets.forEach((widget, i) => {
const delayTime = i * delay;
const elapsed = time - start - delayTime;
let t = elapsed / duration;
if (t < 0) {
allDone = false; // 아직 시작 전
return;
}
if (t >= 1) {
// 원래 색으로 복원
widget.background_color = orig_bg_list[i];
return;
}
allDone = false; // 아직 애니메이션 진행 중
let eased;
if (t <= 0.5) {
eased = easeInOutExpo(t * 2);
hslList[i].l = minHSLList[i].l + (maxL - minHSLList[i].l) * eased;
} else {
eased = easeInOutExpo((t - 0.5) * 2);
hslList[i].l = maxL - (maxL - minHSLList[i].l) * eased;
}
widget.background_color = hslToHex(hslList[i]);
});
node.setDirtyCanvas(true, true);
if (!allDone) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
}
/*
function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}
// easeInOutQuart easing 함수
function easeInOutQuart(t) {
return t < 0.5
? 8 * t * t * t * t
: 1 - Math.pow(-2 * t + 2, 4) / 2;
}
// easeInOutExpo easing 함수
function easeInOutExpo(t) {
if (t === 0) return 0;
if (t === 1) return 1;
return t < 0.5
? Math.pow(2, 20 * t - 10) / 2
: (2 - Math.pow(2, -20 * t + 10)) / 2;
}
*/