diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini
index 794b800146bf05e8501dd4c8f52c9d3c07f1ec58..2f6535e121da317be69d3b9a510a5fea739b0de9 100644
--- a/Config/DefaultEngine.ini
+++ b/Config/DefaultEngine.ini
@@ -152,6 +152,7 @@ GameDefaultMap = /Game/VRTemplate/Maps/VRTemplateMap.VRTemplateMap
 ServerDefaultMap = /Engine/Maps/Entry.Entry
 GlobalDefaultGameMode = /Game/VRTemplate/Blueprints/VRGameMode.VRGameMode_C
 GlobalDefaultServerGameMode = None
+GameInstanceClass=/Script/MetaCastBachelor.StudyManager
 
 [/Script/Slate.SlateSettings]
 bExplicitCanvasChildZOrder = True
diff --git a/Content/BP/BP_PointCloud.uasset b/Content/BP/BP_PointCloud.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..389b994af26df9155700d1c43c65ac11d26ea93e
Binary files /dev/null and b/Content/BP/BP_PointCloud.uasset differ
diff --git a/Content/BP/BaselinePawn.uasset b/Content/BP/BaselinePawn.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..e20d50d04d7a33265dd67dd8abd7d26399308ed5
Binary files /dev/null and b/Content/BP/BaselinePawn.uasset differ
diff --git a/Content/BP/MagicWandPawn.uasset b/Content/BP/MagicWandPawn.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..4dc9451d67cd3053d60fc8aa38349cffc33a9853
Binary files /dev/null and b/Content/BP/MagicWandPawn.uasset differ
diff --git a/Content/BP/MetaCastPawn.uasset b/Content/BP/MetaCastPawn.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..579d6539b7bbe28470f4fd3d933d98e324cec825
Binary files /dev/null and b/Content/BP/MetaCastPawn.uasset differ
diff --git a/Content/BP/MetaCastStudyPawn.uasset b/Content/BP/MetaCastStudyPawn.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..d911325018882954ace99dc61d9a932e7e2c2fd6
Binary files /dev/null and b/Content/BP/MetaCastStudyPawn.uasset differ
diff --git a/Content/BP_PointCloud.uasset b/Content/BP_PointCloud.uasset
index 630f4bc467f5517f4b0d0712ef2c32feeb0479c6..35b8933082c395675797400f21d1c59cb0a3215a 100644
Binary files a/Content/BP_PointCloud.uasset and b/Content/BP_PointCloud.uasset differ
diff --git a/Content/BaselineMap.umap b/Content/BaselineMap.umap
index 790123205ae6a3dd19e1f1ae1031234fc2eb1e24..02ffe12a6cd42b693e15b32ba9eeabae6a553e9b 100644
Binary files a/Content/BaselineMap.umap and b/Content/BaselineMap.umap differ
diff --git a/Content/BaselinePawn.uasset b/Content/BaselinePawn.uasset
index 91601efa69de6e1b1668a248c5d34e4ab21ad9e6..df1dc062900e001e1b966fa2a06a32be4bd0829a 100644
Binary files a/Content/BaselinePawn.uasset and b/Content/BaselinePawn.uasset differ
diff --git a/Content/Erase.uasset b/Content/Erase.uasset
index fc7778b74d7444b17945e38b7b2a7d2291fd24f6..5d7516deb4ba267510f2a0de614bd0d254721000 100644
Binary files a/Content/Erase.uasset and b/Content/Erase.uasset differ
diff --git a/Content/Input/MetaCast_Config.uasset b/Content/Input/MetaCast_Config.uasset
index fd2a0349fe298b04f51242b2bab1313da3b1f56e..c7c5d74a6bbf84c316c0ec6412c7bae48519142d 100644
Binary files a/Content/Input/MetaCast_Config.uasset and b/Content/Input/MetaCast_Config.uasset differ
diff --git a/Content/Input/NextPointCloud.uasset b/Content/Input/NextPointCloud.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..341f8079775b7d55ec1e97fde31fa19307e131db
Binary files /dev/null and b/Content/Input/NextPointCloud.uasset differ
diff --git a/Content/Input/PreviousPointCloud.uasset b/Content/Input/PreviousPointCloud.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..a8c5e3329e790f7a0ea7ae2e0e8792bf9aa95655
Binary files /dev/null and b/Content/Input/PreviousPointCloud.uasset differ
diff --git a/Content/LineMaterialOnTop.uasset b/Content/LineMaterialOnTop.uasset
index dc22cab6810dd4bb4d641ea9a133b9f921fb125f..f708f0611097c173411ee5952e9e312655bb1399 100644
Binary files a/Content/LineMaterialOnTop.uasset and b/Content/LineMaterialOnTop.uasset differ
diff --git a/Content/MagicWandMap.umap b/Content/MagicWandMap.umap
index 539b1a7ba764672b385820a2c7921335dd1e2d81..438e212814f1a9894b3aca21f2bad4671f10d0ae 100644
Binary files a/Content/MagicWandMap.umap and b/Content/MagicWandMap.umap differ
diff --git a/Content/MagicWandPawn.uasset b/Content/MagicWandPawn.uasset
index de43aeb2f5e2148db4609a84bffcf1dd9b746344..378c05d826401e7c832a895b0c7b203f6ba09030 100644
Binary files a/Content/MagicWandPawn.uasset and b/Content/MagicWandPawn.uasset differ
diff --git a/Content/Main_base.umap b/Content/Main_base.umap
index 1834af11c9ac99a1e9dc9a91bddb5b20c613e752..77fc8d18ace6c84129da21fbbcc66ec626e00ff6 100644
Binary files a/Content/Main_base.umap and b/Content/Main_base.umap differ
diff --git a/Content/Maps/BaselineMap.umap b/Content/Maps/BaselineMap.umap
new file mode 100644
index 0000000000000000000000000000000000000000..9de67b74856c69c35a97b1dababa26e52d0aa983
Binary files /dev/null and b/Content/Maps/BaselineMap.umap differ
diff --git a/Content/BaselineMap_BuiltData.uasset b/Content/Maps/BaselineMap_BuiltData.uasset
similarity index 97%
rename from Content/BaselineMap_BuiltData.uasset
rename to Content/Maps/BaselineMap_BuiltData.uasset
index fe57b807e31e2a94825eea43e5d15f1358ba520a..64cc15f67ddb7a0b7ef29870054aa47a857dfd66 100644
Binary files a/Content/BaselineMap_BuiltData.uasset and b/Content/Maps/BaselineMap_BuiltData.uasset differ
diff --git a/Content/Maps/Login.umap b/Content/Maps/Login.umap
new file mode 100644
index 0000000000000000000000000000000000000000..4b1097f1320275d14975cc9b8dd7ff18a59ebc21
Binary files /dev/null and b/Content/Maps/Login.umap differ
diff --git a/Content/Maps/Login_BuiltData.uasset b/Content/Maps/Login_BuiltData.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..679d66d60cb944f7ef57de2a283580c4dfbebabd
Binary files /dev/null and b/Content/Maps/Login_BuiltData.uasset differ
diff --git a/Content/Maps/MagicWandMap.umap b/Content/Maps/MagicWandMap.umap
new file mode 100644
index 0000000000000000000000000000000000000000..c2c339c8e58021b6b782d5be6845ba6079ab1276
Binary files /dev/null and b/Content/Maps/MagicWandMap.umap differ
diff --git a/Content/Maps/Main_base.umap b/Content/Maps/Main_base.umap
new file mode 100644
index 0000000000000000000000000000000000000000..56b4ae9ddd07c0ff333f5a5100fd4322d66833d3
Binary files /dev/null and b/Content/Maps/Main_base.umap differ
diff --git a/Content/Maps/MetaPointMap.umap b/Content/Maps/MetaPointMap.umap
new file mode 100644
index 0000000000000000000000000000000000000000..a90854d788da949d4f535913152805a0d41f8462
Binary files /dev/null and b/Content/Maps/MetaPointMap.umap differ
diff --git a/Content/MetaPointMap_BuiltData.uasset b/Content/Maps/MetaPointMap_BuiltData.uasset
similarity index 89%
rename from Content/MetaPointMap_BuiltData.uasset
rename to Content/Maps/MetaPointMap_BuiltData.uasset
index 24285dcf828b76f9af8653034e84014cb1f8e362..f24ba9f95bd0eccdf027fb7ee478a2afed9ad471 100644
Binary files a/Content/MetaPointMap_BuiltData.uasset and b/Content/Maps/MetaPointMap_BuiltData.uasset differ
diff --git a/Content/Materials/LineMaterialOnTop.uasset b/Content/Materials/LineMaterialOnTop.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..61ff20116a24839677cceb269187058f9d1bab30
Binary files /dev/null and b/Content/Materials/LineMaterialOnTop.uasset differ
diff --git a/Content/SelectionSphere.uasset b/Content/Materials/SelectionSphere.uasset
similarity index 67%
rename from Content/SelectionSphere.uasset
rename to Content/Materials/SelectionSphere.uasset
index 3658db0d60cf2297b8397d7d760059f280068404..19af8b53e240526a6152d0dd26a7f1bf326ff2c4 100644
Binary files a/Content/SelectionSphere.uasset and b/Content/Materials/SelectionSphere.uasset differ
diff --git a/Content/Materials/SelectionVolume.uasset b/Content/Materials/SelectionVolume.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..4d6547f1ed84bf9bc45405bf0fa90e943823b449
Binary files /dev/null and b/Content/Materials/SelectionVolume.uasset differ
diff --git a/Content/MetaPointMap.umap b/Content/MetaPointMap.umap
index a72bbe726246e20a572a9592fe5f670744ae9b98..9fe0e6c60769ed5a361584ec348470b8d4449401 100644
Binary files a/Content/MetaPointMap.umap and b/Content/MetaPointMap.umap differ
diff --git a/Content/Redo.uasset b/Content/Redo.uasset
index 08b3ee74087a8e32a8a405f3a2af265230ed4ede..f28d7fea0c23df8e4fc89708d5044ff56d0c7a96 100644
Binary files a/Content/Redo.uasset and b/Content/Redo.uasset differ
diff --git a/Content/SelectionEndSound.uasset b/Content/SelectionEndSound.uasset
index f1d9214254da15bc2a58ec928f77ddd4b3a28a4c..abbcd8798f55ff5e5500c3d70285715f0bac5b31 100644
Binary files a/Content/SelectionEndSound.uasset and b/Content/SelectionEndSound.uasset differ
diff --git a/Content/SelectionStartSound.uasset b/Content/SelectionStartSound.uasset
index d75674c56db89afff2b1889918a640201d84c70c..08e5d9dbc25ed28280fd8eb1361331654684f45d 100644
Binary files a/Content/SelectionStartSound.uasset and b/Content/SelectionStartSound.uasset differ
diff --git a/Content/SelectionVolume.uasset b/Content/SelectionVolume.uasset
index ee9355b4be96b567ea71a244e4fd54a1255459b8..5d50ad11410ec2c1afc63b788adc1fcf5492f200 100644
Binary files a/Content/SelectionVolume.uasset and b/Content/SelectionVolume.uasset differ
diff --git a/Content/Sounds/Erase.uasset b/Content/Sounds/Erase.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..95d7ee0ad7b2dcf0414898942eb64361c582d38e
Binary files /dev/null and b/Content/Sounds/Erase.uasset differ
diff --git a/Content/Sounds/Redo.uasset b/Content/Sounds/Redo.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..f29798ccaad37a5c6073641c356a98bab7a0ecf0
Binary files /dev/null and b/Content/Sounds/Redo.uasset differ
diff --git a/Content/Sounds/SelectionEndSound.uasset b/Content/Sounds/SelectionEndSound.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..c09698543e16011eef1191b01230f5e12a7262ac
Binary files /dev/null and b/Content/Sounds/SelectionEndSound.uasset differ
diff --git a/Content/Sounds/SelectionStartSound.uasset b/Content/Sounds/SelectionStartSound.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..c2160e68ef00e7dd144173d408edfd498b9a3f3f
Binary files /dev/null and b/Content/Sounds/SelectionStartSound.uasset differ
diff --git a/Content/Sounds/Undo.uasset b/Content/Sounds/Undo.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..0841a5804b600ebf7ea13c0a26b5d2fe24ff5a49
Binary files /dev/null and b/Content/Sounds/Undo.uasset differ
diff --git a/Content/UI/LoginManager.uasset b/Content/UI/LoginManager.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..3b8d5e42b82a1bbeaaa1f1bf8074e2da9f77a458
Binary files /dev/null and b/Content/UI/LoginManager.uasset differ
diff --git a/Content/UI/StudyLogin.uasset b/Content/UI/StudyLogin.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..352dcfe5583b5870307ec88fa185f6e53e564c82
Binary files /dev/null and b/Content/UI/StudyLogin.uasset differ
diff --git a/Content/Undo.uasset b/Content/Undo.uasset
index 7ad45bdaa35db1108919281246596e81b584fc9b..3db51204d0f8180bf0a4990e721824eed956ce19 100644
Binary files a/Content/Undo.uasset and b/Content/Undo.uasset differ
diff --git a/Data/data/snap_C02_200_127_animation b/Data/data/snap_animation
similarity index 100%
rename from Data/data/snap_C02_200_127_animation
rename to Data/data/snap_animation
diff --git "a/Data/data/training_cylinder - \345\211\257\346\234\254" b/Data/data/training_cylinder_2
similarity index 100%
rename from "Data/data/training_cylinder - \345\211\257\346\234\254"
rename to Data/data/training_cylinder_2
diff --git "a/Data/data/training_pyramid - \345\211\257\346\234\254" b/Data/data/training_pyramid_2
similarity index 100%
rename from "Data/data/training_pyramid - \345\211\257\346\234\254"
rename to Data/data/training_pyramid_2
diff --git "a/Data/data/training_sphere - \345\211\257\346\234\254" b/Data/data/training_sphere_2
similarity index 100%
rename from "Data/data/training_sphere - \345\211\257\346\234\254"
rename to Data/data/training_sphere_2
diff --git a/Data/flags/Flocculentcube1_0 b/Data/flags/Flocculentcube1_flags_1
similarity index 100%
rename from Data/flags/Flocculentcube1_0
rename to Data/flags/Flocculentcube1_flags_1
diff --git a/Data/flags/Flocculentcube1_1 b/Data/flags/Flocculentcube1_flags_2
similarity index 100%
rename from Data/flags/Flocculentcube1_1
rename to Data/flags/Flocculentcube1_flags_2
diff --git a/Data/flags/Flocculentcube1_2 b/Data/flags/Flocculentcube1_flags_3
similarity index 100%
rename from Data/flags/Flocculentcube1_2
rename to Data/flags/Flocculentcube1_flags_3
diff --git a/Data/flags/Flocculentcube1_prestudy_flag b/Data/flags/Flocculentcube1_prestudy_flags
similarity index 100%
rename from Data/flags/Flocculentcube1_prestudy_flag
rename to Data/flags/Flocculentcube1_prestudy_flags
diff --git a/Data/flags/Flocculentcube2_1 b/Data/flags/Flocculentcube2_flags
similarity index 100%
rename from Data/flags/Flocculentcube2_1
rename to Data/flags/Flocculentcube2_flags
diff --git a/Data/flags/Flocculentcube3_flag b/Data/flags/Flocculentcube3_flags
similarity index 100%
rename from Data/flags/Flocculentcube3_flag
rename to Data/flags/Flocculentcube3_flags
diff --git a/Data/flags/ball_hemisphere_1 b/Data/flags/ball_hemisphere_flags
similarity index 100%
rename from Data/flags/ball_hemisphere_1
rename to Data/flags/ball_hemisphere_flags
diff --git a/Data/flags/disk_1 b/Data/flags/disk_flags
similarity index 100%
rename from Data/flags/disk_1
rename to Data/flags/disk_flags
diff --git a/Data/flags/fivecluster_prestudy_flag1 b/Data/flags/fivecluster_prestudy_flags
similarity index 100%
rename from Data/flags/fivecluster_prestudy_flag1
rename to Data/flags/fivecluster_prestudy_flags
diff --git a/Data/flags/fiveellipsolds_1 b/Data/flags/fiveellipsolds_flags_1
similarity index 100%
rename from Data/flags/fiveellipsolds_1
rename to Data/flags/fiveellipsolds_flags_1
diff --git a/Data/flags/fiveellipsolds_flag b/Data/flags/fiveellipsolds_flags_2
similarity index 100%
rename from Data/flags/fiveellipsolds_flag
rename to Data/flags/fiveellipsolds_flags_2
diff --git a/Data/flags/halfrings_1 b/Data/flags/halfrings_flags
similarity index 100%
rename from Data/flags/halfrings_1
rename to Data/flags/halfrings_flags
diff --git a/Data/flags/nbody1_1 b/Data/flags/nbody1_flags
similarity index 100%
rename from Data/flags/nbody1_1
rename to Data/flags/nbody1_flags
diff --git a/Data/flags/nbody2_1 b/Data/flags/nbody2_flags
similarity index 100%
rename from Data/flags/nbody2_1
rename to Data/flags/nbody2_flags
diff --git a/Data/flags/nbody_prestudy_flag1 b/Data/flags/nbody_prestudy_flags
similarity index 100%
rename from Data/flags/nbody_prestudy_flag1
rename to Data/flags/nbody_prestudy_flags
diff --git a/Data/flags/new_plus_1 b/Data/flags/new_plus_flags
similarity index 100%
rename from Data/flags/new_plus_1
rename to Data/flags/new_plus_flags
diff --git a/Data/flags/shell_prestudy_flag1 b/Data/flags/shell_prestudy_flags
similarity index 100%
rename from Data/flags/shell_prestudy_flag1
rename to Data/flags/shell_prestudy_flags
diff --git a/Data/flags/snap_C02_200_127_animation_1 b/Data/flags/snap_animation_flags
similarity index 100%
rename from Data/flags/snap_C02_200_127_animation_1
rename to Data/flags/snap_animation_flags
diff --git a/Data/flags/three_rings_1 b/Data/flags/three_rings_flags
similarity index 100%
rename from Data/flags/three_rings_1
rename to Data/flags/three_rings_flags
diff --git a/Data/flags/training_cylinder_1 b/Data/flags/training_cylinder_flags
similarity index 100%
rename from Data/flags/training_cylinder_1
rename to Data/flags/training_cylinder_flags
diff --git a/Data/flags/training_pyramid_1 b/Data/flags/training_pyramid_flags
similarity index 100%
rename from Data/flags/training_pyramid_1
rename to Data/flags/training_pyramid_flags
diff --git a/Data/flags/training_sphere_1 b/Data/flags/training_sphere_flags
similarity index 100%
rename from Data/flags/training_sphere_1
rename to Data/flags/training_sphere_flags
diff --git a/Data/flags/training_torus_1 b/Data/flags/training_torus_flags
similarity index 100%
rename from Data/flags/training_torus_1
rename to Data/flags/training_torus_flags
diff --git a/Data/flags/uniform_Lines_1 b/Data/flags/uniform_Lines_flags
similarity index 100%
rename from Data/flags/uniform_Lines_1
rename to Data/flags/uniform_Lines_flags
diff --git a/Data/flags/ununiform_Lines_1 b/Data/flags/ununiform_Lines_flags
similarity index 100%
rename from Data/flags/ununiform_Lines_1
rename to Data/flags/ununiform_Lines_flags
diff --git a/Plugins/rwth-vr-toolkit-with-meta-cast b/Plugins/rwth-vr-toolkit-with-meta-cast
index 5e91667582826960baf894d65e766f4a57a76976..fb36657e086d1dfc89e89d40d44867bf321a20b4 160000
--- a/Plugins/rwth-vr-toolkit-with-meta-cast
+++ b/Plugins/rwth-vr-toolkit-with-meta-cast
@@ -1 +1 @@
-Subproject commit 5e91667582826960baf894d65e766f4a57a76976
+Subproject commit fb36657e086d1dfc89e89d40d44867bf321a20b4
diff --git a/Source/MetaCastBachelor/PointStorage/PointCloud.cpp b/Source/MetaCastBachelor/PointStorage/PointCloud.cpp
index a9199b7fd712ff940c44bcdd8774d841ff769c6e..cbe28c55d1fc6d51cc82a58b8fedd3f769702efb 100644
--- a/Source/MetaCastBachelor/PointStorage/PointCloud.cpp
+++ b/Source/MetaCastBachelor/PointStorage/PointCloud.cpp
@@ -4,7 +4,7 @@
 
 // Sets default values
 APointCloud::APointCloud()
