先列代码:
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Components/PrimitiveComponent.h"
#include "PaladinNPCPathLineComponent.generated.h"
class FPrimitiveSceneProxy;
UCLASS(BlueprintType, Blueprintable, meta = (BlueprintSpawnableComponent))
class PALADINSEVEN_API UPaladinNPCPathLineComponent : public UPrimitiveComponent
{
GENERATED_UCLASS_BODY()
public:
UFUNCTION(BlueprintImplementableEvent, DisplayName = "GetNPCPathPoints")
void K2_GetNPCPathPoints(TArray<FVector>& PointsArray)const;
public:
//~ Begin UObject Interface
virtual void Serialize(FArchive& Ar) override;
virtual void PostLoad() override;
#if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif // WITH_EDITOR
//~ End UObject Interface
#if !UE_BUILD_SHIPPING
//~ Begin UPrimitiveComponent Interface.
virtual FPrimitiveSceneProxy* CreateSceneProxy() override;
//~ End UPrimitiveComponent Interface.
//~ Begin USceneComponent Interface
virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override;
//~ End USceneComponent Interface
#endif
//~ Begin UPrimitiveComponent Interface.
virtual bool IsZeroExtent() const override;
virtual struct FCollisionShape GetCollisionShape(float Inflation = 0.0f) const override;
virtual bool AreSymmetricRotations(const FQuat& A, const FQuat& B, const FVector& Scale3D) const override;
//~ End UPrimitiveComponent Interface.
protected:
TArray<FVector> Points;
};
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "PaladinNPCPathLineComponent.h"
#include "WorldCollision.h"
#include "PrimitiveSceneProxy.h"
#include "SceneManagement.h"
#include "Engine/CollisionProfile.h"
UPaladinNPCPathLineComponent::UPaladinNPCPathLineComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
BodyInstance.SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
bIsEditorOnly = true;
bGenerateOverlapEvents = false;
}
#if !UE_BUILD_SHIPPING
FPrimitiveSceneProxy* UPaladinNPCPathLineComponent::CreateSceneProxy()
{
class FDrawNPCPathSceneProxy final : public FPrimitiveSceneProxy
{
public:
SIZE_T GetTypeHash() const override
{
static size_t UniquePointer;
return reinterpret_cast<size_t>(&UniquePointer);
}
FDrawNPCPathSceneProxy(const UPaladinNPCPathLineComponent* InComponent)
: FPrimitiveSceneProxy(InComponent)
, bDrawOnlyIfSelected(true)
{
bWillEverBeLit = false;
}
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
{
const FMatrix& LocalToWorld = GetLocalToWorld();
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
if (VisibilityMap & (1 << ViewIndex))
{
const FSceneView* View = Views[ViewIndex];
const FLinearColor DrawLineColor = FLinearColor::Blue;
FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
int ArrNum = Points.Num() - 1;
for (int i = 0;i<ArrNum;++i)
{
PDI->DrawLine(Points[i], Points[i + 1], DrawLineColor, SDPG_World,10.0f);
}
//DrawWireCapsule(PDI, LocalToWorld.GetOrigin(), LocalToWorld.GetScaledAxis(EAxis::X), LocalToWorld.GetScaledAxis(EAxis::Y), LocalToWorld.GetScaledAxis(EAxis::Z), DrawCapsuleColor, CapsuleRadius, CapsuleHalfHeight, CapsuleSides, SDPG_World);
}
}
}
virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
{
const bool bProxyVisible = !bDrawOnlyIfSelected || IsSelected();
FPrimitiveViewRelevance Result;
Result.bDrawRelevance = (IsShown(View) && bProxyVisible);
Result.bDynamicRelevance = true;
Result.bShadowRelevance = IsShadowCast(View);
//Result.bEditorPrimitiveRelevance = UseEditorCompositing(View);
Result.bSeparateTranslucencyRelevance = Result.bNormalTranslucencyRelevance = IsShown(View);
return Result;
}
virtual uint32 GetMemoryFootprint(void) const override { return(sizeof(*this) + GetAllocatedSize()); }
uint32 GetAllocatedSize(void) const { return(FPrimitiveSceneProxy::GetAllocatedSize()); }
void SetPoints(const TArray<FVector>& Arr) { Points = Arr; }
private:
const uint32 bDrawOnlyIfSelected : 1;
TArray<FVector> Points;
};
FDrawNPCPathSceneProxy* Proxy = new FDrawNPCPathSceneProxy(this);
K2_GetNPCPathPoints(Points);
Proxy->SetPoints(Points);
return Proxy;
}
FBoxSphereBounds UPaladinNPCPathLineComponent::CalcBounds(const FTransform& LocalToWorld) const
{
FBox MyBounds;
MyBounds.Init();
MyBounds = FBox(FVector(-HALF_WORLD_MAX, -HALF_WORLD_MAX, -HALF_WORLD_MAX), FVector(HALF_WORLD_MAX, HALF_WORLD_MAX, HALF_WORLD_MAX));
return MyBounds;
/*
FBox BoundingBox(ForceInit);
if (Points.Num()<= 0)
{
return Super::CalcBounds(LocalToWorld);
}
for (const auto& InterpPoint : Points)
{
BoundingBox += InterpPoint;
}
return FBoxSphereBounds(BoundingBox);
*/
}
#endif
void UPaladinNPCPathLineComponent::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
}
void UPaladinNPCPathLineComponent::PostLoad()
{
Super::PostLoad();
}
#if WITH_EDITOR
void UPaladinNPCPathLineComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
}
#endif // WITH_EDITOR
bool UPaladinNPCPathLineComponent::IsZeroExtent() const
{
return false;
//return (CapsuleRadius == 0.f) && (CapsuleHalfHeight == 0.f);
}
FCollisionShape UPaladinNPCPathLineComponent::GetCollisionShape(float Inflation) const
{
return Super::GetCollisionShape(Inflation);
}
bool UPaladinNPCPathLineComponent::AreSymmetricRotations(const FQuat& A, const FQuat& B, const FVector& Scale3D) const
{
return Super::AreSymmetricRotations(A,B,Scale3D);
}
绘制的部分在CreateSceneProxy内完成,而裁剪使用的Bound在CalcBounds中进行计算,上面的代码用的是最大的Bound所以肯定会显示(在物体选中的情况下),注释的代码就是计算这些点的一个有效的Bound的。
选中的时候:
这个组件有很多用途,比如策划给NPC配置一些寻路点,这些寻路组成了这个NPC行走的路线,但是策划希望点击NPC的时候能够显示出路线信息,那么这个组件就可以完成这个任务。如果你要写一个带图形的自定义控件,那么你肯定会涉及到这方面的东西。
因篇幅问题不能全部显示,请点此查看更多更全内容