Answer to my own question which others might find useful.
I’ve discovered that there’s a concept of “const blueprints” (although someone at Epic doesn’t seem to know about them):
C:\P4\Engine\Source\Developer\BlueprintNativeCodeGen\Private\BlueprintNativeCodeGenModule.cpp(637): //BPTYPE_Const, // WTF is a "const" Blueprint?
A const blueprint class is declared in c++ with this:
UCLASS(Blueprintable, BlueprintType, **Const**)
class STONES_API UMyObject : public UObject
{
GENERATED_BODY()
};
Which seems to be what I need (pure data containers) from comments in Epic’s code:
/** Blueprint that is const during execution (no state graph and methods cannot modify member variables). */
BPTYPE_Const UMETA(DisplayName="Const Blueprint Class"),
To allow these to be edited while playing the game, I’ve just changed this function:
bool FBlueprintEditor::InEditingMode() const
{
// allow editing of const blueprints even when playing game
UBlueprint* Blueprint = GetBlueprintObj();
if (Blueprint && Blueprint->BlueprintType == BPTYPE_Const)
return true;
return !InDebuggingMode();
}
Now I can tweak my settings while playing the game and everything seems to work correctly.
Unfortunately this flag is only applied at blueprint creation time so this doesn’t immediately work for already created blueprints.
I’ve made it retrospectively apply this setting upon compilation but this is rather dangerous as it doesn’t check that the blueprint meets the const requirements so I don’t necessarily recommend it:
void FKismetEditorUtilities::CompileBlueprint(UBlueprint* BlueprintObj, bool bIsRegeneratingOnLoad, bool bSkipGarbageCollection, bool bSaveIntermediateProducts, FCompilerResultsLog* pResults, bool bSkeletonUpToDate, bool bBatchCompile, bool bAddInstrumentation)
{
FSecondsCounterScope Timer(BlueprintCompileAndLoadTimerData);
BP_SCOPED_COMPILER_EVENT_STAT(EKismetCompilerStats_CompileBlueprint);
// Wipe the PreCompile log, any generated messages are now irrelevant
BlueprintObj->PreCompileLog.Reset();
// Broadcast pre-compile
#if WITH_EDITOR
{
BP_SCOPED_COMPILER_EVENT_STAT(EKismetCompilerStats_BroadcastPrecompile);
if(GEditor && GIsEditor)
{
GEditor->BroadcastBlueprintPreCompile(BlueprintObj);
** // allow the const flag to be retrospecively applied
if ((BlueprintObj->BlueprintType == BPTYPE_Normal) && (BlueprintObj->ParentClass->HasAnyClassFlags(CLASS_Const)))
{
BlueprintObj->BlueprintType = BPTYPE_Const;
}**
}
}
#endif
I think the first part of this is a legitimate change so it would be nice if Epic could make it official.