Files

234 lines
6.9 KiB
JavaScript

import { COLORS } from "./constants.js";
import { createPresetManager } from "./preset_manager.js";
import {
drawGroupBorder,
findWidget,
registerNode,
setInputDotColor,
waitForWidgets,
} from "./utils.js";
// --- Constants ---
const NODE_NAME = "PromptFaceBuilder";
const COMBO_FIELDS = [
"pupils",
"eye_state",
"gaze",
"blush",
"mouth_state",
"mouth_expression",
"emotion",
"head_angle",
];
const EYE_FIELDS = ["pupils", "gaze"];
const EYEWEAR_FIELDS = ["eyewear_override"];
const NAIL_COLOR_FIELDS = ["nail_color_override"];
const BOOL_FIELDS = [
"show_eyes",
"show_eyewear",
"show_body_details",
"show_nails",
"show_makeup",
];
// --- Capture / Recall ---
const captureState = (node) => {
const state = {};
for (const field of COMBO_FIELDS) {
const w = findWidget(node, field);
if (w) state[field] = w.value ?? "";
}
for (const field of BOOL_FIELDS) {
const w = findWidget(node, field);
if (w) state[field] = w.value ?? false;
}
return state;
};
const recallState = (node, state) => {
for (const field of [...COMBO_FIELDS, ...BOOL_FIELDS]) {
if (!(field in state)) continue;
const w = findWidget(node, field);
if (!w) continue;
w.value = state[field];
w.callback?.(state[field]);
}
updateEyeVisibility(node, findWidget(node, "show_eyes")?.value ?? true);
updateEyewearVisibility(
node,
findWidget(node, "show_eyewear")?.value ?? true,
);
updatePiercingsVisibility(
node,
findWidget(node, "show_body_details")?.value ?? true,
);
const showNails = findWidget(node, "show_nails")?.value ?? true;
const showMakeup = findWidget(node, "show_makeup")?.value ?? true;
updateNailsVisibility(node, showNails, showMakeup);
updateMakeupVisibility(node, showNails, showMakeup);
if (node.graph) node.graph.setDirtyCanvas(true, true);
};
// --- Visibility helpers ---
const updateEyeVisibility = (node, value) => {
for (const field of EYE_FIELDS) {
const w = findWidget(node, field);
if (w) w.disabled = !value;
}
setInputDotColor(node, "eyes", value);
setInputDotColor(node, "eye_type", value);
if (node.graph) node.graph.setDirtyCanvas(true, true);
};
const updateEyewearVisibility = (node, value) => {
for (const field of EYEWEAR_FIELDS) {
const w = findWidget(node, field);
if (w) w.disabled = !value;
}
setInputDotColor(node, "eyewear", value);
if (node.graph) node.graph.setDirtyCanvas(true, true);
};
const updatePiercingsVisibility = (node, value) => {
setInputDotColor(node, "facial_piercings", value);
if (node.graph) node.graph.setDirtyCanvas(true, true);
};
const updateNailsVisibility = (node, showNails, showMakeup) => {
for (const field of NAIL_COLOR_FIELDS) {
const w = findWidget(node, field);
if (w) w.disabled = !showNails || !showMakeup;
}
setInputDotColor(node, "nail_type", showNails);
setInputDotColor(node, "nail_color", showNails && showMakeup);
if (node.graph) node.graph.setDirtyCanvas(true, true);
};
const updateMakeupVisibility = (node, showNails, showMakeup) => {
for (const field of NAIL_COLOR_FIELDS) {
const w = findWidget(node, field);
if (w) w.disabled = !showNails || !showMakeup;
}
setInputDotColor(node, "makeup", showMakeup);
setInputDotColor(node, "makeup_modifiers", showMakeup);
setInputDotColor(node, "nail_color", showNails && showMakeup);
if (node.graph) node.graph.setDirtyCanvas(true, true);
};
// --- Attach ---
const attachFaceBuilder = (node) => {
// --- Toggles ---
const showEyesWidget = findWidget(node, "show_eyes");
if (showEyesWidget) {
const original = showEyesWidget.callback;
showEyesWidget.callback = function (value) {
if (original) original.call(this, value);
updateEyeVisibility(node, value);
};
updateEyeVisibility(node, showEyesWidget.value ?? true);
}
const showEyewearWidget = findWidget(node, "show_eyewear");
if (showEyewearWidget) {
const original = showEyewearWidget.callback;
showEyewearWidget.callback = function (value) {
if (original) original.call(this, value);
updateEyewearVisibility(node, value);
};
updateEyewearVisibility(node, showEyewearWidget.value ?? true);
}
const showPiercingsWidget = findWidget(node, "show_body_details");
if (showPiercingsWidget) {
const original = showPiercingsWidget.callback;
showPiercingsWidget.callback = function (value) {
if (original) original.call(this, value);
updatePiercingsVisibility(node, value);
};
updatePiercingsVisibility(node, showPiercingsWidget.value ?? true);
}
const showNailsWidget = findWidget(node, "show_nails");
const showMakeupWidget = findWidget(node, "show_makeup");
if (showNailsWidget) {
const original = showNailsWidget.callback;
showNailsWidget.callback = function (value) {
if (original) original.call(this, value);
updateNailsVisibility(node, value, showMakeupWidget.value ?? true);
};
updateNailsVisibility(
node,
showNailsWidget.value ?? true,
showMakeupWidget.value ?? true,
);
}
if (showMakeupWidget) {
const original = showMakeupWidget.callback;
showMakeupWidget.callback = function (value) {
if (original) original.call(this, value);
updateMakeupVisibility(node, showNailsWidget.value ?? true, value);
};
updateMakeupVisibility(
node,
showNailsWidget.value ?? true,
showMakeupWidget.value ?? true,
);
}
// --- Borders ---
const groups = [
{ from: "show_eyes", to: "gaze" },
{ from: "show_eyewear", to: "eyewear_override" },
{ from: "show_body_details", to: "show_body_details" },
{ from: "show_nails", to: "nail_color_override" },
{ from: "show_makeup", to: "show_makeup" },
];
const original = node.onDrawForeground;
node.onDrawForeground = function (ctx) {
if (original) original.call(this, ctx);
for (const group of groups) {
drawGroupBorder(
ctx,
node,
group.from,
group.to,
COLORS.toggle_on,
COLORS.toggle_off,
);
}
};
// --- Preset manager ---
const { presetRow, exportImportRow } = createPresetManager(node, {
nodeLabel: NODE_NAME,
onCapture: () => captureState(node),
onRecall: (state) => recallState(node, state),
});
node.widgets.push(presetRow);
node.widgets.push(exportImportRow);
};
// --- Registration ---
registerNode(NODE_NAME, (node) => waitForWidgets(node, attachFaceBuilder));