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触发代码中即可。最后再记录顶点操作位置,再在运行时还原,即可实现这样的编辑器下顶点修改编辑需求。

相关推荐
SomeB1oody2 分钟前
【Rust自学】5.3. struct的方法(Method)
开发语言·后端·rust
无 证明37 分钟前
new 分配空间;引用
数据结构·c++
Kisorge1 小时前
【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
c语言·开发语言
轻口味2 小时前
命名空间与模块化概述
开发语言·前端·javascript
晓纪同学3 小时前
QT-简单视觉框架代码
开发语言·qt
威桑3 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服3 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生3 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生3 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans3 小时前
C# 中串口读取问题及解决方案
开发语言·c#