|
|
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](https://git-ce.rwth-aachen.de/vr-vis/VR-Group/unreal-development/unrealprojecttemplate/-/snippets).
|
|
|
|
|
|
## Code Example
|
|
|
|
|
|
Here is the code you would need to use, if you don't want to use the helper class `DisplayClusterEventWrapper`.
|
|
|
|
|
|
`UserInputSync.h`
|
|
|
```c++
|
|
|
#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:
|
|
|
|
|
|
FOnClusterEventListener ClusterEventListenerDelegate;
|
|
|
void HandleClusterEvent(const FDisplayClusterClusterEvent& Event);
|
|
|
|
|
|
};
|
|
|
```
|
|
|
|
|
|
`UserInputSync.cpp`
|
|
|
```c++
|
|
|
#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 = FOnClusterEventListener::CreateUObject(this, &AUserInputSync::HandleClusterEvent);
|
|
|
ClusterManager->AddClusterEventListener(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->RemoveClusterEventListener(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 (Manager->IsStandalone()) {
|
|
|
//in standalone (e.g., desktop editor play) cluster events are not executed....
|
|
|
ReactOnUserInput();
|
|
|
}
|
|
|
else {
|
|
|
// else create a cluster event to react to
|
|
|
FDisplayClusterClusterEvent cluster_event;
|
|
|
cluster_event.Name = "Some Custom Name, e.g., G pressed";
|
|
|
Manager->EmitClusterEvent(cluster_event, true);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void AUserInputSync::HandleClusterEvent(const FDisplayClusterClusterEvent& Event) {
|
|
|
if (Event.Name == "Some Custom Name, e.g., G pressed") {
|
|
|
//now we actually react on all cluster nodes:
|
|
|
ReactOnUserInput();
|
|
|
}
|
|
|
}
|
|
|
``` |
|
|
\ No newline at end of file |