-	: MyDensityField(nullptr), MyKdTree(), PointCloudVisualizer(nullptr), SelectedMaterial(nullptr), UnselectedMaterial(nullptr)
+	: CurrentPointCloudIndex(0), CurrentPointCloudFlagIndex(0), MyKdTree(), PointCloudVisualizer(nullptr), MyDensityField(nullptr), SelectedMaterial(nullptr), UnselectedMaterial(nullptr)
 {
 	// Set this actor to call Tick() every frame.
 	PrimaryActorTick.bCanEverTick = true;
@@ -15,17 +15,93 @@ APointCloud::APointCloud()
 void APointCloud::BeginPlay()
 {
 	Super::BeginPlay();
+
+	CurrentPointCloudIndex = 0;
+	CurrentPointCloudFlagIndex = 0;
 	
-	ReadPointCloudFromFile(PointInputData, FlagInputData);
-	InitPointCloudVisualizer();
-	SetupDensityFieldFromPointCloud();
-	SaveStateAndUpdate();
+	InitPointCloudAndFlagFiles(PointInputFolder, FlagInputFolder);
+
+	ResetPointCloudData();
 	
 	//UKdtreeBPLibrary::BuildKdtree(MyKdTree, PositionVectors);
 	//UKdtreeBPLibrary::DumpKdtreeToConsole(MyKdTree);
 	//UKdtreeBPLibrary::ValidateKdtree(MyKdTree);
 }
 
+void APointCloud::InitPointCloudAndFlagFiles(const FFilePath& PointInputData, const FFilePath& FlagInputData)
+{
+	MyFileManager.Initialize(PointInputData.FilePath, FlagInputData.FilePath);
+
+	const int32 NumPointCloudFiles = MyFileManager.GetNumberOfPointCloudFiles();
+	UE_LOG(LogTemp, Log, TEXT("Total Point Cloud Files: %d"), NumPointCloudFiles);
+
+	PointCloudsNoFlags.Empty();
+	ValidPointClouds.Empty();
+
+	for (int32 i = 0; i < NumPointCloudFiles; ++i)
+	{
+		FString PointCloudFilePath = MyFileManager.GetPointCloudFilePath(i);
+		UE_LOG(LogTemp, Log, TEXT("Point Cloud File: %s"), *PointCloudFilePath);
+
+		const int32 NumFlagFiles = MyFileManager.GetNumberOfFlagFiles(i);
+		if (NumFlagFiles == 0)
+		{
+			UE_LOG(LogTemp, Error, TEXT("No matching flag file found for point cloud: %s"), *PointCloudFilePath);
+			PointCloudsNoFlags.Add(FFilePath{PointCloudFilePath});
+		}
+		else
+		{
+			ValidPointClouds.Add(FFilePath{PointCloudFilePath});
+			for (int32 j = 0; j < NumFlagFiles; ++j)
+			{
+				FString FlagFilePath = MyFileManager.GetFlagFilePath(i, j);
+				UE_LOG(LogTemp, Log, TEXT("    Matching Flag File: %s"), *FlagFilePath);
+			}
+		}
+	}
+
+	// Log the contents of PointCloudsNoFlags array
+	UE_LOG(LogTemp, Log, TEXT("Point Cloud Files with No Matching Flags:"));
+	for (const auto& [FilePath] : PointCloudsNoFlags)
+	{
+		UE_LOG(LogTemp, Log, TEXT("%s"), *FilePath);
+	}
+
+	// Log the contents of ValidPointClouds array
+	UE_LOG(LogTemp, Log, TEXT("Valid Point Cloud Files with Matching Flags:"));
+	for (const FFilePath& ValidFile : ValidPointClouds)
+	{
+		UE_LOG(LogTemp, Log, TEXT("%s"), *ValidFile.FilePath);
+	}
+}
+
+void APointCloud::ReadPointCloudFromIndex(const int Index)
+{
+	CurrentPointCloudIndex = Index;
+	CurrentPointCloudFlagIndex = 0;
+
+	UE_LOG(LogTemp, Log, TEXT("Resetting to index %i"), Index);
+
+	ResetPointCloudData();
+}
+
+void APointCloud::ResetPointCloudData()
+{
+	if(!ValidPointClouds.IsValidIndex(CurrentPointCloudIndex)) return;
+	
+	const FFilePath PointDataFile = ValidPointClouds[CurrentPointCloudIndex];
+	TArray<FString> PointFlagFiles = MyFileManager.GetFlagFilesForPointCloud(PointDataFile.FilePath);
+
+	if(!PointFlagFiles.IsValidIndex(CurrentPointCloudFlagIndex)) return;
+	const FFilePath FlagFile = FFilePath(PointFlagFiles[CurrentPointCloudFlagIndex]);
+	
+	ReadPointCloudFromFile(PointDataFile, FlagFile);
+	InitPointCloudVisualizer();
+	SetupDensityFieldFromPointCloud();
+	MyUndoRedoManager.Clear();
+	SaveStateAndUpdate();
+}
+
 void APointCloud::ReadPointCloudFromFile(const FFilePath FileNamePoints, const FFilePath FileNameFlags)
 {
 	const TArray<FVector> LoadedPointCloud = FPointCloudDataReader::LoadPointCloudData(FileNamePoints.FilePath);
@@ -45,13 +121,20 @@ void APointCloud::ReadPointCloudFromFile(const FFilePath FileNamePoints, const F
 	}
 
 	UE_LOG(LogTemp, Warning, TEXT("Loaded %d points and flags"), LoadedPointCloud.Num());
-	
-	this->PositionVectors = FPointCloudDataReader::NormalizeData(LoadedPointCloud, FVector::One() * 50, FVector::One() * 100, MinBounds, MaxBounds);
 
+	this->PositionVectors.Empty();
+	this->PositionVectors = FPointCloudDataReader::NormalizeData(LoadedPointCloud, FVector::One() * 50, FVector::One() * 100, MinBounds, MaxBounds);
+	MaxBounds = FVector::One() * 100;
+	
 	UE_LOG(LogTemp, Warning, TEXT("Minimum: %s ; Maximum: %s"), *MinBounds.ToString(), *MaxBounds.ToString());
 
+	this->DefaultFlags.Empty();
 	this->DefaultFlags = BooleanFlags;
+
+	this->SelectionFlags.Empty();
 	this->SelectionFlags.Init(false, DefaultFlags.Num());
+
+	this->PointColors.Empty();
 	this->PointColors.Init(FColor::Blue, PositionVectors.Num());
 }
 
@@ -63,7 +146,7 @@ void APointCloud::InitPointCloudVisualizer()
 	if (Components.Num() > 0)
 	{
 		PointCloudVisualizer = Components[0];
-
+		PointCloudVisualizer->ResetPointCloudRenderer();
 		PointCloudVisualizer->SetInputAndConvert2(PositionVectors, PointColors);
 		PointCloudVisualizer->SetDynamicProperties(FLinearColor::White, 1.0f, SplatSize * 0.1, 1000.f, false);
 	}
@@ -120,7 +203,7 @@ void APointCloud::UpdateSelection()
 			}
 		}
 	}
