Integration fixes: BaseLevelEntry with full map path, ECC_Camera traces, PP disable, thumbnails
- Replace TArray<FString> BaseLevels with TArray<FPS_Editor_BaseLevelEntry> (DisplayName + MapPath) so levels in subfolders (e.g. /Game/Maps/Warehouse) are found correctly - Add BaseLevelPathMap lookup in MainWidget for Play, combo, and scene load - Add optional MapPath parameter to LoadBaseLevelAsSublevel - Switch all LineTrace channels from ECC_Visibility to ECC_Camera for better compatibility with characters that have Visibility disabled - Add W key binding as alias for Z (translate mode) for AZERTY convenience - Disable sublevel PostProcessVolume WeightedBlendables on load to avoid stencil conflicts with the plugin's selection outline - Fix thumbnail generation: NeverStream + TEXTUREGROUP_UI + force alpha to 255 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -163,6 +163,7 @@ void APS_Editor_Pawn::CreateInputActions()
|
||||
IA_TranslateMode = NewObject<UInputAction>(this, TEXT("IA_TranslateMode"));
|
||||
IA_TranslateMode->ValueType = EInputActionValueType::Boolean;
|
||||
EditorMappingContext->MapKey(IA_TranslateMode, EKeys::Z);
|
||||
EditorMappingContext->MapKey(IA_TranslateMode, EKeys::W);
|
||||
|
||||
IA_RotateMode = NewObject<UInputAction>(this, TEXT("IA_RotateMode"));
|
||||
IA_RotateMode->ValueType = EInputActionValueType::Boolean;
|
||||
@@ -609,7 +610,7 @@ void APS_Editor_Pawn::HandleLeftClickStarted(const FInputActionValue& Value)
|
||||
FCollisionQueryParams SplineParams;
|
||||
SplineParams.AddIgnoredActor(this);
|
||||
const FVector TraceEnd = RayOrigin + RayDir * 100000.0f;
|
||||
if (GetWorld()->LineTraceSingleByChannel(SplineHit, RayOrigin, TraceEnd, ECC_Visibility, SplineParams))
|
||||
if (GetWorld()->LineTraceSingleByChannel(SplineHit, RayOrigin, TraceEnd, ECC_Camera, SplineParams))
|
||||
{
|
||||
if (Spline->IsCenterCube(SplineHit.GetComponent()))
|
||||
{
|
||||
@@ -670,7 +671,7 @@ void APS_Editor_Pawn::HandleLeftClickStarted(const FInputActionValue& Value)
|
||||
LineParams.AddIgnoredActor(this);
|
||||
const FVector TraceEnd = RayOrigin + RayDir * 100000.0f;
|
||||
|
||||
if (GetWorld()->LineTraceSingleByChannel(LineHit, RayOrigin, TraceEnd, ECC_Visibility, LineParams))
|
||||
if (GetWorld()->LineTraceSingleByChannel(LineHit, RayOrigin, TraceEnd, ECC_Camera, LineParams))
|
||||
{
|
||||
for (APS_Editor_SplineActor* Spline : TubeCandidates)
|
||||
{
|
||||
@@ -730,7 +731,7 @@ void APS_Editor_Pawn::HandleLeftClickStarted(const FInputActionValue& Value)
|
||||
const FVector AddEnd = RayOrigin + RayDir * 100000.0f;
|
||||
|
||||
FVector ClickPos;
|
||||
if (GetWorld()->LineTraceSingleByChannel(AddHit, RayOrigin, AddEnd, ECC_Visibility, AddParams))
|
||||
if (GetWorld()->LineTraceSingleByChannel(AddHit, RayOrigin, AddEnd, ECC_Camera, AddParams))
|
||||
{
|
||||
ClickPos = AddHit.ImpactPoint + FVector(0.0f, 0.0f, 5.0f);
|
||||
}
|
||||
@@ -1106,7 +1107,7 @@ void APS_Editor_Pawn::HandleSnapToGround(const FInputActionValue& Value)
|
||||
}
|
||||
}
|
||||
|
||||
if (GetWorld()->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECC_Visibility, Params))
|
||||
if (GetWorld()->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECC_Camera, Params))
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("PS_Editor: SnapToGround - PointLoc=%s, HitZ=%.2f, HitActor=%s, HitComp=%s"),
|
||||
*PointLoc.ToString(), Hit.ImpactPoint.Z,
|
||||
@@ -1291,7 +1292,7 @@ void APS_Editor_Pawn::ComputeOrbitFocalPoint()
|
||||
FCollisionQueryParams Params;
|
||||
Params.AddIgnoredActor(this);
|
||||
|
||||
if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params))
|
||||
if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Camera, Params))
|
||||
{
|
||||
OrbitFocalPoint = Hit.ImpactPoint;
|
||||
OrbitDistance = FVector::Dist(Start, OrbitFocalPoint);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "PS_Editor_SplineActor.h"
|
||||
#include "PS_Editor_PointPlaceable.h"
|
||||
#include "Engine/LevelStreamingDynamic.h"
|
||||
#include "Engine/PostProcessVolume.h"
|
||||
#include "PS_Editor_GameInstanceSubsystem.h"
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "GameFramework/GameStateBase.h"
|
||||
@@ -61,7 +62,17 @@ void APS_Editor_PlayerController::BeginPlay()
|
||||
UE_LOG(LogTemp, Log, TEXT("PS_Editor: Restoring from subsystem - BaseLevel='%s', Scenario='%s'"),
|
||||
*Sub->PendingBaseLevel, *Sub->PendingScenarioName);
|
||||
|
||||
LoadBaseLevelAsSublevel(Sub->PendingBaseLevel);
|
||||
// Resolve full map path from MasterCatalog
|
||||
FString ResolvedMapPath;
|
||||
for (const FPS_Editor_BaseLevelEntry& Entry : Master->BaseLevels)
|
||||
{
|
||||
if (Entry.DisplayName == Sub->PendingBaseLevel)
|
||||
{
|
||||
ResolvedMapPath = Entry.MapPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LoadBaseLevelAsSublevel(Sub->PendingBaseLevel, ResolvedMapPath);
|
||||
|
||||
if (!Sub->PendingScenarioName.IsEmpty() && SpawnManager && SceneSerializer)
|
||||
{
|
||||
@@ -197,7 +208,7 @@ void APS_Editor_PlayerController::CancelPointPlacement()
|
||||
FinishPointPlacement();
|
||||
}
|
||||
|
||||
void APS_Editor_PlayerController::LoadBaseLevelAsSublevel(const FString& LevelName)
|
||||
void APS_Editor_PlayerController::LoadBaseLevelAsSublevel(const FString& LevelName, const FString& MapPath)
|
||||
{
|
||||
// Unload previous sublevel first
|
||||
if (CurrentSublevel)
|
||||
@@ -238,11 +249,14 @@ void APS_Editor_PlayerController::LoadBaseLevelAsSublevel(const FString& LevelNa
|
||||
return;
|
||||
}
|
||||
|
||||
// Use MapPath if provided, otherwise fall back to LevelName (legacy behavior)
|
||||
const FString& LevelToLoad = MapPath.IsEmpty() ? LevelName : MapPath;
|
||||
|
||||
// Load new sublevel
|
||||
bool bSuccess = false;
|
||||
CurrentSublevel = ULevelStreamingDynamic::LoadLevelInstance(
|
||||
GetWorld(),
|
||||
LevelName,
|
||||
LevelToLoad,
|
||||
FVector::ZeroVector,
|
||||
FRotator::ZeroRotator,
|
||||
bSuccess);
|
||||
@@ -252,11 +266,33 @@ void APS_Editor_PlayerController::LoadBaseLevelAsSublevel(const FString& LevelNa
|
||||
CurrentSublevel->SetShouldBeLoaded(true);
|
||||
CurrentSublevel->SetShouldBeVisible(true);
|
||||
CurrentBaseLevel = LevelName;
|
||||
UE_LOG(LogTemp, Log, TEXT("PS_Editor: Loaded sublevel '%s'"), *LevelName);
|
||||
|
||||
// Disable custom PP materials once sublevel actors are available
|
||||
CurrentSublevel->OnLevelShown.AddUniqueDynamic(this, &APS_Editor_PlayerController::DisableSublevelPostProcessMaterials);
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("PS_Editor: Loaded sublevel '%s' (path: '%s')"), *LevelName, *LevelToLoad);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("PS_Editor: Failed to load sublevel '%s'"), *LevelName);
|
||||
UE_LOG(LogTemp, Warning, TEXT("PS_Editor: Failed to load sublevel '%s' (path: '%s')"), *LevelName, *LevelToLoad);
|
||||
}
|
||||
}
|
||||
|
||||
void APS_Editor_PlayerController::DisableSublevelPostProcessMaterials()
|
||||
{
|
||||
if (!CurrentSublevel) return;
|
||||
|
||||
ULevel* Level = CurrentSublevel->GetLoadedLevel();
|
||||
if (!Level) return;
|
||||
|
||||
for (AActor* Actor : Level->Actors)
|
||||
{
|
||||
if (!Actor) continue;
|
||||
APostProcessVolume* PPVolume = Cast<APostProcessVolume>(Actor);
|
||||
if (!PPVolume) continue;
|
||||
|
||||
PPVolume->Settings.WeightedBlendables.Array.Empty();
|
||||
UE_LOG(LogTemp, Log, TEXT("PS_Editor: Disabled PP materials on '%s'"), *PPVolume->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +312,7 @@ void APS_Editor_PlayerController::HandleEditorClick(FVector2D ScreenPos, bool bA
|
||||
|
||||
const FVector End = WorldOrigin + WorldDirection * 100000.0f;
|
||||
FVector ClickWorldPos;
|
||||
if (GetWorld()->LineTraceSingleByChannel(Hit, WorldOrigin, End, ECC_Visibility, Params))
|
||||
if (GetWorld()->LineTraceSingleByChannel(Hit, WorldOrigin, End, ECC_Camera, Params))
|
||||
{
|
||||
ClickWorldPos = Hit.ImpactPoint + FVector(0.0f, 0.0f, 5.0f);
|
||||
}
|
||||
@@ -326,7 +362,7 @@ void APS_Editor_PlayerController::HandleEditorClick(FVector2D ScreenPos, bool bA
|
||||
TubeParams.AddIgnoredActor(GetPawn());
|
||||
const FVector TubeEnd = WorldOrigin + WorldDirection * 100000.0f;
|
||||
|
||||
if (GetWorld()->LineTraceSingleByChannel(TubeHit, WorldOrigin, TubeEnd, ECC_Visibility, TubeParams))
|
||||
if (GetWorld()->LineTraceSingleByChannel(TubeHit, WorldOrigin, TubeEnd, ECC_Camera, TubeParams))
|
||||
{
|
||||
if (Spline->IsSplineMesh(TubeHit.GetComponent()))
|
||||
{
|
||||
|
||||
@@ -47,9 +47,13 @@ public:
|
||||
UPROPERTY(BlueprintReadWrite, Category = "PS Editor")
|
||||
FString CurrentBaseLevel;
|
||||
|
||||
/** Load a base level as sublevel for visual context. Unloads previous sublevel. */
|
||||
/** Load a base level as sublevel for visual context. Unloads previous sublevel.
|
||||
* @param LevelName Display name stored in CurrentBaseLevel (used for scene filtering).
|
||||
* @param MapPath Full package path for LoadLevelInstance (e.g. "/Game/Maps/Warehouse").
|
||||
* If empty, LevelName is used as-is (legacy behavior).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS Editor")
|
||||
void LoadBaseLevelAsSublevel(const FString& LevelName);
|
||||
void LoadBaseLevelAsSublevel(const FString& LevelName, const FString& MapPath = TEXT(""));
|
||||
|
||||
// ---- Editor Mode (Normal / SplinePlacement) ----
|
||||
|
||||
@@ -119,5 +123,9 @@ private:
|
||||
UPROPERTY()
|
||||
TObjectPtr<ULevelStreamingDynamic> CurrentSublevel;
|
||||
|
||||
/** Disable custom post-process materials in the loaded sublevel to avoid stencil conflicts. */
|
||||
UFUNCTION()
|
||||
void DisableSublevelPostProcessMaterials();
|
||||
|
||||
void HandleEditorClick(FVector2D ScreenPos, bool bAdditive);
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ static void ConfigureGizmoComponent(UPrimitiveComponent* Comp)
|
||||
{
|
||||
Comp->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||
Comp->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||
Comp->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
|
||||
Comp->SetCollisionResponseToChannel(ECC_Camera, ECR_Block);
|
||||
Comp->SetCollisionObjectType(ECC_WorldDynamic);
|
||||
Comp->SetCastShadow(false);
|
||||
Comp->SetRenderCustomDepth(false);
|
||||
|
||||
@@ -127,7 +127,7 @@ void UPS_Editor_SelectionManager::HandleClickAtScreenPosition(FVector2D ScreenPo
|
||||
}
|
||||
|
||||
const FVector End = WorldOrigin + WorldDirection * 100000.0f;
|
||||
const bool bHit = PC->GetWorld()->LineTraceSingleByChannel(Hit, WorldOrigin, End, ECC_Visibility, Params);
|
||||
const bool bHit = PC->GetWorld()->LineTraceSingleByChannel(Hit, WorldOrigin, End, ECC_Camera, Params);
|
||||
|
||||
if (bHit && Hit.GetActor())
|
||||
{
|
||||
@@ -467,7 +467,7 @@ void UPS_Editor_SelectionManager::SnapSelectionToGround()
|
||||
Params.AddIgnoredActor(PC->GetPawn());
|
||||
if (Gizmo) Params.AddIgnoredActor(Gizmo);
|
||||
|
||||
if (Actor->GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params))
|
||||
if (Actor->GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Camera, Params))
|
||||
{
|
||||
FVector NewLocation = Hit.ImpactPoint;
|
||||
NewLocation.Z += BottomOffset;
|
||||
|
||||
@@ -85,11 +85,18 @@ void UPS_Editor_SpawnCatalog::CaptureAllThumbnails()
|
||||
|
||||
uint8* MipData = Texture->Source.LockMip(0);
|
||||
FMemory::Memcpy(MipData, PixelData.GetData(), PixelData.Num());
|
||||
// Force alpha to 255 — UE thumbnails may have zeroed alpha
|
||||
for (int32 Px = 0; Px < Width * Height; ++Px)
|
||||
{
|
||||
MipData[Px * 4 + 3] = 255;
|
||||
}
|
||||
Texture->Source.UnlockMip(0);
|
||||
|
||||
Texture->SRGB = true;
|
||||
Texture->CompressionSettings = TC_Default;
|
||||
Texture->MipGenSettings = TMGS_NoMipmaps;
|
||||
Texture->NeverStream = true;
|
||||
Texture->LODGroup = TEXTUREGROUP_UI;
|
||||
Texture->PostEditChange();
|
||||
Texture->UpdateResource();
|
||||
|
||||
|
||||
@@ -44,6 +44,28 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* A base level entry: display name + full map path.
|
||||
* The MapPath is used for OpenLevel and sublevel loading.
|
||||
* Example: DisplayName="Warehouse", MapPath="/Game/Maps/Warehouse"
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FPS_Editor_BaseLevelEntry
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
/** Display name shown in the editor combo box and used for scene filtering. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS Editor")
|
||||
FString DisplayName;
|
||||
|
||||
/**
|
||||
* Full map path used for OpenLevel and sublevel loading.
|
||||
* Example: "/Game/Maps/Warehouse"
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS Editor")
|
||||
FString MapPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Master catalog that groups multiple SpawnCatalogs.
|
||||
* Assign this to the PlayerController. Each sub-catalog can represent a domain
|
||||
@@ -60,10 +82,10 @@ public:
|
||||
TArray<TObjectPtr<UPS_Editor_SpawnCatalog>> Catalogs;
|
||||
|
||||
/**
|
||||
* List of base level names available for scene editing.
|
||||
* Used to filter saved scenes by level. Auto-matched by stripping "_Editor" from the current map name.
|
||||
* Example: "Warehouse", "Office", "Parking"
|
||||
* List of base levels available for scene editing.
|
||||
* DisplayName is used for UI display and scene filtering.
|
||||
* MapPath is the full package path for OpenLevel (e.g. "/Game/Maps/Warehouse").
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS Editor")
|
||||
TArray<FString> BaseLevels;
|
||||
TArray<FPS_Editor_BaseLevelEntry> BaseLevels;
|
||||
};
|
||||
|
||||
@@ -67,6 +67,11 @@ void UPS_Editor_SpawnManager::AddCatalog(UPS_Editor_SpawnCatalog* InCatalog)
|
||||
Resolved.Category = SpawnComp ? SpawnComp->Category : TEXT("Default");
|
||||
Resolved.Thumbnail = SpawnComp ? SpawnComp->Thumbnail : nullptr;
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("PS_Editor: Resolved '%s' - SpawnComp=%s, Thumbnail=%s"),
|
||||
*Resolved.DisplayName,
|
||||
SpawnComp ? TEXT("found") : TEXT("null"),
|
||||
Resolved.Thumbnail ? *Resolved.Thumbnail->GetPathName() : TEXT("null"));
|
||||
|
||||
ResolvedEntries.Add(Resolved);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,11 +111,18 @@ FReply FPS_Editor_SpawnableComponentCustomization::OnCaptureThumbnailClicked()
|
||||
|
||||
uint8* MipData = Texture->Source.LockMip(0);
|
||||
FMemory::Memcpy(MipData, PixelData.GetData(), PixelData.Num());
|
||||
// Force alpha to 255 — UE thumbnails may have zeroed alpha
|
||||
for (int32 Px = 0; Px < Width * Height; ++Px)
|
||||
{
|
||||
MipData[Px * 4 + 3] = 255;
|
||||
}
|
||||
Texture->Source.UnlockMip(0);
|
||||
|
||||
Texture->SRGB = true;
|
||||
Texture->CompressionSettings = TC_Default;
|
||||
Texture->MipGenSettings = TMGS_NoMipmaps;
|
||||
Texture->NeverStream = true;
|
||||
Texture->LODGroup = TEXTUREGROUP_UI;
|
||||
Texture->PostEditChange();
|
||||
Texture->UpdateResource();
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ APS_Editor_SplineActor::APS_Editor_SplineActor()
|
||||
SplineMeshComp->SetupAttachment(Root);
|
||||
SplineMeshComp->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||
SplineMeshComp->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||
SplineMeshComp->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
|
||||
SplineMeshComp->SetCollisionResponseToChannel(ECC_Camera, ECR_Block);
|
||||
SplineMeshComp->bUseComplexAsSimpleCollision = true;
|
||||
SplineMeshComp->SetCastShadow(false);
|
||||
|
||||
@@ -101,7 +101,7 @@ void APS_Editor_SplineActor::BeginPlay()
|
||||
CenterCube->SetWorldScale3D(FVector(CenterCubeScale));
|
||||
CenterCube->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||
CenterCube->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||
CenterCube->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
|
||||
CenterCube->SetCollisionResponseToChannel(ECC_Camera, ECR_Block);
|
||||
CenterCube->SetCastShadow(false);
|
||||
if (CenterCubeMat)
|
||||
{
|
||||
@@ -316,7 +316,7 @@ UStaticMeshComponent* APS_Editor_SplineActor::CreatePointHandle(const FVector& W
|
||||
// Collision for raycast
|
||||
Handle->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||
Handle->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||
Handle->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
|
||||
Handle->SetCollisionResponseToChannel(ECC_Camera, ECR_Block);
|
||||
|
||||
Handle->SetCastShadow(false);
|
||||
Handle->SetRenderInDepthPass(false);
|
||||
|
||||
@@ -624,8 +624,16 @@ TSharedRef<SWidget> UPS_Editor_MainWidget::BuildSceneButtons()
|
||||
EditorPC->bShowMouseCursor = false;
|
||||
EditorPC->SetInputMode(FInputModeGameOnly());
|
||||
|
||||
// Use full path to avoid confusion with sublevel instances
|
||||
FString MapPath = FString::Printf(TEXT("/Game/%s"), *BaseLevel);
|
||||
// Use full path from MasterCatalog, fallback to /Game/{name}
|
||||
FString MapPath;
|
||||
if (FString* Found = BaseLevelPathMap.Find(BaseLevel))
|
||||
{
|
||||
MapPath = *Found;
|
||||
}
|
||||
else
|
||||
{
|
||||
MapPath = FString::Printf(TEXT("/Game/%s"), *BaseLevel);
|
||||
}
|
||||
UGameplayStatics::OpenLevel(EditorPC, FName(*MapPath), true, TEXT(""));
|
||||
return FReply::Handled();
|
||||
})
|
||||
@@ -676,7 +684,12 @@ TSharedRef<SWidget> UPS_Editor_MainWidget::BuildSceneButtons()
|
||||
{
|
||||
if (EditorPC->CurrentBaseLevel != SceneLevelName)
|
||||
{
|
||||
EditorPC->LoadBaseLevelAsSublevel(SceneLevelName);
|
||||
FString SceneMapPath = SceneLevelName;
|
||||
if (FString* Found = BaseLevelPathMap.Find(SceneLevelName))
|
||||
{
|
||||
SceneMapPath = *Found;
|
||||
}
|
||||
EditorPC->LoadBaseLevelAsSublevel(SceneLevelName, SceneMapPath);
|
||||
CurrentLevelFilter = EditorPC->CurrentBaseLevel;
|
||||
for (const TSharedPtr<FString>& Opt : BaseLevelOptions)
|
||||
{
|
||||
@@ -748,7 +761,12 @@ TSharedRef<SWidget> UPS_Editor_MainWidget::BuildSceneButtons()
|
||||
SaveNameField->SetText(FText::GetEmpty());
|
||||
}
|
||||
|
||||
EditorPC->LoadBaseLevelAsSublevel(*Selected);
|
||||
FString SublevelPath = *Selected;
|
||||
if (FString* Found = BaseLevelPathMap.Find(*Selected))
|
||||
{
|
||||
SublevelPath = *Found;
|
||||
}
|
||||
EditorPC->LoadBaseLevelAsSublevel(*Selected, SublevelPath);
|
||||
CurrentLevelFilter = EditorPC->CurrentBaseLevel;
|
||||
|
||||
if (BaseLevelComboText.IsValid())
|
||||
@@ -834,9 +852,13 @@ void UPS_Editor_MainWidget::NativeConstruct()
|
||||
BaseLevelOptions.Add(MakeShared<FString>(TEXT("None")));
|
||||
if (UPS_Editor_MasterCatalog* Master = EditorPC->MasterCatalogAsset)
|
||||
{
|
||||
for (const FString& Level : Master->BaseLevels)
|
||||
for (const FPS_Editor_BaseLevelEntry& Entry : Master->BaseLevels)
|
||||
{
|
||||
BaseLevelOptions.Add(MakeShared<FString>(Level));
|
||||
BaseLevelOptions.Add(MakeShared<FString>(Entry.DisplayName));
|
||||
if (!Entry.MapPath.IsEmpty())
|
||||
{
|
||||
BaseLevelPathMap.Add(Entry.DisplayName, Entry.MapPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,7 +937,12 @@ void UPS_Editor_MainWidget::PopulateSceneList()
|
||||
{
|
||||
if (EditorPC->CurrentBaseLevel != SceneLevelName)
|
||||
{
|
||||
EditorPC->LoadBaseLevelAsSublevel(SceneLevelName);
|
||||
FString SceneMapPath = SceneLevelName;
|
||||
if (FString* Found = BaseLevelPathMap.Find(SceneLevelName))
|
||||
{
|
||||
SceneMapPath = *Found;
|
||||
}
|
||||
EditorPC->LoadBaseLevelAsSublevel(SceneLevelName, SceneMapPath);
|
||||
CurrentLevelFilter = EditorPC->CurrentBaseLevel;
|
||||
|
||||
for (const TSharedPtr<FString>& Opt : BaseLevelOptions)
|
||||
|
||||
@@ -75,6 +75,8 @@ private:
|
||||
TArray<TSharedPtr<FString>> BaseLevelOptions;
|
||||
TSharedPtr<STextBlock> BaseLevelComboText;
|
||||
FString CurrentLevelFilter;
|
||||
/** Maps DisplayName → full MapPath for base levels (from MasterCatalog). */
|
||||
TMap<FString, FString> BaseLevelPathMap;
|
||||
TArray<TSharedPtr<FSlateBrush>> CachedBrushes;
|
||||
|
||||
// Transform fields
|
||||
|
||||
Reference in New Issue
Block a user