Skip to content

Commit

Permalink
Copy LevelStreaming actors in editor mode to level
Browse files Browse the repository at this point in the history
  • Loading branch information
shun126 committed Apr 19, 2023
1 parent 5cc837a commit ca5b081
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 167 deletions.
22 changes: 10 additions & 12 deletions Source/DungeonGenerator/Private/DungeonGenerateActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,15 +341,18 @@ void ADungeonGenerateActor::DestroyImplementation()
*/
void ADungeonGenerateActor::MovePlayerStart()
{
if (mDungeonGeneratorCore != nullptr)
if (DungeonGenerateParameter && DungeonGenerateParameter->IsMovePlayerStartToStartingPoint())
{
if (OnMovePlayerStart.IsBound())
if (mDungeonGeneratorCore)
{
OnMovePlayerStart.Broadcast(mDungeonGeneratorCore->GetStartLocation());
}
else
{
mDungeonGeneratorCore->MovePlayerStart();
if (OnMovePlayerStart.IsBound())
{
OnMovePlayerStart.Broadcast(mDungeonGeneratorCore->GetStartLocation());
}
else
{
mDungeonGeneratorCore->MovePlayerStart();
}
}
}
}
Expand Down Expand Up @@ -378,11 +381,6 @@ void ADungeonGenerateActor::Tick(float DeltaSeconds)
{
mPostGenerated = true;
PostGenerateImplementation();

#if !WITH_EDITOR
// ティック無効化
PrimaryActorTick.bCanEverTick = false;
#endif
}

// 部屋の生成通知
Expand Down
5 changes: 5 additions & 0 deletions Source/DungeonGenerator/Private/DungeonGenerateParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,11 @@ const FDungeonDoorActorParts* UDungeonGenerateParameter::SelectDoorParts(const s
return SelectParts(gridIndex, grid, random, DoorParts, DoorPartsSelectionMethod);
}

bool UDungeonGenerateParameter::IsMovePlayerStartToStartingPoint() const noexcept
{
return MovePlayerStartToStartingPoint;
}

const FDungeonActorPartsWithDirection& UDungeonGenerateParameter::GetStartParts() const
{
return StartParts;
Expand Down
129 changes: 95 additions & 34 deletions Source/DungeonGenerator/Private/DungeonGeneratorCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All Rights Reserved.
#include "DungeonGeneratorCore.h"
#include "DungeonGenerateParameter.h"
#include "DungeonDoor.h"
#include "DungeonLevelStreamingDynamic.h"
#include "DungeonRoomProps.h"
#include "DungeonRoomSensor.h"
#include "Core/Debug/Debug.h"
Expand All @@ -28,6 +29,7 @@ All Rights Reserved.

#if WITH_EDITOR
// UnrealEd
#include <EditorLevelUtils.h>
#include <Builders/CubeBuilder.h>
#endif

Expand Down Expand Up @@ -1021,9 +1023,6 @@ bool CDungeonGeneratorCore::RequestStreamLevel(const FSoftObjectPath& levelPath,
if (requestStreamLevel != mRequestLoadStreamLevels.end())
return false;

if (mLoadedStreamLevels.Contains(levelPath))
return false;

mRequestLoadStreamLevels.emplace_back(levelPath, levelLocation);

return true;
Expand All @@ -1036,44 +1035,89 @@ void CDungeonGeneratorCore::AsyncLoadStreamLevels()
LoadStreamLevelParameter requestStreamLevel = mRequestLoadStreamLevels.front();
mRequestLoadStreamLevels.pop_front();

LoadStreamLevel(requestStreamLevel.mPath, requestStreamLevel.mLocation);
if (FindLoadedStreamLevel(requestStreamLevel.mPath) == nullptr)
{
UWorld* world = mWorld.Get();
if (IsValid(world))
{
const FTransform transform(FRotator::ZeroRotator, requestStreamLevel.mLocation);
ULevelStreamingDynamic::FLoadLevelInstanceParams parameter(world, requestStreamLevel.mPath.GetLongPackageName(), transform);
parameter.OptionalLevelStreamingClass = UDungeonLevelStreamingDynamic::StaticClass();
bool bSuccess = false;
ULevelStreamingDynamic* levelStreaming = ULevelStreamingDynamic::LoadLevelInstance(parameter, bSuccess);
if (bSuccess && IsValid(levelStreaming))
{
mLoadedStreamLevels.Add(levelStreaming);

DUNGEON_GENERATOR_LOG(TEXT("Load Level (%s)"), *requestStreamLevel.mPath.GetLongPackageName());
}
else
{
DUNGEON_GENERATOR_ERROR(TEXT("Failed to Load Level (%s)"), *requestStreamLevel.mPath.GetLongPackageName());
}
}
}
}
}

