// DTFluxRemoteActor.cpp #include "DTFluxRemotedLevelController.h" #include "DTFluxRemoteSubsystem.h" #include "Engine/Engine.h" #include "Engine/World.h" ADTFluxRemotedLevelController::ADTFluxRemotedLevelController() { PrimaryActorTick.bCanEverTick = false; RemoteSubsystem = nullptr; bEventsBound = false; UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: Constructor called")); } void ADTFluxRemotedLevelController::PostInitializeComponents() { Super::PostInitializeComponents(); UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: PostInitializeComponents called")); // Essayer de bind dès que possible InitializeSubsystemBinding(); } void ADTFluxRemotedLevelController::BeginPlay() { Super::BeginPlay(); UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: BeginPlay called")); // S'assurer que le binding est fait (au cas où PostInitializeComponents aurait échoué) if (!bEventsBound) { InitializeSubsystemBinding(); } } void ADTFluxRemotedLevelController::InitializeSubsystemBinding() { // Éviter le double binding if (bEventsBound) { UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: Events already bound, skipping")); return; } // Récupérer le subsystem if (UWorld* World = GetWorld()) { RemoteSubsystem = GEngine->GetEngineSubsystem(); if (RemoteSubsystem) { // Bind les events du subsystem RemoteSubsystem->OnTitleReceived.AddDynamic( this, &ADTFluxRemotedLevelController::OnTitleDataReceived ); RemoteSubsystem->OnTitleBibReceived.AddDynamic( this, &ADTFluxRemotedLevelController::OnTitleBibDataReceived ); RemoteSubsystem->OnCommandReceived.AddDynamic( this, &ADTFluxRemotedLevelController::OnCommandDataReceived ); bEventsBound = true; UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: Successfully bound to subsystem events")); } else { UE_LOG(LogTemp, Warning, TEXT("DTFluxRemoteActor: DTFluxRemoteSubsystem not available yet")); } } else { UE_LOG(LogTemp, Warning, TEXT("DTFluxRemoteActor: World not available yet")); } } void ADTFluxRemotedLevelController::EnsureSubsystemBinding() { if (!bEventsBound) { InitializeSubsystemBinding(); } } void ADTFluxRemotedLevelController::EndPlay(const EEndPlayReason::Type EndPlayReason) { // Unbind les events pour éviter les fuites mémoire if (RemoteSubsystem && bEventsBound) { if (TitleReceivedHandle.IsValid()) { RemoteSubsystem->OnTitleReceived.RemoveDynamic(this, &ADTFluxRemotedLevelController::OnTitleDataReceived); TitleReceivedHandle.Reset(); } if (TitleBibReceivedHandle.IsValid()) { RemoteSubsystem->OnTitleBibReceived.RemoveDynamic(this, &ADTFluxRemotedLevelController::OnTitleBibDataReceived); TitleBibReceivedHandle.Reset(); } if (CommandReceivedHandle.IsValid()) { RemoteSubsystem->OnCommandReceived.RemoveDynamic(this, &ADTFluxRemotedLevelController::OnCommandDataReceived); CommandReceivedHandle.Reset(); } bEventsBound = false; UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: Unbound from subsystem events")); } Super::EndPlay(EndPlayReason); } void ADTFluxRemotedLevelController::OnTitleDataReceived(const FDTFluxRemoteTitleData& TitleData) { UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: Received Title Data - %s %s (RundownPageId: %d)"), *TitleData.FirstName, *TitleData.LastName, TitleData.RundownPageId); // Broadcast l'event Blueprint OnTitleReceived.Broadcast(TitleData); // Appeler l'event Blueprint implémentable BP_OnTitleDataReceived(TitleData); // Appeler la fonction virtuelle C++ (peut être overridée dans les classes dérivées) HandleTitleData(TitleData); } void ADTFluxRemotedLevelController::OnTitleBibDataReceived(const FDTFluxRemoteBibData& BibData) { UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: Received Title Bib Data - Bib: %d"), BibData.Bib); // Broadcast l'event Blueprint OnTitleBibReceived.Broadcast(BibData); // Appeler l'event Blueprint implémentable BP_OnTitleBibDataReceived(BibData); // Appeler la fonction virtuelle C++ (peut être overridée dans les classes dérivées) HandleTitleBibData(BibData); } void ADTFluxRemotedLevelController::OnCommandDataReceived(const FDTFluxRemoteCommandData& CommandData) { UE_LOG(LogTemp, Log, TEXT("DTFluxRemoteActor: Received Command Data - Type: %s, : RundownPageId %i"), *CommandData.Type, CommandData.RundownPageId); // Broadcast l'event Blueprint OnCommandReceived.Broadcast(CommandData); // Appeler l'event Blueprint implémentable BP_OnCommandDataReceived(CommandData); // Appeler la fonction virtuelle C++ (peut être overridée dans les classes dérivées) HandleCommandData(CommandData); } bool ADTFluxRemotedLevelController::IsSubsystemAvailable() const { return RemoteSubsystem && RemoteSubsystem->IsValidLowLevel(); } bool ADTFluxRemotedLevelController::IsHTTPServerRunning() const { if (RemoteSubsystem) { return RemoteSubsystem->IsHTTPServerRunning(); } return false; } void ADTFluxRemotedLevelController::StartHTTPServer(int32 Port) { if (RemoteSubsystem) { RemoteSubsystem->StartHTTPServer(Port); } else { UE_LOG(LogTemp, Warning, TEXT("DTFluxRemoteActor: Cannot start HTTP server - subsystem not available")); } } void ADTFluxRemotedLevelController::StopHTTPServer() { if (RemoteSubsystem) { RemoteSubsystem->StopHTTPServer(); } else { UE_LOG(LogTemp, Warning, TEXT("DTFluxRemoteActor: Cannot stop HTTP server - subsystem not available")); } } // Implémentations par défaut des fonctions virtuelles C++ void ADTFluxRemotedLevelController::HandleTitleData_Implementation(const FDTFluxRemoteTitleData& TitleData) { // Implémentation par défaut - peut être overridée dans les classes dérivées UE_LOG(LogTemp, Verbose, TEXT("DTFluxRemoteActor: Handling Title Data (default implementation)")); } void ADTFluxRemotedLevelController::HandleTitleBibData_Implementation(const FDTFluxRemoteBibData& BibData) { // Implémentation par défaut - peut être overridée dans les classes dérivées UE_LOG(LogTemp, Verbose, TEXT("DTFluxRemoteActor: Handling Title Bib Data (default implementation)")); } void ADTFluxRemotedLevelController::HandleCommandData_Implementation(const FDTFluxRemoteCommandData& CommandData) { // Implémentation par défaut - peut être overridée dans les classes dérivées UE_LOG(LogTemp, Verbose, TEXT("DTFluxRemoteActor: Handling Command Data (default implementation)")); }