-	
+
 	PointCloudVisualizer->SetInputAndConvert2(PositionVectors, PointColors);
 }
 
diff --git a/Source/MetaCastBachelor/PointStorage/PointCloud.h b/Source/MetaCastBachelor/PointStorage/PointCloud.h
index 6cf8f9fd13a988b4d748d5b073e9a0af061c5160..672a0b41a907aada54a7645c0b8b39b46ade99a0 100644
--- a/Source/MetaCastBachelor/PointStorage/PointCloud.h
+++ b/Source/MetaCastBachelor/PointStorage/PointCloud.h
@@ -1,7 +1,9 @@
 #pragma once
 #include "CoreMinimal.h"
 #include "GPUPointCloudRendererComponent.h"
+#include "InputActionValue.h"
 #include "KdtreeCommon.h"
+#include "PointCloudFileManager.h"
 #include "UndoRedoManager.h"
 #include "GameFramework/Actor.h"
 #include "MetaCastBachelor/PointStorage/DensityField.h"
@@ -13,6 +15,11 @@ class APointCloud : public AActor
 {
 	GENERATED_BODY()
 
+	int CurrentPointCloudIndex;
+	int CurrentPointCloudFlagIndex;
+	TArray<FFilePath> PointCloudsNoFlags;
+	TArray<FFilePath> ValidPointClouds;
+	
 	mutable FCriticalSection DataGuard;
 	FVector MinBounds;
 	FVector MaxBounds;
@@ -33,6 +40,7 @@ class APointCloud : public AActor
 	UPROPERTY()
 	UGPUPointCloudRendererComponent* PointCloudVisualizer;
 	FUndoRedoManager MyUndoRedoManager;
+	FUPointCloudFileManager MyFileManager;
 	
 public:
 	FDensityField* MyDensityField;
@@ -44,10 +52,10 @@ public:
 	float SplatSize = 1.0f;
 	
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Files")
-	FFilePath PointInputData;
+	FFilePath PointInputFolder;
 
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Files")
-	FFilePath FlagInputData;
+	FFilePath FlagInputFolder;
 	
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Materials")
 	UMaterialInterface* SelectedMaterial;
@@ -63,7 +71,8 @@ public:
 protected:
 	// Called when the game starts or when spawned
 	virtual void BeginPlay() override;
-	
+	void InitPointCloudAndFlagFiles(const FFilePath& PointInputData, const FFilePath& FlagInputData);
+
 	virtual void Tick(float DeltaTime) override;
 
 public:
@@ -132,6 +141,12 @@ public:
 	{
 		return SelectionFlags.Num();
 	}
+
+	UFUNCTION(BlueprintCallable)
+	void ReadPointCloudFromIndex(int Index);
+
+	UFUNCTION(BlueprintCallable)
+	void ResetPointCloudData();
 	
 	UFUNCTION(BlueprintCallable)
 	void ReadPointCloudFromFile(FFilePath FileNamePoints, FFilePath FileNameFlags);
diff --git a/Source/MetaCastBachelor/PointStorage/InputDataReader.cpp b/Source/MetaCastBachelor/PointStorage/PointCloudDataReader.cpp
similarity index 100%
rename from Source/MetaCastBachelor/PointStorage/InputDataReader.cpp
rename to Source/MetaCastBachelor/PointStorage/PointCloudDataReader.cpp
diff --git a/Source/MetaCastBachelor/PointStorage/PointCloudFileManager.cpp b/Source/MetaCastBachelor/PointStorage/PointCloudFileManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5c9e3a726426bcdf7a8782f15e2f60ab8ebec42
--- /dev/null
+++ b/Source/MetaCastBachelor/PointStorage/PointCloudFileManager.cpp
@@ -0,0 +1,95 @@
+#include "PointCloudFileManager.h"
+#include "Misc/Paths.h"
+#include "Misc/FileHelper.h"
+#include "HAL/FileManager.h"
+
+FUPointCloudFileManager::FUPointCloudFileManager()
+{
+}
+
+void FUPointCloudFileManager::Initialize(const FString& PointCloudFolder, const FString& FlagFolder)
+{
+	PointCloudDataArray.Empty();
+
+	// Get all point cloud files in the folder
+	TArray<FString> PointCloudFiles;
+	IFileManager::Get().FindFiles(PointCloudFiles, *PointCloudFolder, nullptr); // No extension filter
+
+	for (const FString& PointCloudFile : PointCloudFiles)
+	{
+		FString PointCloudFilePath = FPaths::Combine(PointCloudFolder, PointCloudFile);
+		FPointCloudData PointCloudData(PointCloudFilePath);
+
+		// Find matching flag files
+		FindMatchingFlagFiles(PointCloudFilePath, FlagFolder, PointCloudData.FlagFilePaths);
+
+		if (PointCloudData.FlagFilePaths.Num() == 0)
+		{
+			//UE_LOG(LogTemp, Error, TEXT("No flag files found for point cloud file: %s"), *PointCloudFilePath);
+		}
+
+		PointCloudDataArray.Add(PointCloudData);
+	}
+}
+
+int32 FUPointCloudFileManager::GetNumberOfPointCloudFiles() const
+{
+    return PointCloudDataArray.Num();
+}
+
+FString FUPointCloudFileManager::GetPointCloudFilePath(const int32 Index) const
+{
+    if (PointCloudDataArray.IsValidIndex(Index))
+    {
+        return PointCloudDataArray[Index].PointCloudFilePath;
+    }
+    return FString();
+}
+
+int32 FUPointCloudFileManager::GetNumberOfFlagFiles(const int32 Index) const
+{
+    if (PointCloudDataArray.IsValidIndex(Index))
+    {
+        return PointCloudDataArray[Index].FlagFilePaths.Num();
+    }
+    return 0;
+}
+
+FString FUPointCloudFileManager::GetFlagFilePath(const int32 PointCloudIndex, const int32 FlagFileIndex) const
+{
+    if (PointCloudDataArray.IsValidIndex(PointCloudIndex) && PointCloudDataArray[PointCloudIndex].FlagFilePaths.IsValidIndex(FlagFileIndex))
+    {
+        return PointCloudDataArray[PointCloudIndex].FlagFilePaths[FlagFileIndex];
+    }
+    return FString();
+}
+
+TArray<FString> FUPointCloudFileManager::GetFlagFilesForPointCloud(const FString& PointCloudFilePath) const
+{
+	for (const FPointCloudData& PointCloudData : PointCloudDataArray)
+	{
+		if (PointCloudData.PointCloudFilePath == PointCloudFilePath)
+		{
+			return PointCloudData.FlagFilePaths;
+		}
+	}
+	return TArray<FString>();
+}
+
+void FUPointCloudFileManager::FindMatchingFlagFiles(const FString& PointCloudFilePath, const FString& FlagFolder, TArray<FString>& OutFlagFilePaths)
+{
+	const FString PointCloudFileName = FPaths::GetBaseFilename(PointCloudFilePath);
+
+	// Get all files in the flag folder
+	TArray<FString> FlagFiles;
+	IFileManager::Get().FindFiles(FlagFiles, *FlagFolder, nullptr); // No extension filter
+
+	for (const FString& FlagFile : FlagFiles)
+	{
+		if (FlagFile.StartsWith(PointCloudFileName + TEXT("_flags")))
+		{
+			FString FlagFilePath = FPaths::Combine(FlagFolder, FlagFile);
+			OutFlagFilePaths.Add(FlagFilePath);
+		}
+	}
+}
diff --git a/Source/MetaCastBachelor/PointStorage/PointCloudFileManager.h b/Source/MetaCastBachelor/PointStorage/PointCloudFileManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..446ad628e7934eab9323474cf5c68ffea6e223b6
--- /dev/null
+++ b/Source/MetaCastBachelor/PointStorage/PointCloudFileManager.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Engine/DataAsset.h"
+#include "PointCloudFileManager.generated.h"
+
+USTRUCT(BlueprintType)
+struct FPointCloudData
+{
+	GENERATED_BODY()
+
+	FString PointCloudFilePath;
+	TArray<FString> FlagFilePaths;
+
+	FPointCloudData() {}
+
+	explicit FPointCloudData(const FString& InPointCloudFilePath)
+		: PointCloudFilePath(InPointCloudFilePath)
+	{}
+};
+
+/**
+ * Class that manages point cloud files and their corresponding flag files.
+ */
+class FUPointCloudFileManager
+{
+public:
+	FUPointCloudFileManager();
+
+	// Loads all point cloud and flag files from the specified directories
+	void Initialize(const FString& PointCloudFolder, const FString& FlagFolder);
+
+	// Gets the number of available point cloud files
+	int32 GetNumberOfPointCloudFiles() const;
+
+	// Gets the point cloud file path by index
+	FString GetPointCloudFilePath(int32 Index) const;
+
+	// Gets the number of flag files corresponding to a point cloud file by index
+	int32 GetNumberOfFlagFiles(int32 Index) const;
+
+	// Gets the flag file path by point cloud index and flag file index
+	FString GetFlagFilePath(int32 PointCloudIndex, int32 FlagFileIndex) const;
+
+	// Gets the flag files corresponding to a given point cloud file path
+	TArray<FString> GetFlagFilesForPointCloud(const FString& PointCloudFilePath) const;
+
+private:
+	// Helper method to find matching flag files for a given point cloud file
+	static void FindMatchingFlagFiles(const FString& PointCloudFilePath, const FString& FlagFolder, TArray<FString>& OutFlagFilePaths);
+
+private:
+	TArray<FPointCloudData> PointCloudDataArray;
+};
\ No newline at end of file
diff --git a/Source/MetaCastBachelor/PointStorage/UndoRedoManager.h b/Source/MetaCastBachelor/PointStorage/UndoRedoManager.h
index 0ea22243a3526c038ef96e2cffe085e7816211b7..725a9811f1a39d3b01f9dddad76439c28e061241 100644
--- a/Source/MetaCastBachelor/PointStorage/UndoRedoManager.h
+++ b/Source/MetaCastBachelor/PointStorage/UndoRedoManager.h
@@ -52,6 +52,13 @@ public:
 		return false;
 	}
 
