From 0a9ce7b371cb4ccf57ceba318aeb6b54da153b44 Mon Sep 17 00:00:00 2001 From: jamestagg Date: Wed, 14 Jan 2026 17:22:39 -0600 Subject: [PATCH] Add setup_scene command for automated scene setup The setup_scene command creates all required actors for rendering control: - PostProcessVolume (unbound, with auto-exposure override) - DirectionalLight (sun) - SkyLight - ExponentialHeightFog - CineCameraActor This allows full AI control without manual UE5 setup. Co-Authored-By: Claude Opus 4.5 --- .../RalphaCore/Private/RalphaMCPServer.cpp | 5 + .../Private/RalphaParameterBridge.cpp | 135 ++++++++++++++++++ .../RalphaCore/Public/RalphaParameterBridge.h | 3 + 3 files changed, 143 insertions(+) diff --git a/Plugins/RalphaPlugin/Source/RalphaCore/Private/RalphaMCPServer.cpp b/Plugins/RalphaPlugin/Source/RalphaCore/Private/RalphaMCPServer.cpp index 288e387b..6673c126 100644 --- a/Plugins/RalphaPlugin/Source/RalphaCore/Private/RalphaMCPServer.cpp +++ b/Plugins/RalphaPlugin/Source/RalphaCore/Private/RalphaMCPServer.cpp @@ -361,6 +361,11 @@ FString URalphaMCPServer::ProcessCommand(const FString& JsonCommand) ResponseObject->SetStringField(TEXT("error"), TEXT("Missing settings")); } } + else if (CommandType == TEXT("setup_scene")) + { + TSharedPtr SetupResult = ParameterBridge->SetupScene(); + ResponseObject = SetupResult; + } else { ResponseObject->SetBoolField(TEXT("success"), false); diff --git a/Plugins/RalphaPlugin/Source/RalphaCore/Private/RalphaParameterBridge.cpp b/Plugins/RalphaPlugin/Source/RalphaCore/Private/RalphaParameterBridge.cpp index 0228cbee..feba6c77 100644 --- a/Plugins/RalphaPlugin/Source/RalphaCore/Private/RalphaParameterBridge.cpp +++ b/Plugins/RalphaPlugin/Source/RalphaCore/Private/RalphaParameterBridge.cpp @@ -879,3 +879,138 @@ TSharedPtr URalphaParameterBridge::GetActorDetails(const FString& A return Result; } + +// ============================================================================ +// Scene Setup +// ============================================================================ + +TSharedPtr URalphaParameterBridge::SetupScene() +{ + TSharedPtr Result = MakeShared(); + TArray CreatedActors; + TArray ExistingActors; + + UWorld* World = GetCurrentWorld(); + if (!World) + { + Result->SetBoolField(TEXT("success"), false); + Result->SetStringField(TEXT("error"), TEXT("No world available")); + return Result; + } + + // Check/Create PostProcessVolume + if (!FindPostProcessVolume()) + { + FActorSpawnParameters SpawnParams; + SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + APostProcessVolume* PPV = World->SpawnActor(FVector::ZeroVector, FRotator::ZeroRotator, SpawnParams); + if (PPV) + { + PPV->bUnbound = true; + PPV->Settings.bOverride_AutoExposureBias = true; + PPV->Settings.AutoExposureBias = 0.0f; +#if WITH_EDITOR + PPV->SetActorLabel(TEXT("Ralpha_PostProcess")); +#endif + CreatedActors.Add(TEXT("PostProcessVolume")); + } + } + else + { + ExistingActors.Add(TEXT("PostProcessVolume")); + } + + // Check/Create DirectionalLight + if (!FindDirectionalLight()) + { + FActorSpawnParameters SpawnParams; + SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + ADirectionalLight* Light = World->SpawnActor(FVector::ZeroVector, FRotator(-45.0f, 0.0f, 0.0f), SpawnParams); + if (Light) + { +#if WITH_EDITOR + Light->SetActorLabel(TEXT("Ralpha_Sun")); +#endif + CreatedActors.Add(TEXT("DirectionalLight")); + } + } + else + { + ExistingActors.Add(TEXT("DirectionalLight")); + } + + // Check/Create SkyLight + if (!FindSkyLight()) + { + FActorSpawnParameters SpawnParams; + SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + ASkyLight* Light = World->SpawnActor(FVector(0.0f, 0.0f, 1000.0f), FRotator::ZeroRotator, SpawnParams); + if (Light) + { +#if WITH_EDITOR + Light->SetActorLabel(TEXT("Ralpha_SkyLight")); +#endif + CreatedActors.Add(TEXT("SkyLight")); + } + } + else + { + ExistingActors.Add(TEXT("SkyLight")); + } + + // Check/Create ExponentialHeightFog + if (!FindExponentialHeightFog()) + { + FActorSpawnParameters SpawnParams; + SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + AExponentialHeightFog* Fog = World->SpawnActor(FVector::ZeroVector, FRotator::ZeroRotator, SpawnParams); + if (Fog) + { +#if WITH_EDITOR + Fog->SetActorLabel(TEXT("Ralpha_Fog")); +#endif + CreatedActors.Add(TEXT("ExponentialHeightFog")); + } + } + else + { + ExistingActors.Add(TEXT("ExponentialHeightFog")); + } + + // Check/Create CineCameraActor + if (!FindCineCamera()) + { + FActorSpawnParameters SpawnParams; + SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + ACineCameraActor* Camera = World->SpawnActor(FVector(0.0f, -500.0f, 200.0f), FRotator(0.0f, 90.0f, 0.0f), SpawnParams); + if (Camera) + { +#if WITH_EDITOR + Camera->SetActorLabel(TEXT("Ralpha_Camera")); +#endif + CreatedActors.Add(TEXT("CineCameraActor")); + } + } + else + { + ExistingActors.Add(TEXT("CineCameraActor")); + } + + Result->SetBoolField(TEXT("success"), true); + + TArray> CreatedArray; + for (const FString& Actor : CreatedActors) + { + CreatedArray.Add(MakeShared(Actor)); + } + Result->SetArrayField(TEXT("created"), CreatedArray); + + TArray> ExistingArray; + for (const FString& Actor : ExistingActors) + { + ExistingArray.Add(MakeShared(Actor)); + } + Result->SetArrayField(TEXT("existing"), ExistingArray); + + return Result; +} diff --git a/Plugins/RalphaPlugin/Source/RalphaCore/Public/RalphaParameterBridge.h b/Plugins/RalphaPlugin/Source/RalphaCore/Public/RalphaParameterBridge.h index 5c85eafb..182b8ec6 100644 --- a/Plugins/RalphaPlugin/Source/RalphaCore/Public/RalphaParameterBridge.h +++ b/Plugins/RalphaPlugin/Source/RalphaCore/Public/RalphaParameterBridge.h @@ -63,6 +63,9 @@ public: bool SetActorTransform(const FString& ActorId, const FVector* Location, const FRotator* Rotation, const float* Scale, bool bRelative); TSharedPtr GetActorDetails(const FString& ActorId, bool bIncludeComponents, bool bIncludeMaterials); + // Scene Setup - creates required actors for rendering control + TSharedPtr SetupScene(); + private: // Find actors of specific types in the world APostProcessVolume* FindPostProcessVolume();