diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.cpp index 6512aaa81..1bc08cbab 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.cpp @@ -12,7 +12,7 @@ #include "GameFramework/Controller.h" -void FActorDispatcher::Bind(FActorDefinition Definition, SpawnFunctionType Functor) +void UActorDispatcher::Bind(FActorDefinition Definition, SpawnFunctionType Functor) { if (UActorBlueprintFunctionLibrary::CheckActorDefinition(Definition)) { @@ -27,7 +27,7 @@ void FActorDispatcher::Bind(FActorDefinition Definition, SpawnFunctionType Funct } } -void FActorDispatcher::Bind(ACarlaActorFactory &ActorFactory) +void UActorDispatcher::Bind(ACarlaActorFactory &ActorFactory) { for (const auto &Definition : ActorFactory.GetDefinitions()) { @@ -37,7 +37,7 @@ void FActorDispatcher::Bind(ACarlaActorFactory &ActorFactory) } } -TPair FActorDispatcher::SpawnActor( +TPair UActorDispatcher::SpawnActor( const FTransform &Transform, FActorDescription Description) { @@ -59,7 +59,7 @@ TPair FActorDispatcher::SpawnActor( Result.Status = EActorSpawnResultStatus::UnknownError; } - auto View = Result.IsValid() ? Registry.Register(*Result.Actor, std::move(Description)) : FActorView(); + auto View = Result.IsValid() ? RegisterActor(*Result.Actor, std::move(Description)) : FActorView(); if (!View.IsValid()) { @@ -70,7 +70,7 @@ TPair FActorDispatcher::SpawnActor( return MakeTuple(Result.Status, View); } -bool FActorDispatcher::DestroyActor(AActor *Actor) +bool UActorDispatcher::DestroyActor(AActor *Actor) { if (Actor == nullptr) { UE_LOG(LogCarla, Error, TEXT("Trying to destroy nullptr actor")); @@ -102,9 +102,18 @@ bool FActorDispatcher::DestroyActor(AActor *Actor) UE_LOG(LogCarla, Log, TEXT("Destroying actor: '%s'"), *Id); if (Actor->Destroy()) { - Registry.Deregister(Actor); return true; } UE_LOG(LogCarla, Error, TEXT("Failed to destroy actor: '%s'"), *Id); return false; } + +FActorView UActorDispatcher::RegisterActor(AActor &Actor, FActorDescription Description) +{ + auto View = Registry.Register(Actor, std::move(Description)); + if (View.IsValid()) + { + Actor.OnDestroyed.AddDynamic(this, &UActorDispatcher::OnActorDestroyed); + } + return View; +} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.h index c50482c33..cfbcc37b2 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.h @@ -14,12 +14,17 @@ #include "Containers/Array.h" #include "Templates/Function.h" +#include "ActorDispatcher.generated.h" + class ACarlaActorFactory; -/// Actor in charge of binding ActorDefinitions to spawn functions, as well as +/// Object in charge of binding ActorDefinitions to spawn functions, as well as /// keeping the registry of all the actors spawned. -class FActorDispatcher +UCLASS() +class CARLA_API UActorDispatcher : public UObject { + GENERATED_BODY() + public: using SpawnFunctionType = TFunction; @@ -51,16 +56,15 @@ public: /// destruction, false if indestructible or nullptr. bool DestroyActor(AActor *Actor); + /// Register an actor that was not created using "SpawnActor" function but + /// that should be kept in the registry. + FActorView RegisterActor(AActor &Actor, FActorDescription ActorDescription); + const TArray &GetActorDefinitions() const { return Definitions; } - FActorRegistry &GetActorRegistry() - { - return Registry; - } - const FActorRegistry &GetActorRegistry() const { return Registry; @@ -68,6 +72,12 @@ public: private: + UFUNCTION() + void OnActorDestroyed(AActor *Actor) + { + Registry.Deregister(Actor); + } + TArray Definitions; TArray SpawnFunctions; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp index c95877de4..367b0c32d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp @@ -38,7 +38,9 @@ UCarlaEpisode::UCarlaEpisode(const FObjectInitializer &ObjectInitializer) Id([]() { static uint32 COUNTER = 0u; return ++COUNTER; - }()) {} + }()) { + ActorDispatcher = CreateDefaultSubobject(TEXT("ActorDispatcher")); +} TArray UCarlaEpisode::GetRecommendedSpawnPoints() const { @@ -90,7 +92,7 @@ void UCarlaEpisode::InitializeAtBeginPlay() FActorDescription Description; Description.Id = TEXT("spectator"); Description.Class = Spectator->GetClass(); - ActorDispatcher.GetActorRegistry().Register(*Spectator, Description); + ActorDispatcher->RegisterActor(*Spectator, Description); } else { @@ -104,6 +106,6 @@ void UCarlaEpisode::InitializeAtBeginPlay() FActorDescription Description; Description.Id = UCarlaEpisode_GetTrafficSignId(Actor->GetTrafficSignState()); Description.Class = Actor->GetClass(); - ActorDispatcher.GetActorRegistry().Register(*Actor, Description); + ActorDispatcher->RegisterActor(*Actor, Description); } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.h index cc3cd797f..238801b59 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.h @@ -58,7 +58,7 @@ public: UFUNCTION(BlueprintCallable) const TArray &GetActorDefinitions() const { - return ActorDispatcher.GetActorDefinitions(); + return ActorDispatcher->GetActorDefinitions(); } /// Return the list of recommended spawn points for vehicles. @@ -90,7 +90,7 @@ public: const FActorRegistry &GetActorRegistry() const { - return ActorDispatcher.GetActorRegistry(); + return ActorDispatcher->GetActorRegistry(); } // =========================================================================== @@ -105,7 +105,7 @@ public: /// invalid. FActorView FindActor(FActorView::IdType ActorId) const { - return ActorDispatcher.GetActorRegistry().Find(ActorId); + return ActorDispatcher->GetActorRegistry().Find(ActorId); } /// Find the actor view of @a Actor. @@ -114,7 +114,7 @@ public: /// invalid. FActorView FindActor(AActor *Actor) const { - return ActorDispatcher.GetActorRegistry().Find(Actor); + return ActorDispatcher->GetActorRegistry().Find(Actor); } /// Find the actor view of @a Actor. If the actor is not found, a "fake" view @@ -124,7 +124,7 @@ public: /// If the actor is pending kill, the returned view is invalid. FActorView FindOrFakeActor(AActor *Actor) const { - return ActorDispatcher.GetActorRegistry().FindOrFake(Actor); + return ActorDispatcher->GetActorRegistry().FindOrFake(Actor); } // =========================================================================== @@ -143,7 +143,7 @@ public: const FTransform &Transform, FActorDescription ActorDescription) { - return ActorDispatcher.SpawnActor(Transform, std::move(ActorDescription)); + return ActorDispatcher->SpawnActor(Transform, std::move(ActorDescription)); } /// Spawns an actor based on @a ActorDescription at @a Transform. To properly @@ -170,7 +170,7 @@ public: UFUNCTION(BlueprintCallable) bool DestroyActor(AActor *Actor) { - return ActorDispatcher.DestroyActor(Actor); + return ActorDispatcher->DestroyActor(Actor); } // =========================================================================== @@ -194,7 +194,7 @@ private: void RegisterActorFactory(ACarlaActorFactory &ActorFactory) { - ActorDispatcher.Bind(ActorFactory); + ActorDispatcher->Bind(ActorFactory); } const uint32 Id = 0u; @@ -202,7 +202,8 @@ private: UPROPERTY(VisibleAnywhere) FString MapName; - FActorDispatcher ActorDispatcher; + UPROPERTY(VisibleAnywhere) + UActorDispatcher *ActorDispatcher = nullptr; UPROPERTY(VisibleAnywhere) APawn *Spectator = nullptr; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp index 3294033a8..0a3588f1a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp @@ -75,21 +75,21 @@ static carla::Buffer AWorldObserver_Serialize( write_data(header); // Write every actor. - for (auto &&actor_view : Registry) { - check(actor_view.GetActor() != nullptr); + for (auto &&View : Registry) { + check(View.IsValid()); constexpr float TO_METERS = 1e-2; - const auto velocity = TO_METERS * actor_view.GetActor()->GetVelocity(); + const auto velocity = TO_METERS * View.GetActor()->GetVelocity(); // get the angular velocity - const auto RootComponent = Cast(actor_view.GetActor()->GetRootComponent()); + const auto RootComponent = Cast(View.GetActor()->GetRootComponent()); FVector angularVelocity { 0.0f, 0.0f, 0.0f }; if (RootComponent != nullptr) angularVelocity = RootComponent->GetPhysicsAngularVelocityInDegrees(); ActorDynamicState info = { - actor_view.GetActorId(), - actor_view.GetActor()->GetActorTransform(), + View.GetActorId(), + View.GetActor()->GetActorTransform(), carla::geom::Vector3D{velocity.X, velocity.Y, velocity.Z}, carla::geom::Vector3D{angularVelocity.X, angularVelocity.Y, angularVelocity.Z}, - AWorldObserver_GetActorState(actor_view) + AWorldObserver_GetActorState(View) }; write_data(info); }