Save accumulator without rerunning workflow

This commit is contained in:
2026-06-25 16:27:56 +02:00
parent cd076b3c02
commit 7675bf3bea
3 changed files with 53 additions and 15 deletions
+17
View File
@@ -394,6 +394,7 @@ try:
accumulator_delete_entries, accumulator_delete_entries,
accumulator_list_entries, accumulator_list_entries,
accumulator_move_entry, accumulator_move_entry,
accumulator_save_entries,
) )
from .prompt_builder import ( from .prompt_builder import (
build_camera_config_json, build_camera_config_json,
@@ -471,6 +472,7 @@ except ImportError:
accumulator_delete_entries, accumulator_delete_entries,
accumulator_list_entries, accumulator_list_entries,
accumulator_move_entry, accumulator_move_entry,
accumulator_save_entries,
) )
from prompt_builder import ( from prompt_builder import (
build_camera_config_json, build_camera_config_json,
@@ -583,6 +585,21 @@ if PromptServer is not None and web is not None:
except Exception as exc: except Exception as exc:
return web.json_response({"error": str(exc)}, status=400) return web.json_response({"error": str(exc)}, status=400)
@PromptServer.instance.routes.post("/sxcp/accumulator/save")
async def sxcp_accumulator_save(request):
try:
payload = await request.json()
result = accumulator_save_entries(
store_key=str(payload.get("store_key") or ""),
save_path=str(payload.get("save_path") or "sxcp_accumulator"),
filename_prefix=str(payload.get("filename_prefix") or "sxcp_accum"),
clear_after_save=bool(payload.get("clear_after_save")),
preview_limit=int(payload.get("preview_limit") or 0),
)
return web.json_response(result)
except Exception as exc:
return web.json_response({"error": str(exc)}, status=400)
@PromptServer.instance.routes.post("/sxcp/accumulator/move") @PromptServer.instance.routes.post("/sxcp/accumulator/move")
async def sxcp_accumulator_move(request): async def sxcp_accumulator_move(request):
try: try:
+25
View File
@@ -317,6 +317,31 @@ def accumulator_delete_entries(
return result return result
def accumulator_save_entries(
store_key: str,
save_path: str = "sxcp_accumulator",
filename_prefix: str = "sxcp_accum",
clear_after_save: bool = False,
preview_limit: int = 0,
) -> dict[str, Any]:
key = str(store_key or "").strip()
if not key:
raise ValueError("store_key is required for accumulator save")
store = _ACCUMULATOR_STORES.setdefault(key, [])
saved_paths = _save_images_to_folder(store, save_path, filename_prefix, None, None)
if saved_paths and bool(clear_after_save):
store.clear()
result = accumulator_list_entries(key, preview_limit=preview_limit)
result["saved_paths"] = saved_paths
result["saved"] = len(saved_paths)
result["cleared_after_save"] = bool(saved_paths and clear_after_save)
result["status"] = (
f"{result.get('status', '')}; saved={len(saved_paths)}"
f"{'; cleared_after_save' if saved_paths and clear_after_save else ''}"
)
return result
def accumulator_move_entry( def accumulator_move_entry(
store_key: str, store_key: str,
preview_key: str = "", preview_key: str = "",
+11 -15
View File
@@ -594,26 +594,22 @@ async function clearStore(node) {
} }
async function saveBatch(node) { async function saveBatch(node) {
const saveWidget = widget(node, "save_batch"); const key = storeKey(node);
if (!saveWidget) { if (!key) {
alert("Missing save_batch widget."); alert("Set the same explicit store_key on the Accumulator and Accumulator Preview first.");
return; return;
} }
setWidgetValue(node, "finished", true);
setWidgetValue(node, "save_batch", true);
node.setDirtyCanvas?.(true, true);
try { try {
try { const data = await postJson("/sxcp/accumulator/save", actionPayload(node, {
await app.queuePrompt(0, 1); store_key: key,
} catch (_err) { save_path: widget(node, "save_path")?.value || "sxcp_accumulator",
await app.queuePrompt(0); filename_prefix: widget(node, "filename_prefix")?.value || "sxcp_accum",
} clear_after_save: !!widget(node, "clear_after_save")?.value,
}));
applyData(node, data, data.status || `saved=${data.saved || 0}`);
} catch (err) { } catch (err) {
console.error(`[${EXTENSION}] save queue failed`, err); console.error(`[${EXTENSION}] direct save failed`, err);
alert(`Save failed: ${err}`); alert(`Save failed: ${err}`);
} finally {
setWidgetValue(node, "save_batch", false);
node.setDirtyCanvas?.(true, true);
} }
} }