Unreal Engine/C++

[Unreal Engine C++] 에디터의 디테일 패널에서 속성을 수정할 때 호출되는 함수 PostEditChangeProperty / PostEditChangeChainProperty

한돌이 2024. 7. 12. 16:29

 PostEditChangeProperty 함수와 PostEditChangeChainProperty 함수는 Unreal Engine의 에디터에서만 실행되는 함수입니다. 이 함수들은 에디터에서 변수 값이 변경될 때 추가적인 처리를 할 수 있게 해줍니다. 이러한 변경 사항은 주로 디테일 패널에서 속성을 수정할 때 발생합니다. 에디터에서만 실행되는 함수 이므로 WITH_EDITOR 매크로를 사용했습니다.

// .h
#if WITH_EDITOR
protected:
	virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
	virtual void PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent) override;
#endif

// .cpp
#if WITH_EDITOR
void UPRAISpawnArea::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
{
}

void UPRAISpawnArea::PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent)
{
}
#endif

 

PostEditChangeProperty

 PostEditChangeProperty 함수는 디테일 패널에서 단일 속성의 값이 변경될 때 호출되며 변경된 속성에 대해 단일 속성 변경 이벤트를 처리합니다. 함수에 주어진 FPRopertyChangedEvent 구조체의 Property의 Name을 GET_MEMBER_NAME_CHECKED 매크로로 해당 클래스의 변경된 변수의 이름을 비교하여 일치할 경우 구현한 동작을 실행하는 방식입니다. 사용하는 방법은 다음과 같습니다.

// .h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "PRAISpawnArea.generated.h"

/**
 * 범위내에 존재하는 AISpawnPoint를 탐색하는 SceneComponent 클래스입니다.
 */
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class PROJECTREPLICA_API UPRAISpawnArea : public USceneComponent
{
	GENERATED_BODY()

public:	
	UPRAISpawnArea();

#if WITH_EDITOR
protected:
	/** 디테일 패널에서 단일 속성의 값이 변경될 때 변경된 속성에 대해 단일 속성 변경 이벤트를 처리합니다. */
	virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
#endif

private:
	/** SpawnArea의 Index입니다. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PRAISpawnArea", meta = (AllowPrivateAccess = "true"))
	int32 SpawnAreaIndex;

	/** SpawnAreaBox의 범위입니다. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "PRAISpawnArea", meta = (AllowPrivateAccess = "true", DisplayPriority = 0))
	FVector SpawnAreaBoxExtent;
};
// .cpp

UPRAISpawnArea::UPRAISpawnArea()
{
	SpawnAreaIndex = INDEX_NONE;
	SpawnAreaBoxExtent = FVector(100.0f, 100.0f, 100.0f);
}

#if WITH_EDITOR
void UPRAISpawnArea::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);

	if(PropertyChangedEvent.Property)
	{
		FName PropertyName = PropertyChangedEvent.GetPropertyName();
		PR_LOG_WARNING("PostEditChangeProperty PropertyName: %s", *PropertyName.ToString());
		if(PropertyName == GET_MEMBER_NAME_CHECKED(UPRAISpawnArea, SpawnAreaBoxExtent))
		{
			PR_LOG_WARNING("Find PostEditChangeProperty PropertyName: %s", *PropertyName.ToString());
		}
		else if(PropertyName == GET_MEMBER_NAME_CHECKED(UPRAISpawnArea, SpawnAreaIndex))
		{
			PR_LOG_WARNING("Find PostEditChangeProperty PropertyName: %s", *PropertyName.ToString());
		}
		else
		{
			PR_LOG_WARNING("PostEditChangeProperty Property False");
		}
	}
}
#endif

 해당 클래스를 월드에 배치하고 디테일 패널에서 기본 값이 FVector(100.0f, 100.0f, 100.0f)인 SpawnAreaBoxExtent와 -1인 SpawnAreaIndex의 값을 변경한 결과는 다음과 같습니다.

SpawnAreaBoxExtent의 X값을 변경
SpawnAreaBoxExtent의 Y값을 변경
SpawnAreaBoxExtent의 Z값을 변경
FVector 값을 붙여넣기
SpawnAreaBoxExtent의 디폴트 값으로 변경
SpawnAreaIndex의 값을 변경
SpawnAreaIndex의 디폴트 값으로 변경

 

PostEditChangeChainProperty

 PostEditChangeChainProperty 함수는 디테일 패널에서 구조체의 값이 변경되거나, 여러 속성이 연쇄적으로 변경될 때 호출되며, 여러 속성의 연쇄적 변경을 한 번에 처리할 수 있습니다.

 PostEditChangeProperty와 마찬가지로 함수에 주어진 FPropertyChangedChainEvent 구조체를 사용하지만, PostEditChangeChainProperty는 Property가 아닌 PropertyChain 구조체를 사용하였습니다. 해당 구조체를 사용하여 GET_MEMBER_NAME_CHECKED 매크로로 변수의 이름을 비교하여 구현하면 됩니다. 이번에는 PostEditChangeChainProperty를 사용하여 각 함수 값에 출력되는 Name을 출력하기만 했습니다.

// .h

#if WITH_EDITOR
protected:
	/** 디테일 패널에서 구조체의 값이 변경되거나, 여러 속성이 연쇄적으로 변경될 때 여러 속성의 연쇄적 변경을 한 번에 처리합니다. */
	virtual void PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent) override;
#endif
// .cpp

#if WITH_EDITOR
void UPRAISpawnArea::PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent)
{
	Super::PostEditChangeChainProperty(PropertyChangedEvent);
	
	const FName PropertyStrName = PropertyChangedEvent.GetPropertyName();
	const FName MemberPropertyName = PropertyChangedEvent.GetMemberPropertyName();
	PR_LOG_ERROR("PostEditChangeChainProperty PropertyName: %s", *PropertyStrName.ToString());
	PR_LOG_ERROR("PostEditChangeChainProperty MemberPropertyName: %s", *MemberPropertyName.ToString());

	const FName HeadName = PropertyChangedEvent.PropertyChain.GetHead()->GetValue()->GetFName();
	const FName TailName = PropertyChangedEvent.PropertyChain.GetTail()->GetValue()->GetFName();
	PR_LOG_ERROR("PostEditChangeChainProperty Head: %s", *HeadName.ToString());
	PR_LOG_ERROR("PostEditChangeChainProperty Tail: %s", *TailName.ToString());

	const FName ActivateNodeName = PropertyChangedEvent.PropertyChain.GetActiveNode()->GetValue()->GetFName();
	const FName ActivateMemberNodeName = PropertyChangedEvent.PropertyChain.GetActiveMemberNode()->GetValue()->GetFName();
	PR_LOG_ERROR("PostEditChangeChainProperty MemberNodeName: %s", *ActivateNodeName.ToString());
	PR_LOG_ERROR("PostEditChangeChainProperty MemberNodeName: %s", *ActivateMemberNodeName.ToString());
}
#endif

SpawnAreaBoxExtent의 X값을 변경
SpawnAreaBoxExtent의 Y값을 변경
SpawnAreaBoxExtent의 Z값을 변경
FVector 값을 붙여넣기
SpawnAreaBoxExtent의 디폴트 값으로 변경
SpawnAreaIndex의 값을 변경
SpawnAreaIndex의 디폴트 값으로 변경