void CDungeonGeneratorCore::SyncLoadStreamLevels()
{
for (const auto& requestStreamLevel : mRequestLoadStreamLevels)
UWorld* world = mWorld.Get();
if (IsValid(world))
{
LoadStreamLevel(requestStreamLevel.mPath, requestStreamLevel.mLocation);
}
mRequestLoadStreamLevels.clear();
}
TArray<AActor*> moveActors;

void CDungeonGeneratorCore::LoadStreamLevel(const FSoftObjectPath& levelPath, const FVector& levelLocation)
{
if (!mLoadedStreamLevels.Contains(levelPath))
{
UWorld* world = mWorld.Get();
if (IsValid(world))
for (const auto& requestStreamLevel : mRequestLoadStreamLevels)
{
bool bSuccess;
/*ULevelStreamingDynamic* levelStreaming = */ ULevelStreamingDynamic::LoadLevelInstanceBySoftObjectPtr(
world,
TSoftObjectPtr<UWorld>(levelPath),
levelLocation,
FRotator::ZeroRotator,
bSuccess
);
if (bSuccess)
if (FindLoadedStreamLevel(requestStreamLevel.mPath))
continue;

const FTransform transform(FRotator::ZeroRotator, requestStreamLevel.mLocation);
ULevelStreamingDynamic::FLoadLevelInstanceParams parameter(world, requestStreamLevel.mPath.GetLongPackageName(), transform);
parameter.OptionalLevelStreamingClass = UDungeonLevelStreamingDynamic::StaticClass();
bool bSuccess = false;
ULevelStreamingDynamic* levelStreaming = ULevelStreamingDynamic::LoadLevelInstance(parameter, bSuccess);
if (bSuccess && IsValid(levelStreaming))
{
mLoadedStreamLevels.Emplace(levelPath);
DUNGEON_GENERATOR_LOG(TEXT("Load Level (%s)"), *levelPath.GetLongPackageName());
levelStreaming->bShouldBlockOnLoad = true;
world->FlushLevelStreaming();
//world->UpdateLevelStreaming();

ULevel* loadedLevel = levelStreaming->GetLoadedLevel();
if (IsValid(loadedLevel))
{
#if WITH_EDITOR
FString path, filename, extension;
FPaths::Split(levelStreaming->PackageNameToLoad.ToString(), path, filename, extension);
#endif
for (AActor* actor : loadedLevel->Actors)
{
actor->Tags.Add(GetDungeonGeneratorTag());
#if WITH_EDITOR
const FName folderPath(FString(TEXT("Dungeon/Levels/")) + filename);
actor->SetFolderPath(folderPath);
#endif
}

moveActors.Append(loadedLevel->Actors);
}

mLoadedStreamLevels.Add(levelStreaming);

DUNGEON_GENERATOR_LOG(TEXT("Load Level (%s)"), *requestStreamLevel.mPath.GetLongPackageName());
}
else
{
DUNGEON_GENERATOR_ERROR(TEXT("Failed to Load Level (%s)"), *levelPath.GetLongPackageName());
DUNGEON_GENERATOR_ERROR(TEXT("Failed to Load Level (%s)"), *requestStreamLevel.mPath.GetLongPackageName());
}
}

if (moveActors.Num() > 0)
{
EditorLevelUtils::MoveActorsToLevel(moveActors, world->PersistentLevel);
}

mRequestLoadStreamLevels.clear();
}
}

Expand All @@ -1084,30 +1128,47 @@ void CDungeonGeneratorCore::UnloadStreamLevels()
UWorld* world = mWorld.Get();
if (IsValid(world))
{
for (const auto& levelPath : mLoadedStreamLevels)
for (const TSoftObjectPtr<ULevelStreamingDynamic>& streamLevel : mLoadedStreamLevels)
{
FLatentActionInfo LatentInfo;
UGameplayStatics::UnloadStreamLevelBySoftObjectPtr(world, TSoftObjectPtr<UWorld>(levelPath), LatentInfo, false);
world->RemoveStreamingLevel(streamLevel.Get());
}
mLoadedStreamLevels.Empty();
}
}

void CDungeonGeneratorCore::UnloadStreamLevel(const FSoftObjectPath& levelPath)
{
SyncLoadStreamLevels();

UWorld* world = mWorld.Get();
if (IsValid(world))
{
if (mLoadedStreamLevels.Contains(levelPath))
for (int32 i = 0; i < mLoadedStreamLevels.Num(); ++i)
{
FLatentActionInfo LatentInfo;
UGameplayStatics::UnloadStreamLevelBySoftObjectPtr(world, TSoftObjectPtr<UWorld>(levelPath), LatentInfo, false);
const TSoftObjectPtr<ULevelStreamingDynamic>& loadedStreamLevel = mLoadedStreamLevels[i];
if (loadedStreamLevel->PackageNameToLoad == levelPath.GetAssetPathName())
{
world->RemoveStreamingLevel(loadedStreamLevel.Get());

mLoadedStreamLevels.Remove(levelPath);
mLoadedStreamLevels.RemoveAt(i);
break;
}
}
}
}

