Files
UnrealEngine/Engine/Plugins/Runtime/SmartObjects/Source/SmartObjectsModule/Private/SmartObjectContainerRenderingComponent.cpp
2025-05-18 13:04:45 +08:00

125 lines
4.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SmartObjectContainerRenderingComponent.h"
#include "Engine/CollisionProfile.h"
#include "PrimitiveViewRelevance.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(SmartObjectContainerRenderingComponent)
#if WITH_EDITORONLY_DATA
#include "Engine/CollisionProfile.h"
#include "MeshElementCollector.h"
#include "PrimitiveDrawingUtils.h"
#include "DebugRenderSceneProxy.h"
#include "Math/ColorList.h"
#include "SmartObjectPersistentCollection.h"
#else
#include "Engine/CollisionProfile.h"
#endif
#if WITH_EDITORONLY_DATA
//----------------------------------------------------------------------//
// FSOContainerRenderingSceneProxy
//----------------------------------------------------------------------//
class FSOContainerRenderingSceneProxy final : public FDebugRenderSceneProxy
{
public:
/** Initialization constructor. */
FSOContainerRenderingSceneProxy(const USmartObjectContainerRenderingComponent& InComponent)
: FDebugRenderSceneProxy(&InComponent)
{
ASmartObjectPersistentCollection* Owner = Cast<ASmartObjectPersistentCollection>(InComponent.GetOwner());
if (Owner == nullptr || Owner->IsEmpty() || Owner->ShouldDebugDraw() == false)
{
return;
}
OwnerLocation = Owner->GetActorLocation();
EndLocations.Reserve(Owner->GetSmartObjectContainer().GetEntries().Num());
for (const FSmartObjectCollectionEntry& Entry : Owner->GetSmartObjectContainer().GetEntries())
{
const FVector EntryLocation = Entry.GetTransform().GetLocation();
EndLocations.Add(EntryLocation);
}
}
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
{
constexpr float ArrowLineThickness = 5.f;
constexpr float ArrowHeadSize = 30.f;
static const FLinearColor RadiusColor = FLinearColor(FColorList::Orange);
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
if (VisibilityMap & (1 << ViewIndex))
{
FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
for (const FVector& Location : EndLocations)
{
PDI->DrawLine(OwnerLocation, Location, RadiusColor, SDPG_World, ArrowLineThickness, /*DepthBias=*/0.f, /*bScreenSpace=*/true);
DrawArrowHead(PDI, Location, OwnerLocation, ArrowHeadSize, RadiusColor, SDPG_World, ArrowLineThickness, /*bScreenSpace=*/true);
}
}
}
}
virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
{
FPrimitiveViewRelevance Result;
Result.bDrawRelevance = IsShown(View) && IsSelected();
Result.bDynamicRelevance = true;
// ideally the TranslucencyRelevance should be filled out by the material, here we do it conservative
Result.bSeparateTranslucency = Result.bNormalTranslucency = IsShown(View);
return Result;
}
FVector OwnerLocation;
TArray<FVector> EndLocations;
};
#endif // WITH_EDITORONLY_DATA
//----------------------------------------------------------------------//
// USmartObjectContainerRenderingComponent
//----------------------------------------------------------------------//
USmartObjectContainerRenderingComponent::USmartObjectContainerRenderingComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
// Allows updating in game, while optimizing rendering for the case that it is not modified
Mobility = EComponentMobility::Stationary;
BodyInstance.SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
bIsEditorOnly = true;
SetGenerateOverlapEvents(false);
}
FPrimitiveSceneProxy* USmartObjectContainerRenderingComponent::CreateSceneProxy()
{
#if WITH_EDITORONLY_DATA
return new FSOContainerRenderingSceneProxy(*this);
#else
return nullptr;
#endif // WITH_EDITORONLY_DATA
}
FBoxSphereBounds USmartObjectContainerRenderingComponent::CalcBounds(const FTransform& LocalToWorld) const
{
FBox BoundingBox(EForceInit::ForceInitToZero);
#if WITH_EDITORONLY_DATA
const ASmartObjectPersistentCollection* Owner = Cast<ASmartObjectPersistentCollection>(GetOwner());
if (Owner && HasAnyFlags(RF_BeginDestroyed) == false)
{
FVector Origin(ForceInit), BoxExtent(ForceInit);
Owner->GetActorBounds(/*bOnlyCollidingComponents=*/false, Origin, BoxExtent);
BoundingBox = FBox(Origin - BoxExtent, Origin + BoxExtent);
BoundingBox += Owner->GetBounds();
}
#endif // WITH_EDITORONLY_DATA
return FBoxSphereBounds(BoundingBox);
}