Files
2025-05-18 13:04:45 +08:00

102 lines
2.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SceneStateEventUtils.h"
#include "Engine/World.h"
#include "SceneStateEventLog.h"
#include "SceneStateEventSchema.h"
#include "SceneStateEventSchemaHandle.h"
#include "SceneStateEventStream.h"
#include "SceneStateEventSubsystem.h"
#include "SceneStateEventTemplate.h"
#include "StructUtils/InstancedStruct.h"
namespace UE::SceneState
{
namespace Private
{
bool IsEventStreamInContext(const USceneStateEventStream* InEventStream, const UObject* InEventContext)
{
// Special case for Worlds: instead of checking outer chain, check that the world the event stream returns is the same
if (const UWorld* ContextWorld = Cast<UWorld>(InEventContext))
{
return GetContextWorld(InEventStream) == ContextWorld;
}
return InEventStream->IsIn(InEventContext);
}
} // Private
bool PushEvent(USceneStateEventStream* InEventStream, const FSceneStateEventSchemaHandle& InEventSchemaHandle, FInstancedStruct&& InEventData)
{
if (!InEventStream)
{
return false;
}
const USceneStateEventSchemaObject* EventSchema = InEventSchemaHandle.GetEventSchema();
if (!EventSchema)
{
return false;
}
InEventStream->PushEvent(EventSchema->CreateEvent(MoveTemp(InEventData)));
return true;
}
bool PushEvent(USceneStateEventStream* InEventStream, const FSceneStateEventTemplate& InEventTemplate)
{
return PushEvent(InEventStream, InEventTemplate.GetEventSchemaHandle(), FInstancedStruct(InEventTemplate.GetEventData()));
}
const UWorld* GetContextWorld(const UObject* InObject)
{
const UWorld* World = InObject ? InObject->GetWorld() : nullptr;
return World ? World : GWorld;
}
bool BroadcastEvent(const UObject* InEventContext, const FSceneStateEventSchemaHandle& InEventSchemaHandle, FInstancedStruct&& InEventData)
{
if (!InEventContext)
{
UE_LOG(LogSceneStateEvent, Error, TEXT("Broadcast event failed. Event context is invalid."));
return false;
}
USceneStateEventSubsystem* const EventSubsystem = USceneStateEventSubsystem::Get();
if (!EventSubsystem)
{
UE_LOG(LogSceneStateEvent, Error, TEXT("Broadcast event failed. Event subsystem not found."));
return false;
}
const USceneStateEventSchemaObject* EventSchema = InEventSchemaHandle.GetEventSchema();
if (!EventSchema)
{
UE_LOG(LogSceneStateEvent, Error, TEXT("Broadcast event failed. Event schema not found."));
return false;
}
const FSharedStruct Event = EventSchema->CreateEvent(MoveTemp(InEventData));
EventSubsystem->ForEachEventStream(
[&Event, InEventContext](USceneStateEventStream* InEventStream)
{
// Only consider event streams that are within the context
if (Private::IsEventStreamInContext(InEventStream, InEventContext))
{
InEventStream->PushEvent(Event);
}
});
return true;
}
bool BroadcastEvent(const UObject* InEventContext, const FSceneStateEventTemplate& InEventTemplate)
{
return BroadcastEvent(InEventContext, InEventTemplate.GetEventSchemaHandle(), FInstancedStruct(InEventTemplate.GetEventData()));
}
} // UE::SceneState