Hi [mention removed] !
After looking at the Unreal Engine development branch, it doesn’t seem like they’re planning to implement anything like this in either 5.7 or 5.8. At the moment, there’s nothing in the codebase that supports it.
I dug a bit deeper into the problem and found a way to achieve what you want without modifying the engine. I’ll share the solution below in case it helps you and your team. This only needs to live inside an Editor module.
As a quick test, I created a custom settings object under Editor Settings and added a TMap to specify which classes should always open in the full Blueprint Editor. You can remove that part if you’d prefer to apply the behavior to all Blueprints.
UCLASS(config=EditorPerProjectUserSettings, meta=(DisplayName="My Blueprint Editor"))
class EM_SC_56_API UMyBlueprintEditorSettings : public UDeveloperSettings
{
GENERATED_BODY()
public:
/** If a Blueprint is Data-Only and its ParentClass matches (or derives from) the key, it will open the whole Blueprint Editor*/
UPROPERTY(EditAnywhere, config, Category="Overrides")
TMap<TSoftClassPtr<UObject>, bool> ForceFullEditorForDataOnlyParents;
virtual FName GetCategoryName() const override
{
return "My Blueprint Editor";
}
};
With Unreal FAssetTypeActions_Blueprint class, you can react when an asset is open inside the Editor:
FMyAssetTypeActions_Blueprint.h
class FMyAssetTypeActions_Blueprint : public FAssetTypeActions_Blueprint
{
public:
virtual void OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<class IToolkitHost> EditWithinLevelEditor) override;
private:
bool ShouldForceFullEditorFor(const class UBlueprint* BP) const;
};
FMyAssetTypeActions_Blueprint.cpp
#include "MyAssetTypeActions_Blueprint.h"
#include "BlueprintEditorModule.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "Modules/ModuleManager.h"
#include "MyBlueprintEditorSettings.h"
#include "Engine/Blueprint.h"
static bool CheckParentSuperclass(const UClass* Parent, const UClass* KeyClass)
{
for (const UClass* C = Parent; C; C = C->GetSuperClass())
{
if (C == KeyClass)
{
return true;
}
}
return false;
}
bool FMyAssetTypeActions_Blueprint::ShouldForceFullEditorFor(const UBlueprint* BP) const
{
if (!BP || !BP->ParentClass)
{
return false;
}
if (!FBlueprintEditorUtils::IsDataOnlyBlueprint(BP))
return false;
const UMyBlueprintEditorSettings* Settings = GetDefault<UMyBlueprintEditorSettings>();
if (!Settings)
return false;
for (const TPair<TSoftClassPtr<UObject>, bool>& Pair : Settings->ForceFullEditorForDataOnlyParents)
{
if (!Pair.Value)
continue;
UClass* KeyClass = Pair.Key.LoadSynchronous();
if (!KeyClass)
continue;
if (CheckParentSuperclass(BP->ParentClass, KeyClass))
return true;
}
return false;
}
void FMyAssetTypeActions_Blueprint::OpenAssetEditor(const TArray<UObject*>& InObjects,
TSharedPtr<IToolkitHost> EditWithinLevelEditor)
{
bool bAnyForced = false;
for (UObject* Obj : InObjects)
{
if (const UBlueprint* BP = Cast<UBlueprint>(Obj))
{
if (ShouldForceFullEditorFor(BP))
{
bAnyForced = true;
break;
}
}
}
if (!bAnyForced)
{
FAssetTypeActions_Blueprint::OpenAssetEditor(InObjects, EditWithinLevelEditor);
return;
}
FBlueprintEditorModule& KismetModule =
FModuleManager::LoadModuleChecked<FBlueprintEditorModule>("Kismet");
const EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone;
for (UObject* Obj : InObjects)
{
if (UBlueprint* BP = Cast<UBlueprint>(Obj))
{
if (ShouldForceFullEditorFor(BP))
{
// Open Full Blueprint Editor
KismetModule.CreateBlueprintEditor(Mode, EditWithinLevelEditor, BP, false);
}
else
{
TArray<UObject*> Single{ Obj };
FAssetTypeActions_Blueprint::OpenAssetEditor(Single, EditWithinLevelEditor);
}
}
else
{
TArray<UObject*> Single{ Obj };
FAssetTypeActions_Blueprint::OpenAssetEditor(Single, EditWithinLevelEditor);
}
}
}
After that, you only need to register the editor blueprint action. A good place to do it is in the StartupModule of the same editor module.
MyEditorModule.h
class FEM_SC_56Module : public IModuleInterface
{
TSharedPtr<IAssetTypeActions> BlueprintActions;
public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
MyEditorModule.cpp
void FEM_SC_56Module::StartupModule()
{
IAssetTools& AssetTools = FAssetToolsModule::GetModule().Get();
BlueprintActions = MakeShared<FMyAssetTypeActions_Blueprint>();
AssetTools.RegisterAssetTypeActions(BlueprintActions.ToSharedRef());
}
void FEM_SC_56Module::ShutdownModule()
{
if (FModuleManager::Get().IsModuleLoaded("AssetTools") && BlueprintActions.IsValid())
{
IAssetTools& AssetTools = FAssetToolsModule::GetModule().Get();
AssetTools.UnregisterAssetTypeActions(BlueprintActions.ToSharedRef());
}
}
Unfortunately, I can’t tell you whether it’s included or not, but so far I haven’t seen anything similar in the development branch. I hope this code can help you and thus avoid having to modify the engine.
Regards,
Joan