+	// Resets the undo and redo stacks
+	void Clear()
+	{
+		UndoStack.Empty();
+		RedoStack.Empty();
+	}
+
 private:
 	TArray<FSelectionState> UndoStack;
 	TArray<FSelectionState> RedoStack;
diff --git a/Source/MetaCastBachelor/StudyManager.cpp b/Source/MetaCastBachelor/StudyManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a97ed4be2fd33f8aef6decbea614573b0902a10b
--- /dev/null
+++ b/Source/MetaCastBachelor/StudyManager.cpp
@@ -0,0 +1,19 @@
+#include "StudyManager.h"
+
+void UStudyManager::InitializeParticipant(const int32 ParticipantID)
+{
+	CurrentParticipantID = ParticipantID;
+	
+	StudyOrder = LatinSquare.GetOrder(ParticipantID);
+	StudyOrder.Insert(EStudyState::Tutorial, 0);  // Insert Tutorial at the beginning
+	StudyOrder.Add(EStudyState::Final);  // Append Final at the end
+	
+	CurrentState = StudyOrder[0];  // Start with Tutorial
+
+	// Log initial setup for debugging
+	UE_LOG(LogTemp, Warning, TEXT("Study initialized for participant ID: %d"), CurrentParticipantID);
+	for (EStudyState State : StudyOrder)
+	{
+		UE_LOG(LogTemp, Log, TEXT("Order: %d"), (int32)State);
+	}
+}
diff --git a/Source/MetaCastBachelor/StudyManager.h b/Source/MetaCastBachelor/StudyManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..7cb7fad8e2bb5153c3d359999c6f7608fda0f4d8
--- /dev/null
+++ b/Source/MetaCastBachelor/StudyManager.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Engine/GameInstance.h"
+#include "StudyManager.generated.h"
+
+UENUM(BlueprintType)
+enum class EStudyState : uint8
+{
+	Tutorial,
+	Brush,
+	MagicWand,
+	MetaPoint,
+	Final
+};
+
+/**
+ * Helper struct to manage Latin square method for 3 methods.
+ */
+USTRUCT(BlueprintType)
+struct FLatinSquare
+{
+	GENERATED_BODY()
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite)
+	TArray<EStudyState> Order;
+
+	FLatinSquare()
+	{
+		// Default order
+		Order = { EStudyState::Brush, EStudyState::MagicWand, EStudyState::MetaPoint };
+	}
+
+	/**
+	 * Get order based on participant ID.
+	 */
+	TArray<EStudyState> GetOrder(const int32 ParticipantID) const
+	{
+		const int32 Index = ParticipantID % 3;
+		TArray<EStudyState> RotatedOrder = Order;
+
+		// Rotate the array according to the index
+		for (int32 i = 0; i < Index; ++i)
+		{
+			EStudyState First = RotatedOrder[0];
+			RotatedOrder.RemoveAt(0);
+			RotatedOrder.Add(First);
+		}
+		return RotatedOrder;
+	}
+};
+
+/**
+ * Game Instance class to manage the study.
+ */
+UCLASS()
+class UStudyManager : public UGameInstance
+{
+	GENERATED_BODY()
+
+public:
+	UFUNCTION(BlueprintCallable)
+	void InitializeParticipant(int32 ParticipantID);
+
+private:
+	int32 CurrentParticipantID;
+	TArray<EStudyState> StudyOrder;
+	EStudyState CurrentState;
+	FLatinSquare LatinSquare;
+};
+