UE5 C++ 通过绑定编辑器事件实现控制柄顶点编辑

开发中经常会遇到编辑器环境中制作工具拖拽控制柄编辑内容的需求,此时可以通过Editor事件拿到对应回调,进行相应更新:

1.创建Mesh编辑Actor类

创建一个Mesh编辑Actor类,提供Mesh顶点编辑的相关逻辑。

.h:

cpp 复制代码
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ProceduralMeshComponent.h"
#include "DraggableHandleActor.h"
#include "CustomMeshActor.generated.h"

UCLASS()
class MYPROJECT6_API ACustomMeshActor : public AActor
{
	GENERATED_BODY()
	
public:	
	ACustomMeshActor();

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UProceduralMeshComponent* MeshComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	ADraggableHandleActor* HandleP0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	ADraggableHandleActor* HandleP1;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	ADraggableHandleActor* HandleP2;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	ADraggableHandleActor* HandleP3;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	void OnRebuild();

	UFUNCTION()
	void OnHandleP0Moved();

	UFUNCTION()
	void OnHandleP1Moved();

	UFUNCTION()
	void OnHandleP2Moved();

	UFUNCTION()
	void OnHandleP3Moved();
};

.cpp:

cpp 复制代码
#include "CustomMeshActor.h"

ACustomMeshActor::ACustomMeshActor()
{
	PrimaryActorTick.bCanEverTick = true;

	MeshComponent = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("ProceduralMesh"));
	RootComponent = MeshComponent;
}

void ACustomMeshActor::BeginPlay()
{
	Super::BeginPlay();
	
    HandleP0->OnHandleMoved.AddDynamic(this, &ACustomMeshActor::OnHandleP0Moved);
    HandleP1->OnHandleMoved.AddDynamic(this, &ACustomMeshActor::OnHandleP1Moved);
    HandleP2->OnHandleMoved.AddDynamic(this, &ACustomMeshActor::OnHandleP2Moved);
    HandleP3->OnHandleMoved.AddDynamic(this, &ACustomMeshActor::OnHandleP3Moved);

    this->OnRebuild();
}

void ACustomMeshActor::OnRebuild()
{
    TArray<FVector> Vertices;
    
    FTransform ActorTransform = GetActorTransform();

    Vertices.Add(HandleP0->GetActorLocation());
    Vertices.Add(HandleP1->GetActorLocation());
    Vertices.Add(HandleP2->GetActorLocation());
    Vertices.Add(HandleP3->GetActorLocation());

    TArray<int32> Triangles;
    Triangles.Add(0);
    Triangles.Add(1);
    Triangles.Add(2);

    Triangles.Add(0);
    Triangles.Add(2);
    Triangles.Add(3);

    // 定义 UV 坐标
    TArray<FVector2D> UV0;
    UV0.Add(FVector2D(0.0f, 0.0f));
    UV0.Add(FVector2D(0.0f, 1.0f));
    UV0.Add(FVector2D(1.0f, 1.0f));
    UV0.Add(FVector2D(1.0f, 0.0f));

    // 法线
    TArray<FVector> Normals;
    Normals.Add(FVector(0.0f, 0.0f, 1.0f));
    Normals.Add(FVector(0.0f, 0.0f, 1.0f));
    Normals.Add(FVector(0.0f, 0.0f, 1.0f));
    Normals.Add(FVector(0.0f, 0.0f, 1.0f));

    // 切线
    TArray<FProcMeshTangent> Tangents;
    Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
    Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
    Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));
    Tangents.Add(FProcMeshTangent(1.0f, 0.0f, 0.0f));

    TArray<FColor> VertexColors;
    VertexColors.Add(FLinearColor::White.ToFColor(true));
    VertexColors.Add(FLinearColor::White.ToFColor(true));
    VertexColors.Add(FLinearColor::White.ToFColor(true));
    VertexColors.Add(FLinearColor::White.ToFColor(true));

    MeshComponent->ClearAllMeshSections();
    MeshComponent->CreateMeshSection(0, Vertices, Triangles, Normals, UV0, VertexColors, Tangents, true);
}

void ACustomMeshActor::OnHandleP0Moved()
{
    OnRebuild();
}

void ACustomMeshActor::OnHandleP1Moved()
{
    OnRebuild();
}

void ACustomMeshActor::OnHandleP2Moved()
{
    OnRebuild();
}

void ACustomMeshActor::OnHandleP3Moved()
{
    OnRebuild();
}

这部分代码通过UE的ProceduralMeshComponent动态创建顶点和Mesh。

2.创建操作柄

第二步需要实现拖拽操作柄或者修改界面数值得到回调,从而更新Mesh,在UE中这一块的编辑器回调有如下:

cpp 复制代码
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; //UE面板修改数值
virtual void PostEditMove(bool bFinished) override; //UE界面拖拽Actor

接下来编写Actor - DraggableHandleActor来实现这样的逻辑:

.h

cpp 复制代码
#pragma once

#include "CoreMinimal.h"
#include "DraggableHandleActor.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnHandleMoved);

UCLASS()
class MYPROJECT6_API ADraggableHandleActor : public AActor
{
    GENERATED_BODY()

public:
    ADraggableHandleActor();

#if WITH_EDITOR
    virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
    virtual void PostEditMove(bool bFinished) override;
#endif
    // Delegate for handle moved callback
    UPROPERTY(BlueprintAssignable, Category = "Handle Events")
    FOnHandleMoved OnHandleMoved; // Delegate for broadcasting the movement
};

.cpp:

cpp 复制代码
#include "DraggableHandleActor.h"

ADraggableHandleActor::ADraggableHandleActor()
{
}

#if WITH_EDITOR

void ADraggableHandleActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
    Super::PostEditChangeProperty(PropertyChangedEvent);

    OnHandleMoved.Broadcast();
}

void ADraggableHandleActor::PostEditMove(bool bFinished)
{
    Super::PostEditMove(bFinished);

    OnHandleMoved.Broadcast();
}

#endif

注意这里定义了一个委托来给外部绑定回调:

cpp 复制代码
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnHandleMoved);

3.UE整合

最后在UE中绑定控制柄对应的Actor,并放置进对应的UMG或者Editor触发代码中即可。最后再记录顶点操作位置,再在运行时还原,即可实现这样的编辑器下顶点修改编辑需求。

相关推荐
西西学代码12 分钟前
Flutter---异步编程
开发语言·前端·javascript
卡提西亚17 分钟前
C++笔记-26-类模板
c++·笔记
song85460113418 分钟前
锁的初步学习
开发语言·python·学习
重整旗鼓~24 分钟前
38.附近商户实现
java·开发语言
沐怡旸32 分钟前
【穿越Effective C++】条款19:设计class犹如设计type——用户定义类型的艺术与科学
c++·面试
一个不知名程序员www35 分钟前
算法学习入门---模拟(C++)
c++·算法
夜月yeyue44 分钟前
嵌入式开发中的 Git CI/CD
c++·git·单片机·嵌入式硬件·ci/cd·硬件架构
曹勖之1 小时前
UE5 的 Waterline Pro 6的浮力作用机制解析
ue5
曹勖之1 小时前
UE5 UDS(Ultra Dynamic Sky)动态天气天空如何采用官方光源和雾
ue5
❀͜͡傀儡师1 小时前
JDK 25 新特性速览
java·开发语言