Save accumulator without rerunning workflow
This commit is contained in:
+17
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user