287 lines
8.2 KiB
JavaScript
287 lines
8.2 KiB
JavaScript
import { COLORS } from "./constants.js";
|
|
import { attachInlineSelector } from "./inline_selector.js";
|
|
import { createPresetManager } from "./preset_manager.js";
|
|
import {
|
|
drawGroupBorder,
|
|
findWidget,
|
|
hideWidget,
|
|
hideWidgetInput,
|
|
registerNode,
|
|
setInputDotColor,
|
|
waitForWidgets,
|
|
} from "./utils.js";
|
|
|
|
// --- Constants ---
|
|
|
|
const NODE_NAME = "PromptPoseBuilder";
|
|
|
|
const COMBO_FIELDS = [
|
|
"stance",
|
|
"posture",
|
|
"arms",
|
|
"first_arm",
|
|
"second_arm",
|
|
"hands",
|
|
"first_hand",
|
|
"second_hand",
|
|
"holding",
|
|
"legs",
|
|
"feet",
|
|
];
|
|
|
|
const SPLIT_ARMS_FIELDS = ["first_arm", "second_arm"];
|
|
const SINGLE_ARM_FIELDS = ["arms"];
|
|
const SPLIT_HANDS_FIELDS = ["first_hand", "second_hand"];
|
|
const SINGLE_HAND_FIELDS = ["hands"];
|
|
const BOOL_FIELDS = [
|
|
"split_arms",
|
|
"split_hands",
|
|
"show_body_details",
|
|
"show_upper_body",
|
|
"show_lower_body",
|
|
];
|
|
|
|
// --- Capture / Recall ---
|
|
|
|
const captureState = (node) => {
|
|
const state = {};
|
|
for (const field of COMBO_FIELDS) {
|
|
const w = findWidget(node, field);
|
|
if (w) state[field] = w.value ?? "";
|
|
}
|
|
|
|
// Action inline selector
|
|
const actionSelected = findWidget(node, "action_selected");
|
|
if (actionSelected) state["action_selected"] = actionSelected.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]);
|
|
}
|
|
|
|
// Action
|
|
if ("action_selected" in state) {
|
|
const w = findWidget(node, "action_selected");
|
|
if (w) {
|
|
w.value = state["action_selected"];
|
|
w.callback?.(state["action_selected"]);
|
|
}
|
|
actionSelector?.renderColored();
|
|
}
|
|
|
|
updateArmsVisibility(node, findWidget(node, "split_arms")?.value ?? false);
|
|
updateHandsVisibility(
|
|
node,
|
|
findWidget(node, "split_hands")?.value ?? false,
|
|
);
|
|
updatePiercingsVisibility(
|
|
node,
|
|
findWidget(node, "show_body_details")?.value ?? true,
|
|
);
|
|
updateUpperBodyVisibility(
|
|
node,
|
|
findWidget(node, "show_upper_body")?.value ?? true,
|
|
);
|
|
updateLowerBodyVisibility(
|
|
node,
|
|
findWidget(node, "show_lower_body")?.value ?? true,
|
|
);
|
|
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
// --- Visibility helpers ---
|
|
|
|
const updateArmsVisibility = (node, splitArms) => {
|
|
for (const field of SPLIT_ARMS_FIELDS) {
|
|
const w = findWidget(node, field);
|
|
if (!w) continue;
|
|
if (splitArms) {
|
|
w.type = "combo";
|
|
w.computeSize = null;
|
|
} else {
|
|
hideWidget(w);
|
|
}
|
|
}
|
|
for (const field of SINGLE_ARM_FIELDS) {
|
|
const w = findWidget(node, field);
|
|
if (!w) continue;
|
|
if (!splitArms) {
|
|
w.type = "combo";
|
|
w.computeSize = null;
|
|
} else {
|
|
hideWidget(w);
|
|
}
|
|
}
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
const updateHandsVisibility = (node, splitHands) => {
|
|
for (const field of SPLIT_HANDS_FIELDS) {
|
|
const w = findWidget(node, field);
|
|
if (!w) continue;
|
|
if (splitHands) {
|
|
w.type = "combo";
|
|
w.computeSize = null;
|
|
} else {
|
|
hideWidget(w);
|
|
}
|
|
}
|
|
for (const field of SINGLE_HAND_FIELDS) {
|
|
const w = findWidget(node, field);
|
|
if (!w) continue;
|
|
if (!splitHands) {
|
|
w.type = "combo";
|
|
w.computeSize = null;
|
|
} else {
|
|
hideWidget(w);
|
|
}
|
|
}
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
const updatePiercingsVisibility = (node, value) => {
|
|
setInputDotColor(node, "body_piercings", value);
|
|
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
const updateUpperBodyVisibility = (node, value) => {
|
|
setInputDotColor(node, "upper_body", value);
|
|
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
const updateLowerBodyVisibility = (node, value) => {
|
|
setInputDotColor(node, "lower_body", value);
|
|
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
// --- Attach ---
|
|
|
|
const attachPoseBuilder = (node) => {
|
|
let actionSelector = null;
|
|
|
|
// --- Toggles ---
|
|
|
|
const splitArmsWidget = findWidget(node, "split_arms");
|
|
if (splitArmsWidget) {
|
|
const original = splitArmsWidget.callback;
|
|
splitArmsWidget.callback = function (value) {
|
|
if (original) original.call(this, value);
|
|
updateArmsVisibility(node, value);
|
|
};
|
|
updateArmsVisibility(node, splitArmsWidget.value ?? false);
|
|
}
|
|
|
|
const splitHandsWidget = findWidget(node, "split_hands");
|
|
if (splitHandsWidget) {
|
|
const original = splitHandsWidget.callback;
|
|
splitHandsWidget.callback = function (value) {
|
|
if (original) original.call(this, value);
|
|
updateHandsVisibility(node, value);
|
|
};
|
|
updateHandsVisibility(node, splitHandsWidget.value ?? false);
|
|
}
|
|
|
|
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 showUpperBodyWidget = findWidget(node, "show_upper_body");
|
|
if (showUpperBodyWidget) {
|
|
const original = showUpperBodyWidget.callback;
|
|
showUpperBodyWidget.callback = function (value) {
|
|
if (original) original.call(this, value);
|
|
updateUpperBodyVisibility(node, value);
|
|
};
|
|
updateUpperBodyVisibility(node, showUpperBodyWidget.value ?? true);
|
|
}
|
|
|
|
const showLowerBodyWidget = findWidget(node, "show_lower_body");
|
|
if (showLowerBodyWidget) {
|
|
const original = showLowerBodyWidget.callback;
|
|
showLowerBodyWidget.callback = function (value) {
|
|
if (original) original.call(this, value);
|
|
updateLowerBodyVisibility(node, value);
|
|
};
|
|
updateLowerBodyVisibility(node, showLowerBodyWidget.value ?? true);
|
|
}
|
|
|
|
const actionOptionsWidget = findWidget(node, "action_options");
|
|
const actionSelectedWidget = findWidget(node, "action_selected");
|
|
if (actionOptionsWidget && actionSelectedWidget) {
|
|
hideWidget(actionSelectedWidget, true);
|
|
hideWidgetInput(node, actionSelectedWidget);
|
|
actionSelector = attachInlineSelector(
|
|
node,
|
|
actionOptionsWidget,
|
|
actionSelectedWidget,
|
|
{
|
|
placeholder: "action",
|
|
},
|
|
);
|
|
}
|
|
|
|
// --- Borders ---
|
|
|
|
const original = node.onDrawForeground;
|
|
node.onDrawForeground = function (ctx) {
|
|
if (original) original.call(this, ctx);
|
|
|
|
const splitArms = findWidget(node, "split_arms")?.value ?? false;
|
|
const splitHands = findWidget(node, "split_hands")?.value ?? false;
|
|
const groups = [
|
|
{ from: "split_arms", to: splitArms ? "second_arm" : "arms" },
|
|
{ from: "split_hands", to: splitHands ? "second_hand" : "hands" },
|
|
{ from: "show_body_details", to: "show_body_details" },
|
|
{ from: "show_upper_body", to: "show_upper_body" },
|
|
{ from: "show_lower_body", to: "show_lower_body" },
|
|
];
|
|
|
|
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, attachPoseBuilder));
|