diff --git a/Source/RealtimeMeshComponent/Private/RealtimeMesh.cpp b/Source/RealtimeMeshComponent/Private/RealtimeMesh.cpp index 0c2a6ed..239fc9e 100644 --- a/Source/RealtimeMeshComponent/Private/RealtimeMesh.cpp +++ b/Source/RealtimeMeshComponent/Private/RealtimeMesh.cpp @@ -36,9 +36,61 @@ URealtimeMesh::URealtimeMesh(const FObjectInitializer& ObjectInitializer) { } +void URealtimeMesh::BroadcastBoundsChangedEvent() +{ + if (!IsInGameThread()) + { + TWeakObjectPtr WeakThis(this); + AsyncTask(ENamedThreads::GameThread, [WeakThis]() + { + if (const auto Mesh = WeakThis.Get()) + { + Mesh->BoundsChangedEvent.Broadcast(Mesh); + } + }); + } + else + { + BoundsChangedEvent.Broadcast(this); + } +} + +void URealtimeMesh::BroadcastRenderDataChangedEvent(bool bShouldRecreateProxies) +{ + if (!IsInGameThread()) + { + TWeakObjectPtr WeakThis(this); + AsyncTask(ENamedThreads::GameThread, [WeakThis, bShouldRecreateProxies]() + { + if (const auto Mesh = WeakThis.Get()) + { + Mesh->RenderDataChangedEvent.Broadcast(Mesh, bShouldRecreateProxies); + } + }); + } + else + { + RenderDataChangedEvent.Broadcast(this, bShouldRecreateProxies); + } +} + void URealtimeMesh::BroadcastCollisionBodyUpdatedEvent(UBodySetup* NewBodySetup) { - CollisionBodyUpdatedEvent.Broadcast(this, NewBodySetup); + if (!IsInGameThread()) + { + TWeakObjectPtr WeakThis(this); + AsyncTask(ENamedThreads::GameThread, [WeakThis, NewBodySetup]() + { + if (const auto Mesh = WeakThis.Get()) + { + Mesh->CollisionBodyUpdatedEvent.Broadcast(Mesh, NewBodySetup); + } + }); + } + else + { + CollisionBodyUpdatedEvent.Broadcast(this, NewBodySetup); + } } void URealtimeMesh::Initialize(const TSharedRef& InSharedResources) @@ -64,6 +116,8 @@ void URealtimeMesh::Initialize(const TSharedRefGetGuard()); + UE_LOG(LogTemp, Warning, TEXT("RM Resetting... %s"), *GetName()); if (!bCreateNewMeshData) { @@ -122,6 +176,8 @@ void URealtimeMesh::RemoveTrailingLOD() void URealtimeMesh::SetupMaterialSlot(int32 MaterialSlot, FName SlotName, UMaterialInterface* InMaterial) { + RealtimeMesh::FRealtimeMeshScopeGuardWrite ScopeGuard(SharedResources->GetGuard()); + // Does this slot already exist? if (SlotNameLookup.Contains(SlotName)) { @@ -148,27 +204,33 @@ void URealtimeMesh::SetupMaterialSlot(int32 MaterialSlot, FName SlotName, UMater int32 URealtimeMesh::GetMaterialIndex(FName MaterialSlotName) const { + RealtimeMesh::FRealtimeMeshScopeGuardRead ScopeGuard(SharedResources->GetGuard()); + const int32* SlotIndex = SlotNameLookup.Find(MaterialSlotName); return SlotIndex ? *SlotIndex : INDEX_NONE; } bool URealtimeMesh::IsMaterialSlotNameValid(FName MaterialSlotName) const { + RealtimeMesh::FRealtimeMeshScopeGuardRead ScopeGuard(SharedResources->GetGuard()); return SlotNameLookup.Contains(MaterialSlotName); } FRealtimeMeshMaterialSlot URealtimeMesh::GetMaterialSlot(int32 SlotIndex) const { + RealtimeMesh::FRealtimeMeshScopeGuardRead ScopeGuard(SharedResources->GetGuard()); return MaterialSlots[SlotIndex]; } int32 URealtimeMesh::GetNumMaterials() const { + RealtimeMesh::FRealtimeMeshScopeGuardRead ScopeGuard(SharedResources->GetGuard()); return MaterialSlots.Num(); } TArray URealtimeMesh::GetMaterialSlotNames() const { + RealtimeMesh::FRealtimeMeshScopeGuardRead ScopeGuard(SharedResources->GetGuard()); TArray OutNames; SlotNameLookup.GetKeys(OutNames); return OutNames; @@ -176,11 +238,13 @@ TArray URealtimeMesh::GetMaterialSlotNames() const TArray URealtimeMesh::GetMaterialSlots() const { + RealtimeMesh::FRealtimeMeshScopeGuardRead ScopeGuard(SharedResources->GetGuard()); return MaterialSlots; } UMaterialInterface* URealtimeMesh::GetMaterial(int32 SlotIndex) const { + RealtimeMesh::FRealtimeMeshScopeGuardRead ScopeGuard(SharedResources->GetGuard()); if (MaterialSlots.IsValidIndex(SlotIndex)) { return MaterialSlots[SlotIndex].Material; diff --git a/Source/RealtimeMeshComponent/Public/RealtimeMesh.h b/Source/RealtimeMeshComponent/Public/RealtimeMesh.h index f415fbf..b5267a4 100644 --- a/Source/RealtimeMeshComponent/Public/RealtimeMesh.h +++ b/Source/RealtimeMeshComponent/Public/RealtimeMesh.h @@ -42,8 +42,8 @@ class REALTIMEMESHCOMPONENT_API URealtimeMesh : public UObject, public IInterfac FCollisionBodyUpdated& OnCollisionBodyUpdated() { return CollisionBodyUpdatedEvent; } protected: - void BroadcastBoundsChangedEvent() { BoundsChangedEvent.Broadcast(this); } - void BroadcastRenderDataChangedEvent(bool bShouldRecreateProxies) { RenderDataChangedEvent.Broadcast(this, bShouldRecreateProxies); } + void BroadcastBoundsChangedEvent(); + void BroadcastRenderDataChangedEvent(bool bShouldRecreateProxies); void BroadcastCollisionBodyUpdatedEvent(UBodySetup* NewBodySetup); void Initialize(const TSharedRef& InSharedResources);