diff --git a/CHANGELOG.md b/CHANGELOG.md
index 299c5e4..3063c48 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
# Change Log - Procedural 3D Dungeon Generator Plug-in
+## 20250903-1.7.7 (60)
+### Changes
+* Add DungeonRoomSensorDatabase
+* Fixed several bugs
+### 変更点
+* DungeonRoomSensorDatabaseを追加
+* いくつかの不具合を修正
+
+## 20250903-1.7.6 (59)
+### Changes
+* Removed access to editor functions while in standalone mode.
+* Fixed several bugs
+### 変更点
+* スタンドアローンモード中にエディタ機能へアクセスしていたので削除
+* いくつかの不具合を修正
+
## 20250831-1.7.5 (58)
### Changes
* Enable/disable control of shadow generation in point light derived classes changed from per-partition to per-light.
diff --git a/Content/Maps/Demonstration.umap b/Content/Maps/Demonstration.umap
index c16bc8c..59bc59d 100644
Binary files a/Content/Maps/Demonstration.umap and b/Content/Maps/Demonstration.umap differ
diff --git a/DungeonGenerator.uplugin b/DungeonGenerator.uplugin
index 0a088a6..8a76e38 100644
--- a/DungeonGenerator.uplugin
+++ b/DungeonGenerator.uplugin
@@ -1,7 +1,7 @@
{
"FileVersion": 3,
- "Version": 58,
- "VersionName": "1.7.5",
+ "Version": 60,
+ "VersionName": "1.7.7",
"FriendlyName": "Dungeon Generator",
"Description": "Procedural 3d dungeon generator plugin. Easy generation of levels, mini-maps and missions.",
"Category": "Procedural Systems",
diff --git a/README.md b/README.md
index d5da62e..dc2448b 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,6 @@
[](https://github.com/shun126/DungeonGenerator/blob/main/LICENSE)
@@ -16,7 +10,7 @@
[](https://github.com/shun126/DungeonGenerator/stargazers)
[](https://youtu.be/1igd4pls5x8)
-Please visit our website for full feature list: [https://happy-game-dev.undo.jp/](https://happy-game-dev.undo.jp/plugins/DungeonGenerator/)
+Please visit our website for full feature list: [https://happy-game-dev.undo.jp/](https://happy-game-dev.undo.jp/plugins/DungeonGenerator/index.html)

@@ -66,7 +60,7 @@ The foundational generation algorithm you shared was a major source of inspirati
* Open Unreal Engine Editor and create a project using the First Person template or Third Person template.
* Install the Dungeon Generator plugin via Epic Games Launcher, or copy it to the `Plugins` directory of your project.
* Enable the plugin content.
-* Open `Plugins/Dungeon Generator/Contents/Demonstration`.
+* Open `Plugins/Dungeon Generator/Contents/Maps/Demonstration`.

@@ -80,11 +74,11 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
Or, [Fab](https://fab.com/s/f5587c55bad0) is releasing it under Epic license. If you need a license other than the GPL, please consider it. Proceeds will be used to fund the development of our game.
# 👀 See also
+* [Issues](https://github.com/shun126/UE5-DungeonGeneratorDemo/issues)
+* [Discussions](https://github.com/shun126/UE5-DungeonGeneratorDemo/discussions)
* [Wiki](https://github.com/shun126/UE5-DungeonGeneratorDemo/wiki)
* [DeepWiki](https://deepwiki.com/shun126/DungeonGenerator)
* [Doxygen](https://happy-game-dev.undo.jp/_doxygen/dungeon_generator/index.html)
-* [Issues](https://github.com/shun126/UE5-DungeonGeneratorDemo/issues)
-* [Discussions](https://github.com/shun126/UE5-DungeonGeneratorDemo/discussions)
The [Fab](https://fab.com/s/f5587c55bad0) version includes the following enhancements.
* Sub-levels can be applied as dungeon rooms
@@ -97,6 +91,8 @@ The [Fab](https://fab.com/s/f5587c55bad0) version includes the following enhance
This is an easy to use. Simply drop the DungeonGenerateActor into your level, set the grid scale and number of rooms and start generating out your structures. Please read the [Wiki](https://github.com/shun126/UE5-DungeonGeneratorDemo/wiki) for more information.
+Please visit our website for full feature list: [https://happy-game-dev.undo.jp/](https://happy-game-dev.undo.jp/plugins/DungeonGenerator/index.html)
+
# 😀 Authors
* Nonbiri ([X.com](https://x.com/happy_game_dev) / [YouTube](https://www.youtube.com/channel/UCkLXe57GpUyaOoj2ycREU1Q))
* Shun Moriya ([X.com](https://x.com/monjiro1972))
diff --git a/Source/DungeonGenerator/Private/Core/Generator.cpp b/Source/DungeonGenerator/Private/Core/Generator.cpp
index 1a5d081..00e496d 100644
--- a/Source/DungeonGenerator/Private/Core/Generator.cpp
+++ b/Source/DungeonGenerator/Private/Core/Generator.cpp
@@ -1273,6 +1273,7 @@ namespace dungeon
uint8_t depthRatioFromStart = 0;
if (GetDeepestDepthFromStart() > 0)
{
+ // TODO: ダンジョンの深さを0~255に正規化する関数を検討してください
float depthFromStart = static_cast(room->GetDepthFromStart());
depthFromStart /= static_cast(GetDeepestDepthFromStart());
depthRatioFromStart = static_cast(depthFromStart * 255.f);
@@ -1536,7 +1537,6 @@ namespace dungeon
int32 count = static_cast(std::sqrt(static_cast(room->GetRect().Area())));
if (count >= 5)
{
- count /= 2;
for (int32 i = 0; i < count; ++i)
{
const int32 x = mGenerateParameter.GetRandom()->Get(room->GetLeft(), room->GetRight());
diff --git a/Source/DungeonGenerator/Private/Core/RoomGeneration/Room.h b/Source/DungeonGenerator/Private/Core/RoomGeneration/Room.h
index f60c99a..a99d157 100644
--- a/Source/DungeonGenerator/Private/Core/RoomGeneration/Room.h
+++ b/Source/DungeonGenerator/Private/Core/RoomGeneration/Room.h
@@ -80,7 +80,7 @@ namespace dungeon
識別子を取得
@return 識別子
*/
- const Identifier& GetIdentifier() const noexcept;
+ const Identifier GetIdentifier() const noexcept;
/**
X座標を取得
diff --git a/Source/DungeonGenerator/Private/Core/RoomGeneration/Room.inl b/Source/DungeonGenerator/Private/Core/RoomGeneration/Room.inl
index 0c0b68d..00a3a26 100644
--- a/Source/DungeonGenerator/Private/Core/RoomGeneration/Room.inl
+++ b/Source/DungeonGenerator/Private/Core/RoomGeneration/Room.inl
@@ -10,7 +10,7 @@ All Rights Reserved.
namespace dungeon
{
- inline const Identifier& Room::GetIdentifier() const noexcept
+ inline const Identifier Room::GetIdentifier() const noexcept
{
return mIdentifier;
}
diff --git a/Source/DungeonGenerator/Private/DungeonGenerateActor.cpp b/Source/DungeonGenerator/Private/DungeonGenerateActor.cpp
index b173b34..b479891 100644
--- a/Source/DungeonGenerator/Private/DungeonGenerateActor.cpp
+++ b/Source/DungeonGenerator/Private/DungeonGenerateActor.cpp
@@ -60,6 +60,11 @@ void ADungeonGenerateActor::PostInitializeComponents()
// Calling the parent class
Super::PostInitializeComponents();
+ if (AutoGenerateAtStart == true)
+ {
+ PostGenerateImplementation();
+ }
+
//if (GetNetMode() != NM_Standalone)
if (GetLocalRole() == ROLE_Authority)
{
@@ -201,16 +206,6 @@ void ADungeonGenerateActor::PreGenerateImplementation()
return;
}
- if (GetActorRotation().Equals(FRotator::ZeroRotator) == false)
- {
- DUNGEON_GENERATOR_ERROR(TEXT("The actor's rotation is not applied in the generated dungeon."));
- }
-
- if (GetActorScale().Equals(FVector::OneVector) == false)
- {
- DUNGEON_GENERATOR_ERROR(TEXT("The actor's scale is not applied in the generated dungeon."));
- }
-
Dispose(true);
// インスタンスメッシュを登録
@@ -313,6 +308,19 @@ void ADungeonGenerateActor::PreGenerateImplementation()
EndDungeonGeneration();
}
+void ADungeonGenerateActor::PostGenerateImplementation() const
+{
+ if (GetActorRotation().Equals(FRotator::ZeroRotator) == false)
+ {
+ DUNGEON_GENERATOR_ERROR(TEXT("The actor's rotation is not applied in the generated dungeon."));
+ }
+
+ if (GetActorScale().Equals(FVector::OneVector) == false)
+ {
+ DUNGEON_GENERATOR_ERROR(TEXT("The actor's scale is not applied in the generated dungeon."));
+ }
+}
+
void ADungeonGenerateActor::Dispose(const bool flushStreamLevels)
{
if (IsGenerated())
@@ -349,6 +357,7 @@ void ADungeonGenerateActor::MulticastOnGenerateDungeon_Implementation()
DUNGEON_GENERATOR_LOG(TEXT("MulticastOnGenerateDungeon: %s"), HasAuthority() ? TEXT("Server") : TEXT("Client"));
#endif
PreGenerateImplementation();
+ PostGenerateImplementation();
}
void ADungeonGenerateActor::GenerateDungeonWithParameter(UDungeonGenerateParameter* dungeonGenerateParameter)
diff --git a/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp b/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp
index a0a5493..ec87f5a 100644
--- a/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp
+++ b/Source/DungeonGenerator/Private/DungeonGenerateBase.cpp
@@ -54,6 +54,8 @@ ADungeonGenerateActorは配置可能(Placeable)、ADungeonGeneratedActorは配
#include
#include
+#include "SubActor/DungeonRoomSensorDatabase.h"
+
#if WITH_EDITOR
// UnrealEd
#include
@@ -77,10 +79,21 @@ namespace
const FString LevelsFolderPath = TEXT("/Levels/");
const FString InteriorsFolderPath = TEXT("Interiors");
- bool operator==(const EDungeonRoomItem left, const dungeon::Room::Item right)
+ constexpr bool operator==(const EDungeonRoomItem left, const dungeon::Room::Item right)
{
return static_cast(left) == static_cast(right);
}
+
+ constexpr EDungeonRoomItem Cast(const dungeon::Room::Item item)
+ {
+ return static_cast(item);
+ }
+
+ constexpr EDungeonRoomLocatorParts Cast(const dungeon::Room::Parts parts)
+ {
+ return static_cast(parts);
+ }
+
}
ADungeonGenerateBase::ADungeonGenerateBase(const FObjectInitializer& initializer)
@@ -278,41 +291,45 @@ void ADungeonGenerateBase::DestroySpawnedActors(UWorld* world)
UGameplayStatics::GetAllActorsWithTag(world, GetDungeonGeneratorTag(), actors);
#if WITH_EDITOR
- TArray deleteFolders;
-
- // TagにDungeonGeneratorTagがついているアクターのフォルダを回収
- for (const AActor* actor : actors)
+ // Standaloneモードによる起動ではGEditorやGEngineが無効になる
+ if (IsValid(GEditor))
{
- if (IsValid(actor))
- {
- const FFolder& folder = actor->GetFolder();
-
- if (!folder.IsValid())
- continue;
- if (folder.GetPath() == folder.GetEmptyPath())
- continue;
+ TArray deleteFolders;
- if (const auto* actorFolder = folder.GetActorFolder())
+ // TagにDungeonGeneratorTagがついているアクターのフォルダを回収
+ for (const AActor* actor : actors)
+ {
+ if (IsValid(actor))
{
- if (!actorFolder->IsValid())
+ const FFolder& folder = actor->GetFolder();
+
+ if (!folder.IsValid())
continue;
- }
+ if (folder.GetPath() == folder.GetEmptyPath())
+ continue;
+
+ if (const auto* actorFolder = folder.GetActorFolder())
+ {
+ if (!actorFolder->IsValid())
+ continue;
+ }
- deleteFolders.AddUnique(folder);
+ deleteFolders.AddUnique(folder);
+ }
}
- }
- // パスが長い順に並べ替え
- deleteFolders.Sort([](const FFolder& l, const FFolder& r)
+ // パスが長い順に並べ替え
+ deleteFolders.Sort([](const FFolder& l, const FFolder& r)
+ {
+ return l.GetPath().GetStringLength() > r.GetPath().GetStringLength();
+ }
+ );
+
+ // フォルダを削除
+ for (FFolder& folder : deleteFolders)
{
- return l.GetPath().GetStringLength() > r.GetPath().GetStringLength();
+ FActorFolders::Get().DeleteFolder(*world, folder);
}
- );
-
- // フォルダを削除
- for (FFolder& folder : deleteFolders)
- {
- FActorFolders::Get().DeleteFolder(*world, folder);
}
#endif
@@ -1297,18 +1314,35 @@ void ADungeonGenerateBase::CreateImplement_PrepareSpawnRoomSensor(RoomAndRoomSen
// RoomSensorActorを生成
mGenerator->ForEach([this, &roomSensorCache](const std::shared_ptr& room)
{
- ADungeonRoomSensorBase* roomSensorActor = SpawnRoomSensorActorDeferred(
- mParameter->GetRoomSensorClass(),
- room->GetIdentifier(),
- room->GetCenter() * mParameter->GetGridSize().To3D() + GetActorLocation(),
- room->GetExtent() * mParameter->GetGridSize().To3D(),
- static_cast(room->GetParts()),
- static_cast(room->GetItem()),
- room->GetBranchId(),
- room->GetDepthFromStart(),
- mGenerator->GetDeepestDepthFromStart()
- );
- roomSensorCache[room.get()] = roomSensorActor;
+ auto* roomSensorClass = mParameter->GetRoomSensorClass();
+ if (const auto* roomSensorDatabase = mParameter->GetRoomSensorDatabase())
+ {
+ // TODO: ダンジョンの深さを0~255に正規化する関数を検討してください
+ auto depthFromStart = static_cast(room->GetDepthFromStart());
+ depthFromStart /= static_cast(mGenerator->GetDeepestDepthFromStart());
+ const auto depthRatioFromStart = static_cast(depthFromStart * 255.f);
+
+ roomSensorClass = roomSensorDatabase->Select(
+ room->GetIdentifier(),
+ depthRatioFromStart,
+ GetSynchronizedRandom()
+ );
+ }
+ if (roomSensorClass)
+ {
+ auto* roomSensorActor = SpawnRoomSensorActorDeferred(
+ roomSensorClass,
+ room->GetIdentifier(),
+ room->GetCenter() * mParameter->GetGridSize().To3D() + GetActorLocation(),
+ room->GetExtent() * mParameter->GetGridSize().To3D(),
+ static_cast(room->GetParts()),
+ static_cast(room->GetItem()),
+ room->GetBranchId(),
+ room->GetDepthFromStart(),
+ mGenerator->GetDeepestDepthFromStart()
+ );
+ roomSensorCache[room.get()] = roomSensorActor;
+ }
}
);
diff --git a/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp b/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp
index f06e6f3..e3b319b 100644
--- a/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp
+++ b/Source/DungeonGenerator/Private/Parameter/DungeonGenerateParameter.cpp
@@ -45,6 +45,7 @@ UDungeonGenerateParameter* UDungeonGenerateParameter::GenerateRandomParameter(co
parameter->DoorPartsSelectionMethod = sourceParameter->DoorPartsSelectionMethod;
parameter->DoorParts = sourceParameter->DoorParts;
parameter->DungeonRoomSensorClass = sourceParameter->DungeonRoomSensorClass;
+ parameter->DungeonRoomSensorDatabase = sourceParameter->DungeonRoomSensorDatabase;
}
return parameter;
diff --git a/Source/DungeonGenerator/Private/SubActor/DungeonRoomSensorDatabase.cpp b/Source/DungeonGenerator/Private/SubActor/DungeonRoomSensorDatabase.cpp
new file mode 100644
index 0000000..f792b62
--- /dev/null
+++ b/Source/DungeonGenerator/Private/SubActor/DungeonRoomSensorDatabase.cpp
@@ -0,0 +1,53 @@
+/**
+@author Shun Moriya
+@copyright 2023- Shun Moriya
+All Rights Reserved.
+*/
+
+#include "SubActor/DungeonRoomSensorDatabase.h"
+#include "Core/Math/Random.h"
+#include "Core/Debug/Debug.h"
+#include "Parameter/DungeonMeshSetDatabase.h"
+#include
+
+UDungeonRoomSensorDatabase::UDungeonRoomSensorDatabase(const FObjectInitializer& ObjectInitializer)
+ : Super(ObjectInitializer)
+{
+}
+
+UClass* UDungeonRoomSensorDatabase::Select(const uint16_t identifier, const uint8_t depthRatioFromStart, const std::shared_ptr& random) const
+{
+ TArray roomSensors;
+ roomSensors.Reserve(DungeonRoomSensorClass.Num());
+ for (const auto& dungeonRoomSensorClass : DungeonRoomSensorClass)
+ {
+ if (IsValid(dungeonRoomSensorClass))
+ roomSensors.Add(dungeonRoomSensorClass);
+ }
+ if (roomSensors.Num() <= 0)
+ return nullptr;
+
+ // 抽選
+ switch (SelectionMethod)
+ {
+ case EDungeonMeshSetSelectionMethod::Random:
+ {
+ const auto index = random->Get(roomSensors.Num());
+ return roomSensors[index];
+ }
+ case EDungeonMeshSetSelectionMethod::Identifier:
+ {
+ const auto index = identifier % roomSensors.Num();
+ return roomSensors[index];
+ }
+ case EDungeonMeshSetSelectionMethod::DepthFromStart:
+ {
+ const float ratio = static_cast(depthRatioFromStart) / 255.f;
+ const float index = static_cast(roomSensors.Num() - 1) * ratio;
+ return roomSensors[static_cast(std::round(index))];
+ }
+ default:
+ DUNGEON_GENERATOR_ERROR(TEXT("Set the correct SelectionMethod"));
+ return nullptr;
+ }
+}
diff --git a/Source/DungeonGenerator/Public/DungeonGenerateActor.h b/Source/DungeonGenerator/Public/DungeonGenerateActor.h
index 0be10d5..d23c78f 100644
--- a/Source/DungeonGenerator/Public/DungeonGenerateActor.h
+++ b/Source/DungeonGenerator/Public/DungeonGenerateActor.h
@@ -153,6 +153,7 @@ class DUNGEONGENERATOR_API ADungeonGenerateActor : public ADungeonGenerateBase
void ApplyInstancedMeshCullDistance();
void PreGenerateImplementation();
+ void PostGenerateImplementation() const;
#if WITH_EDITOR
void DrawDebugInformation() const;
diff --git a/Source/DungeonGenerator/Public/Mission/DungeonRoomParts.h b/Source/DungeonGenerator/Public/Mission/DungeonRoomParts.h
index 53dbf7d..c1f6703 100644
--- a/Source/DungeonGenerator/Public/Mission/DungeonRoomParts.h
+++ b/Source/DungeonGenerator/Public/Mission/DungeonRoomParts.h
@@ -68,3 +68,23 @@ inline constexpr bool Equal(const EDungeonRoomLocatorParts locatorParts, const E
{
return Equal(parts, locatorParts);
}
+
+/**
+ * Cast from EDungeonRoomLocatorParts to EDungeonRoomParts
+ *
+ * EDungeonRoomLocatorPartsからEDungeonRoomPartsへのキャスト
+ */
+inline constexpr EDungeonRoomParts Cast(const EDungeonRoomLocatorParts parts)
+{
+ return static_cast(parts);
+}
+
+/**
+ * Cast from EDungeonRoomParts to EDungeonRoomLocatorParts
+ *
+ * EDungeonRoomPartsからEDungeonRoomLocatorPartsへのキャスト
+ */
+inline constexpr EDungeonRoomLocatorParts Cast(const EDungeonRoomParts parts)
+{
+ return static_cast(parts);
+}
diff --git a/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h b/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h
index 458ef1b..a7a2965 100644
--- a/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h
+++ b/Source/DungeonGenerator/Public/Parameter/DungeonGenerateParameter.h
@@ -14,6 +14,7 @@ All Rights Reserved.
#include "DungeonGenerateParameter.generated.h"
// forward declaration
+class UDungeonRoomSensorDatabase;
/**
Frequency of generation
@@ -68,6 +69,7 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject
UClass* GetRoomSensorClass() const;
+ UDungeonRoomSensorDatabase* GetRoomSensorDatabase() const;
// Converts from a grid coordinate system to a world coordinate system
FVector ToWorld(const FIntVector& location) const;
@@ -399,20 +401,32 @@ void EachPillarParts(const std::function& functi
/**
- Specify the DungeonRoomSensorBase class,
- which is a box sensor that covers the room and controls doors and enemy spawn.
-
- DungeonRoomSensorBaseクラスを指定して下さい。
- DungeonRoomSensorBaseは部屋を覆う箱センサーで、ドアや敵のスポーンを制御します。
- */
- UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor", BlueprintReadWrite, meta = (AllowedClasses = "DungeonRoomSensorBase"))
+ * Specify the DungeonRoomSensorBase class,
+ * which is a box sensor that covers the room and controls doors and enemy spawn.
+ * DungeonRoomSensorDatabase takes precedence
+ *
+ * DungeonRoomSensorBaseクラスを指定して下さい。
+ * DungeonRoomSensorBaseは部屋を覆う箱センサーで、ドアや敵のスポーンを制御します。
+ * DungeonRoomSensorDatabaseが優先されます
+ */
+ UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor", BlueprintReadWrite, meta = (AllowedClasses = "DungeonRoomSensorBase", DeprecatedProperty, ToolTip = "This variable is deprecated. Please use DungeonRoomSensorDatabase instead."))
TObjectPtr DungeonRoomSensorClass;
/**
- PluginVersion
+ * Specify the room sensor database
+ * The room sensor database specifies the arrangement and direction in the room
+ *
+ * ルームセンサーのデータベースを指定して下さい
+ * ルームセンサーのデータベースは部屋の中の配置や演出を指定します
+ */
+ UPROPERTY(EditAnywhere, Category = "DungeonGenerator|RoomSensor", BlueprintReadWrite)
+ TObjectPtr DungeonRoomSensorDatabase;
- プラグインバージョン
- */
+ /**
+ * PluginVersion
+ *
+ * プラグインバージョン
+ */
UPROPERTY(BlueprintReadOnly, Category = "DungeonGenerator")
uint8 PluginVersion;
@@ -510,6 +524,11 @@ inline UClass* UDungeonGenerateParameter::GetRoomSensorClass() const
return DungeonRoomSensorClass;
}
+inline UDungeonRoomSensorDatabase* UDungeonGenerateParameter::GetRoomSensorDatabase() const
+{
+ return DungeonRoomSensorDatabase;
+}
+
inline void UDungeonGenerateParameter::EachFloorParts(const std::function& function) const
{
EachRoomFloorParts(function);
diff --git a/Source/DungeonGenerator/Public/Parameter/DungeonMeshSetDatabase.h b/Source/DungeonGenerator/Public/Parameter/DungeonMeshSetDatabase.h
index 9a70d90..d62b1e8 100644
--- a/Source/DungeonGenerator/Public/Parameter/DungeonMeshSetDatabase.h
+++ b/Source/DungeonGenerator/Public/Parameter/DungeonMeshSetDatabase.h
@@ -5,8 +5,8 @@ All Rights Reserved.
*/
#pragma once
+#include "DungeonMeshSetSelectionMethod.h"
#include "Parameter/DungeonMeshSet.h"
-#include
#include
#include "DungeonMeshSetDatabase.generated.h"
@@ -16,18 +16,6 @@ namespace dungeon
class Random;
}
-/**
-Part Selection Method
-パーツを選択する方法
-*/
-UENUM(BlueprintType)
-enum class EDungeonMeshSetSelectionMethod : uint8
-{
- Identifier,
- DepthFromStart,
- Random,
-};
-
/**
Database of dungeon mesh sets
ダンジョンのメッシュセットのデータベース
@@ -73,7 +61,7 @@ class DUNGEONGENERATOR_API UDungeonMeshSetDatabase : public UObject
パーツを選択する方法
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DungeonGenerator")
- EDungeonMeshSetSelectionMethod SelectionMethod = EDungeonMeshSetSelectionMethod::Identifier;
+ EDungeonMeshSetSelectionMethod SelectionMethod = EDungeonMeshSetSelectionMethod::DepthFromStart;
/**
Set the DungeonRoomMeshSet; multiple DungeonRoomMeshSets can be set.
diff --git a/Source/DungeonGenerator/Public/Parameter/DungeonMeshSetSelectionMethod.h b/Source/DungeonGenerator/Public/Parameter/DungeonMeshSetSelectionMethod.h
new file mode 100644
index 0000000..3a8d147
--- /dev/null
+++ b/Source/DungeonGenerator/Public/Parameter/DungeonMeshSetSelectionMethod.h
@@ -0,0 +1,21 @@
+/**
+@author Shun Moriya
+@copyright 2025- Shun Moriya
+All Rights Reserved.
+*/
+
+#pragma once
+#include
+#include "DungeonMeshSetSelectionMethod.generated.h"
+
+/**
+Part Selection Method
+パーツを選択する方法
+*/
+UENUM(BlueprintType)
+enum class EDungeonMeshSetSelectionMethod : uint8
+{
+ Identifier,
+ DepthFromStart,
+ Random,
+};
diff --git a/Source/DungeonGenerator/Public/SubActor/DungeonRoomSensorDatabase.h b/Source/DungeonGenerator/Public/SubActor/DungeonRoomSensorDatabase.h
new file mode 100644
index 0000000..f33e07a
--- /dev/null
+++ b/Source/DungeonGenerator/Public/SubActor/DungeonRoomSensorDatabase.h
@@ -0,0 +1,68 @@
+/**
+@author Shun Moriya
+@copyright 2023- Shun Moriya
+All Rights Reserved.
+*/
+
+#pragma once
+#include "Parameter/DungeonMeshSetSelectionMethod.h"
+#include
+#include "DungeonRoomSensorDatabase.generated.h"
+
+namespace dungeon
+{
+ class Random;
+}
+
+/**
+ * Database class that manages dungeon room intrusion detection sensors
+ *
+ * UDungeonRoomSensorDatabase is a database class that holds and manages multiple UDungeonRoomSensor
+ * Database class that holds and manages multiple UDungeonRoomSensors.
+ * draws lots and selects available sensors based on set conditions.
+ *
+ * ダンジョンの部屋侵入検知センサーを管理するデータベースクラス
+ *
+ * UDungeonRoomSensorDatabase は、複数の UDungeonRoomSensor を保持・管理する
+ * データベースクラスです。
+ * 設定された条件を元に、利用可能なセンサーを抽選し選択します。
+*/
+UCLASS(ClassGroup = "DungeonGenerator")
+class DUNGEONGENERATOR_API UDungeonRoomSensorDatabase : public UObject
+{
+ GENERATED_BODY()
+
+public:
+ /**
+ * constructor
+ */
+ explicit UDungeonRoomSensorDatabase(const FObjectInitializer& ObjectInitializer);
+
+ /**
+ * destructor
+ */
+ virtual ~UDungeonRoomSensorDatabase() override = default;
+
+ /**
+ * Select the DungeonRoomSensor class that matches the condition of the argument
+ *
+ * 引数の条件にあったDungeonRoomSensorのクラスを選択します
+ */
+ UClass* Select(const uint16_t identifier, const uint8_t depthRatioFromStart, const std::shared_ptr& random) const;
+
+protected:
+ /**
+ * Room Sensor Generation Rules
+ * ルームセンサーの生成ルール
+ */
+ UPROPERTY(EditAnywhere, Category = "DungeonGenerator")
+ EDungeonMeshSetSelectionMethod SelectionMethod = EDungeonMeshSetSelectionMethod::Identifier;
+
+ /**
+ * Register the RoomSensor to be placed.
+ *
+ * 配置するRoomSensorを登録して下さい。
+ */
+ UPROPERTY(EditAnywhere, Category = "DungeonGenerator", meta = (AllowedClasses = "DungeonRoomSensorBase"))
+ TArray> DungeonRoomSensorClass;
+};
diff --git a/Source/DungeonGeneratorEditor/Private/DungeonGeneratorEditorModule.cpp b/Source/DungeonGeneratorEditor/Private/DungeonGeneratorEditorModule.cpp
index 42632c4..fa465b1 100644
--- a/Source/DungeonGeneratorEditor/Private/DungeonGeneratorEditorModule.cpp
+++ b/Source/DungeonGeneratorEditor/Private/DungeonGeneratorEditorModule.cpp
@@ -7,6 +7,7 @@ All Rights Reserved.
#include "DungeonGeneratorEditorModule.h"
#include "DungeonGeneratorStyle.h"
#include "DungeonGeneratorCommands.h"
+#include "SubActor/DungeonRoomSensorDatabaseTypeActions.h"
#include "Parameter/DungeonMeshSetDatabaseTypeActions.h"
#include "Parameter/DungeonGenerateParameterTypeActions.h"
#include "BuildInfomation.h"
@@ -80,6 +81,12 @@ void FDungeonGenerateEditorModule::StartupModule()
AssetTools.RegisterAssetTypeActions(actionType.ToSharedRef());
}
+
+ // Register FDungeonRoomSensorDatabaseTypeActions
+ {
+ TSharedPtr actionType = MakeShareable(new FDungeonRoomSensorDatabaseTypeActions(gameAssetCategory));
+ AssetTools.RegisterAssetTypeActions(actionType.ToSharedRef());
+ }
}
void FDungeonGenerateEditorModule::ShutdownModule()
@@ -324,9 +331,11 @@ void FDungeonGenerateEditorModule::DisposeDungeon(UWorld* world, const bool flus
UWorld* FDungeonGenerateEditorModule::GetWorldFromGameViewport()
{
- if (const FWorldContext* worldContext = GEngine->GetWorldContextFromGameViewport(GEngine->GameViewport))
- return worldContext->World();
-
+ if (IsValid(GEngine))
+ {
+ if (const auto* worldContext = GEngine->GetWorldContextFromGameViewport(GEngine->GameViewport))
+ return worldContext->World();
+ }
return nullptr;
}
diff --git a/Source/DungeonGeneratorEditor/Private/SubActor/DungeonRoomSensorDatabaseFactory.cpp b/Source/DungeonGeneratorEditor/Private/SubActor/DungeonRoomSensorDatabaseFactory.cpp
new file mode 100644
index 0000000..cc17953
--- /dev/null
+++ b/Source/DungeonGeneratorEditor/Private/SubActor/DungeonRoomSensorDatabaseFactory.cpp
@@ -0,0 +1,20 @@
+/**
+@author Shun Moriya
+@copyright 2025- Shun Moriya
+All Rights Reserved.
+*/
+
+#include "SubActor/DungeonRoomSensorDatabaseFactory.h"
+#include "SubActor/DungeonRoomSensorDatabase.h"
+
+UDungeonRoomSensorDatabaseFactory::UDungeonRoomSensorDatabaseFactory()
+{
+ SupportedClass = UDungeonRoomSensorDatabase::StaticClass();
+ bCreateNew = true;
+ bEditAfterNew = true;
+}
+
+UObject* UDungeonRoomSensorDatabaseFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
+{
+ return NewObject(InParent, InClass, InName, Flags);
+}
diff --git a/Source/DungeonGeneratorEditor/Private/SubActor/DungeonRoomSensorDatabaseTypeActions.cpp b/Source/DungeonGeneratorEditor/Private/SubActor/DungeonRoomSensorDatabaseTypeActions.cpp
new file mode 100644
index 0000000..1973967
--- /dev/null
+++ b/Source/DungeonGeneratorEditor/Private/SubActor/DungeonRoomSensorDatabaseTypeActions.cpp
@@ -0,0 +1,34 @@
+/**
+@author Shun Moriya
+@copyright 2025- Shun Moriya
+All Rights Reserved.
+*/
+
+#include "SubActor/DungeonRoomSensorDatabaseTypeActions.h"
+#include "SubActor/DungeonRoomSensorDatabase.h"
+
+FDungeonRoomSensorDatabaseTypeActions::FDungeonRoomSensorDatabaseTypeActions(EAssetTypeCategories::Type InAssetCategory)
+ : mAssetCategory(InAssetCategory)
+{
+}
+
+FText FDungeonRoomSensorDatabaseTypeActions::GetName() const
+{
+ return FText::FromName(TEXT("Room sensor database"));
+}
+
+UClass* FDungeonRoomSensorDatabaseTypeActions::GetSupportedClass() const
+{
+ return UDungeonRoomSensorDatabase::StaticClass();
+}
+
+uint32 FDungeonRoomSensorDatabaseTypeActions::GetCategories()
+{
+ return mAssetCategory;
+}
+
+FColor FDungeonRoomSensorDatabaseTypeActions::GetTypeColor() const
+{
+ static constexpr FColor Color(56, 156, 156);
+ return Color;
+}
diff --git a/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseFactory.h b/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseFactory.h
new file mode 100644
index 0000000..a13d873
--- /dev/null
+++ b/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseFactory.h
@@ -0,0 +1,23 @@
+/**
+@author Shun Moriya
+@copyright 2025- Shun Moriya
+All Rights Reserved.
+*/
+
+#pragma once
+#include
+#include
+#include "DungeonRoomSensorDatabaseFactory.generated.h"
+
+UCLASS()
+class DUNGEONGENERATOREDITOR_API UDungeonRoomSensorDatabaseFactory : public UFactory
+{
+ GENERATED_BODY()
+
+public:
+ UDungeonRoomSensorDatabaseFactory();
+ virtual ~UDungeonRoomSensorDatabaseFactory() override = default;
+
+ // UFactory overrides
+ virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
+};
diff --git a/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseTypeActions.h b/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseTypeActions.h
new file mode 100644
index 0000000..a89e1b8
--- /dev/null
+++ b/Source/DungeonGeneratorEditor/Public/SubActor/DungeonRoomSensorDatabaseTypeActions.h
@@ -0,0 +1,24 @@
+/**
+@author Shun Moriya
+@copyright 2025- Shun Moriya
+All Rights Reserved.
+*/
+
+#pragma once
+#include "DungeonAssetTypeActionsBase.h"
+
+class FDungeonRoomSensorDatabaseTypeActions : public FDungeonAssetTypeActionsBase
+{
+public:
+ explicit FDungeonRoomSensorDatabaseTypeActions(EAssetTypeCategories::Type InAssetCategory);
+ virtual ~FDungeonRoomSensorDatabaseTypeActions() override = default;
+
+ // IAssetTypeActions Implementation
+ virtual FText GetName() const override;
+ virtual UClass* GetSupportedClass() const override;
+ virtual uint32 GetCategories() override;
+ virtual FColor GetTypeColor() const override;
+
+private:
+ EAssetTypeCategories::Type mAssetCategory;
+};