Good evening/night/morning/Easter to all kind souls!
I’m completely stumped, and have spent 2 days with a headache. The code works perfectly as expected when the editor is fresh, but if I stop PIE and start again it fails repeatedly until I restart the editor. Then it works once and fails again. I need the owning player to work with focus, which means Gamepad navigation only works on the first PIE session. The (blueprint) error that started my quest is:
The PlayerController is not a valid local player so it can't focus on {widget}
I know it’s not a CommonUI bug because I have another branch when I was learning CommonUI that I kept while rebuilding the structure, and the PlayerController is properly propagated. I have compared the code far and wide, and fundamentally there’s really no difference…
I did something somewhere to the Editor that is kept in memory between PIE sessions for some reason, and I don’t know Unreal enough to understand what I did to it. I didn’t even think it was possible for any data to survive?!
The culprit:
MoodyViewportLayout.h file
UCLASS(Abstract)
class MOODYUI_API UMoodyViewportLayout : public UCommonUserWidget {
GENERATED_BODY()
UPROPERTY(meta=(BindWidget))
TObjectPtr<UCommonActivatableWidgetStack> MenuStack;
public:
UFUNCTION(BlueprintCallable)
void PushMenu(const TSubclassOf<UMoodyActivatableMenu> Menu) const;
};
MoodyViewportLayout.cpp file
void UMoodyViewportLayout::PushMenu(const TSubclassOf<UMoodyActivatableMenu> Menu) const {
// UMoodyActivatableMenu is a direct subclass of UCommonActivatableWidget
UMoodyActivatableMenu* NewMenu = MenuStack->AddWidget<UMoodyActivatableMenu>(Menu);
APlayerController* NMO = NewMenu->GetOwningPlayer();
DLOG("MenuStack Owner: " + MenuStack->GetOwningPlayer()->GetName())
DLOG("New Menu Owner: " + (NMO?NMO->GetName():"___null___"))
}
The code that initializes the UI
// This code is inside a UWorldSubsystem, called from a direct subclass of APlayerController
void UMoodyUISubsystem::SpawnUI(APlayerController* PlayerController, UMoodyUIDefinitionDataAsset* UIDefinition) {
UMoodyViewportLayout* InViewportLayout = UIDefinition->GetViewportLayout();
TSubclassOf<UMoodyActivatableMenu> InRootMenu = UIDefinition->GetRootMenu();
if (InViewportLayout) {
RootLayout = InViewportLayout;
RootLayout->SetOwningPlayer(PlayerController);
RootLayout->AddToViewport();
if (InRootMenu) RootLayout->PushMenu(InRootMenu);
}
}
Output on the first PIE session
LogSurvivalGame: Display: Standalone : MenuStack Owner: BP_MainMenuPlayerController_C_0 [in UMoodyViewportLayout::PushMenu (13)]
LogSurvivalGame: Display: Standalone : New Menu Owner: BP_MainMenuPlayerController_C_0 [in UMoodyViewportLayout::PushMenu (14)]
Output on any other PIE session
LogSurvivalGame: Display: Standalone : MenuStack Owner: BP_MainMenuPlayerController_C_0 [in UMoodyViewportLayout::PushMenu (13)]
LogSurvivalGame: Display: Standalone : New Menu Owner: ___null___ [in UMoodyViewportLayout::PushMenu (14)]
I have tried an insane amount of things so I won’t list them all (Because I forgot most of them) including some I tried while rubber ducking this post. But amongst them:
- Deleted everything but Config, Source, Content, .vsconfig and the .uproject and rebuilt the whole thing
- Rebuilt the whole UI on the blueprint side and it still does it
- Used SetOwningLocalPlayer and SetOwningPlayer
- Tried casting to its parent with
AddWidget<UCommonActivatableWidget>()
- Tried changing the DataAsset and code to actually use UCommonActivatableWidget instead
- Tried using the following Lambda, it did change the owner in the logging but did nothing for focus and its error:
MenuStack->AddWidget<UMoodyActivatableMenu>(Menu, [this](UMoodyActivatableMenu& Menu) {
Menu.SetOwningPlayer(this->GetOwningPlayer());
});
- I have spent a lot of time digging in the code looking left and right
- It works perfectly in packaged build (which is not surprising)
- I have been through 12 stages of depression
- I was thinking about making a brand new project and importing my code in it since the other branch works, but i’m also thinking that this is not a reasonable approach because it will become a nightmare once the project grows a little, so i’ll keep busting my brain on my keyboard to learn how to fix that editor…
Other random tidbids of info:
- Unreal Engine 5.5.4
- The plugins I have installed in my .uproject are the same in both branches: ModelingToolsEditorMode, CommonUI, ModelViewViewModel.
- The private modules in the module’s Build.cs: Core, CoreUObject, Engine, EnhancedInput, Slate, SlateCore, UMG, CommonUI, MoodyCore (only has my *LOG macros)
- This is me giving up for the night. I prefer warning those who are kind enough to try and help this poor soul, I will be able to try again in about 20h.
- If you want any other information, or if you want the code, I can post the whole UI module somewhere tomorrow
Thank you very, very much
ItsMoodyDoom