TSoftObjectPtr<const ULevelStreamingDynamic> CDungeonGeneratorCore::FindLoadedStreamLevel(const FSoftObjectPath& levelPath) const
{
for (const TSoftObjectPtr<const ULevelStreamingDynamic>& loadedStreamLevel : mLoadedStreamLevels)
{
if (loadedStreamLevel.IsValid())
{
if (loadedStreamLevel->PackageNameToLoad == levelPath.GetAssetPathName())
return loadedStreamLevel;
}
}
return nullptr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
#if WITH_EDITOR
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "DungeonLevelStreamingDynamic.h"

UDungeonLevelStreamingDynamic::UDungeonLevelStreamingDynamic(const FObjectInitializer& initializer)
: Super(initializer)
{
}
6 changes: 6 additions & 0 deletions Source/DungeonGenerator/Public/DungeonGenerateParameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject

const FDungeonDoorActorParts* SelectDoorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const;

bool IsMovePlayerStartToStartingPoint() const noexcept;

const FDungeonActorPartsWithDirection& GetStartParts() const;

const FDungeonActorPartsWithDirection& GetGoalParts() const;
Expand Down Expand Up @@ -371,6 +373,10 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject
UPROPERTY(EditAnywhere, Category = "DungeonGenerator|Door", BlueprintReadWrite)
TArray<FDungeonDoorActorParts> DoorParts;

// Move PlayerStart to the starting point.
UPROPERTY(EditAnywhere, Category = "DungeonGenerator|Door", BlueprintReadWrite)
bool MovePlayerStartToStartingPoint = true;

// starting point
UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite)
FDungeonActorPartsWithDirection StartParts;
Expand Down
6 changes: 4 additions & 2 deletions Source/DungeonGenerator/Public/DungeonGeneratorCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ All Rights Reserved.

// Forward declaration
class UDungeonGenerateParameter;
class ULevelStreamingDynamic;
class UStaticMesh;
class ANavMeshBoundsVolume;
class AStaticMeshActor;
Expand Down Expand Up @@ -181,8 +182,8 @@ class DUNGEONGENERATOR_API CDungeonGeneratorCore final : public std::enable_shar
void AsyncLoadStreamLevels();
void SyncLoadStreamLevels();
void UnloadStreamLevels();
void LoadStreamLevel(const FSoftObjectPath& levelPath, const FVector& levelLocation);
void UnloadStreamLevel(const FSoftObjectPath& levelPath);
TSoftObjectPtr<const ULevelStreamingDynamic> FindLoadedStreamLevel(const FSoftObjectPath& levelPath) const;

////////////////////////////////////////////////////////////////////////////
UTexture2D* GenerateMiniMapTexture(uint32_t worldToTextureScale, uint32_t textureWidthHeight, uint32_t currentLevel) const;
Expand Down Expand Up @@ -222,7 +223,8 @@ class DUNGEONGENERATOR_API CDungeonGeneratorCore final : public std::enable_shar
};

std::list<LoadStreamLevelParameter> mRequestLoadStreamLevels;
TSet<FSoftObjectPath> mLoadedStreamLevels;
TArray<TSoftObjectPtr<ULevelStreamingDynamic>> mLoadedStreamLevels;


// friend class
friend class ADungeonGenerateActor;
Expand Down
26 changes: 26 additions & 0 deletions Source/DungeonGenerator/Public/DungeonLevelStreamingDynamic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <CoreMinimal.h>
#include <Engine/LevelStreamingDynamic.h>
#include "DungeonLevelStreamingDynamic.generated.h"

class ULevelStreamingDynamic;

UCLASS(Blueprintable, BlueprintType)
class DUNGEONGENERATOR_API UDungeonLevelStreamingDynamic : public ULevelStreamingDynamic
{
GENERATED_BODY()

public:
/*
constructor
*/
explicit UDungeonLevelStreamingDynamic(const FObjectInitializer& initializer);

/*
destructor
*/
virtual ~UDungeonLevelStreamingDynamic() = default;

//virtual bool ShouldBeAlwaysLoaded() const override { return true; }
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ UDungeonGenerateParameterTypeActions::UDungeonGenerateParameterTypeActions(EAsse

FColor UDungeonGenerateParameterTypeActions::GetTypeColor() const
{
return FColor::Orange;
return FColor::Emerald;
}

void UDungeonGenerateParameterTypeActions::OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<class IToolkitHost> EditWithinLevelEditor)
Expand Down

0 comments on commit ca5b081

Please sign in to comment.