Here is a little example on how to use cluster events in C++, e.g., reacting to UMG user input, or keyboard input which is otherwise not synced yet in the CAVE.
You can now find it in the Snippets section of the Unreal Template.
Code Example
Here is the code you would need to use, if you don't want to use the helper class DisplayClusterEventWrapper
.
UserInputSync.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Cluster/IDisplayClusterClusterManager.h"
#include "Cluster/DisplayClusterClusterEvent.h"
#include "UserInputSync.generated.h"
UCLASS()
class DYNDIRUNREAL_API AUserInputSync : public AActor
{
GENERATED_BODY()
public:
void BeginPlay() override;
void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFUNCTION(BlueprintCallable)
void OnUserInput();
void ReactOnUserInput();
private:
FOnClusterEventJsonListener ClusterEventListenerDelegate;
void HandleClusterEvent(const FDisplayClusterClusterEventJson& Event);
};
UserInputSync.cpp
#include "UserInputSync.h"
#include "IUniversalLogging.h" //just here to give some feedback on the user's action
#include "Engine.h"
#include "IDisplayCluster.h"
void AUserInputSync::BeginPlay() {
Super::BeginPlay();
//register the listener
IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
if (ClusterManager && !ClusterEventListenerDelegate.IsBound())
{
ClusterEventListenerDelegate = FOnClusterEventJsonListener::CreateUObject(this, &AUserInputSync::HandleClusterEvent);
ClusterManager->AddClusterEventJsonListener(ClusterEventListenerDelegate);
}
//so the log shows on all slaves on screen
UniLog.GetDefaultLogStream()->SetLogOnScreenOnMaster(true);
UniLog.GetDefaultLogStream()->SetLogOnScreenOnSlaves(true);
}
void AUserInputSync::EndPlay(const EEndPlayReason::Type EndPlayReason) {
//de-register the listener again
IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
if (ClusterManager && ClusterEventListenerDelegate.IsBound())
{
ClusterManager->RemoveClusterEventJsonListener(ClusterEventListenerDelegate);
}
Super::EndPlay(EndPlayReason);
}
void AUserInputSync::ReactOnUserInput() {
//some action you want to perform on all nodes, e.g.:
UniLog.Log("Input received!");
}
void AUserInputSync::OnUserInput() {
IDisplayClusterClusterManager* const Manager = IDisplayCluster::Get().GetClusterMgr();
if (Manager)
{
if (!URWTHVRUtilities::IsRoomMountedMode()) {
//in standalone (e.g., desktop editor play) cluster events are not executed....
ReactOnUserInput();
}
else {
// else create a cluster event to react to
FDisplayClusterClusterEventJson ClusterEvent;
ClusterEvent.Name = "Some Custom Name, e.g., G pressed";
Manager->EmitClusterEventJson(ClusterEvent, true);
}
}
}
void AUserInputSync::HandleClusterEvent(const FDisplayClusterClusterEventJson& Event) {
if (Event.Name == "Some Custom Name, e.g., G pressed") {
//now we actually react on all cluster nodes:
ReactOnUserInput();
}
}