Fix editor restore: init order, combo callback, scenario name

- SceneSerializer created before subsystem check (was nullptr crash)
- ComboBox OnSelectionChanged ignores ESelectInfo::Direct (programmatic)
  to prevent NativeConstruct from clearing the just-loaded scenario
- SaveNameField restored from LastEditedScenarioName on return
- Added ReturnToEditor/OpenEditor to GameInstanceSubsystem
- EditorMapName auto-saved on Play for return navigation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 16:23:32 +02:00
parent 9c43fd523a
commit aa4313057c
2 changed files with 29 additions and 7 deletions

View File

@@ -32,10 +32,15 @@ void APS_Editor_PlayerController::BeginPlay()
UndoManager = NewObject<UPS_Editor_UndoManager>(this); UndoManager = NewObject<UPS_Editor_UndoManager>(this);
// Create spawn manager and load catalogs from MasterCatalog // Create spawn manager, scene serializer
SpawnManager = NewObject<UPS_Editor_SpawnManager>(this); SpawnManager = NewObject<UPS_Editor_SpawnManager>(this);
SpawnManager->Initialize(this); SpawnManager->Initialize(this);
SceneSerializer = NewObject<UPS_Editor_SceneSerializer>(this);
SceneSerializer->SetSelectionManager(SelectionManager);
// Load catalogs from MasterCatalog
if (UPS_Editor_MasterCatalog* Master = MasterCatalogAsset.LoadSynchronous()) if (UPS_Editor_MasterCatalog* Master = MasterCatalogAsset.LoadSynchronous())
{ {
for (const TSoftObjectPtr<UPS_Editor_SpawnCatalog>& CatalogRef : Master->Catalogs) for (const TSoftObjectPtr<UPS_Editor_SpawnCatalog>& CatalogRef : Master->Catalogs)
@@ -53,10 +58,16 @@ void APS_Editor_PlayerController::BeginPlay()
{ {
if (!Sub->PendingBaseLevel.IsEmpty()) if (!Sub->PendingBaseLevel.IsEmpty())
{ {
UE_LOG(LogTemp, Log, TEXT("PS_Editor: Restoring from subsystem - BaseLevel='%s', Scenario='%s'"),
*Sub->PendingBaseLevel, *Sub->PendingScenarioName);
LoadBaseLevelAsSublevel(Sub->PendingBaseLevel); LoadBaseLevelAsSublevel(Sub->PendingBaseLevel);
if (!Sub->PendingScenarioName.IsEmpty() && SpawnManager)
if (!Sub->PendingScenarioName.IsEmpty() && SpawnManager && SceneSerializer)
{ {
SceneSerializer->LoadScene(Sub->PendingScenarioName, SpawnManager); bool bLoaded = SceneSerializer->LoadScene(Sub->PendingScenarioName, SpawnManager);
UE_LOG(LogTemp, Log, TEXT("PS_Editor: LoadScene('%s') = %s"),
*Sub->PendingScenarioName, bLoaded ? TEXT("OK") : TEXT("FAILED"));
} }
Sub->PendingScenarioName.Empty(); Sub->PendingScenarioName.Empty();
Sub->PendingBaseLevel.Empty(); Sub->PendingBaseLevel.Empty();
@@ -72,9 +83,6 @@ void APS_Editor_PlayerController::BeginPlay()
UE_LOG(LogTemp, Warning, TEXT("PS_Editor: No MasterCatalog assigned.")); UE_LOG(LogTemp, Warning, TEXT("PS_Editor: No MasterCatalog assigned."));
} }
SceneSerializer = NewObject<UPS_Editor_SceneSerializer>(this);
SceneSerializer->SetSelectionManager(SelectionManager);
// After undo/redo, deselect hidden actors and refresh gizmo // After undo/redo, deselect hidden actors and refresh gizmo
UndoManager->OnUndoRedo.AddWeakLambda(this, [this]() UndoManager->OnUndoRedo.AddWeakLambda(this, [this]()
{ {

View File

@@ -584,9 +584,11 @@ TSharedRef<SWidget> UPS_Editor_MainWidget::BuildSceneButtons()
[ [
SAssignNew(BaseLevelCombo, SComboBox<TSharedPtr<FString>>) SAssignNew(BaseLevelCombo, SComboBox<TSharedPtr<FString>>)
.OptionsSource(&BaseLevelOptions) .OptionsSource(&BaseLevelOptions)
.OnSelectionChanged_Lambda([this](TSharedPtr<FString> Selected, ESelectInfo::Type) .OnSelectionChanged_Lambda([this](TSharedPtr<FString> Selected, ESelectInfo::Type SelectInfo)
{ {
if (!Selected.IsValid()) return; if (!Selected.IsValid()) return;
// Ignore programmatic selection (e.g. from NativeConstruct init)
if (SelectInfo == ESelectInfo::Direct) return;
APS_Editor_PlayerController* EditorPC = Cast<APS_Editor_PlayerController>(GetOwningPlayer()); APS_Editor_PlayerController* EditorPC = Cast<APS_Editor_PlayerController>(GetOwningPlayer());
if (!EditorPC) return; if (!EditorPC) return;
@@ -706,6 +708,18 @@ void UPS_Editor_MainWidget::NativeConstruct()
} }
} }
} }
// Restore scenario name in save field (from subsystem LastEdited)
if (UGameInstance* GI = EditorPC->GetGameInstance())
{
if (UPS_Editor_GameInstanceSubsystem* Sub = GI->GetSubsystem<UPS_Editor_GameInstanceSubsystem>())
{
if (!Sub->LastEditedScenarioName.IsEmpty() && SaveNameField.IsValid())
{
SaveNameField->SetText(FText::FromString(Sub->LastEditedScenarioName));
}
}
}
} }
PopulateSceneList(); PopulateSceneList();