Hi
You’re right that save_level(save_all=true) could show the Save Content dialog. That was a bug on our side, not an engine limitation, and it’s fixed in the next release. We were calling FEditorFileUtils::SaveDirtyPackages with bPromptUserToSave=true.
To answer the underlying question: yes, there are recommended built-in C++ APIs for non-modal saves.
For saving all dirty packages, you can use the same function with prompting disabled:
FEditorFileUtils::SaveDirtyPackages(
/*bPromptUserToSave=*/false,
/*bSaveMapPackages=*/true,
/*bSaveContentPackages=*/true,
/*bFastSave=*/false,
/*bNotifyNoPackagesSaved=*/false,
/*bCanBeDeclined=*/false);
Alternatively, you can use the scripting-safe wrapper:
UEditorLoadingAndSavingUtils::SaveDirtyPackages(
bSaveMapPackages,
bSaveContentPackages);
This is defined in FileHelpers.h and is what the Python unreal.EditorLoadingAndSavingUtils calls map to, so you should get the same behavior as your Python workaround without leaving C++.
For a known list of packages, use either:
UEditorLoadingAndSavingUtils::SavePackages(
Packages,
/*bOnlyDirty=*/true);
or:
FEditorFileUtils::PromptForCheckoutAndSave(
Packages,
bCheckDirty,
/*bPromptToSave=*/false,
...);
Despite the name, bPromptToSave=false skips the dialog.
To enumerate dirty packages first, use:
FEditorFileUtils::GetDirtyWorldPackages();
FEditorFileUtils::GetDirtyContentPackages();
As an extra safeguard, you can wrap the save in:
TGuardValue<bool> Guard(GIsRunningUnattendedScript, true);
This helps suppress nested modal UI, such as source-control checkout prompts, and matches what the editor’s own scripting layer does. Running the editor with -unattended has the same global effect.