초보 코린이의 성장 일지

UE4 StaticMesh 본문

언리얼

UE4 StaticMesh

코오린이 2023. 4. 6. 12:24

등록시킨 StaticMesh를 클릭하거나 에디터 맵에 올릴때 로그가 출력되도록 만들어 볼 것이다.

1. 직렬화 시켜줄 클래스를 하나 생성해준다.

1. 엔진에있는 MatineeCam_SM을 복사해서 가져와준다.

1. 머터리얼을 하나 검은색으로 생성해주고, 사용할 수 있도록 인스턴스 생성도 해준다.

더보기
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CStaticMesh.generated.h"

UCLASS()
class U2212_05_API ACStaticMesh : public AActor
{
	GENERATED_BODY()

private:
	UPROPERTY(VisibleAnywhere, Category = "Material")
		class UMaterialInstanceConstant* Material;

private:
	UPROPERTY(VisibleAnywhere)
		class UStaticMeshComponent* Mesh;

public:	
	ACStaticMesh();

protected:
	virtual void BeginPlay() override;

};
#include "CStaticMesh.h"
#include "Global.h"
#include "Components/StaticMeshComponent.h"
#include "Materials/MaterialInstanceConstant.h"


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

	CHelpers::CreateComponent<UStaticMeshComponent>(this, &Mesh, "Mesh");
	
	UStaticMesh* mesh;
	CHelpers::GetAsset<UStaticMesh>(&mesh, "StaticMesh'/Game/MatineeCam_SM.MatineeCam_SM'");
	Mesh->SetStaticMesh(mesh);

	CHelpers::GetAsset<UMaterialInstanceConstant>(&Material, "MaterialInstanceConstant'/Game/M_StaticMesh_Inst.M_StaticMesh_Inst'");
	Mesh->SetMaterial(0, Material);
}

void ACStaticMesh::BeginPlay()
{
	Super::BeginPlay();
	
}

1. 생성해준 MatineeCam과 머터리얼을 받아서 생성해준다.


1. 이제 CStaticMesh에 Type을 다뤄 볼 것이다.

2. 다루려고 하는 주제에 CStaticMesh는 다른 모듈에 있다.

3. Modules 안에 내용을 추가할수도 있다. Modules 안에 "Engine" 밑에 작성을 하게되면, 외부 모듈들을 기본 모듈들로 불러들이게 된다.

4. 중요한점은 Name 부분에 있는 이름이 해당 모듈에 이름이 된다.

1. Build 안에 해당 모듈을 작성하여 불러들여준다.

1. 프로젝트 Build에서도 Public, Private로 지정해주고 연결해준다.

FExampleModule.cpp 수정 전
FExampleModule.cpp 수정 후

1. 헤더를 추가해주고, ACStaticMesh로 변경해준다.

1. Log("Test")를 입력 후 맵상에 올려서 실행해보면 좌측 로그에 Test가 뜨는걸 볼 수 있다.

2. 클릭을 하거나 옮기거나 등 여러 동작에 로그가 출력된다.

1. 이번에는 위 사진처럼 카테고리 리스트에 있는 여러 항목을 만들어볼 것이다. 

2. 만든 카테고리 안에서는 내가 원하는것을 추가할 수도 있다.

더보기
#pragma once

#include "CoreMinimal.h"
#include "IDetailCustomization.h"

// 싱글톤으로 만들거라 생성, 소멸자 제거
class EXAMPLE_API FStaticMesh_Detail
	: public IDetailCustomization
{

public:
	static TSharedRef<IDetailCustomization> MakeInstance();

public:
	void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;
};
#include "StaticMesh_Detail.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "DetailWidgetRow.h"

TSharedRef<IDetailCustomization> FStaticMesh_Detail::MakeInstance()
{
	// 자신의 자료형 return 해준다.
	return MakeShareable(new FStaticMesh_Detail());
}

void FStaticMesh_Detail::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
	// 다른 누군가가 접근해서 건드리면 안되는 부분은 그 카테고리를 숨겨놓는다.
	IDetailCategoryBuilder& actor = DetailBuilder.EditCategory("Actor");
	actor.SetCategoryVisibility(false);

	// IDetailCategoryBuilder : 편집하라는 의미
	// 카테고리 명
	IDetailCategoryBuilder& lighting = DetailBuilder.EditCategory("Lighting");
	// 검색어 명
	IDetailCategoryBuilder& mesh = DetailBuilder.EditCategory("Mesh");

	// 커스텀해서 카테고리 행을 추가
	mesh.AddCustomRow(FText::FromString("Mesh"))
		.NameContent()
		[
			// SNew 슬레이트 UI들을 동적할당 해준다.
			SNew(STextBlock)
			.Text(FText::FromString("Color"))
		];

}

 

1. 만들어 놨던 Static를 맵에 올려보면 오른쪽 카테고리 창에 "Color"이 추가된걸 확인 할 수 있다.

2. 그리고 접근을 할 수 없도록 actor 카테고리를 숨겨 놓을 수 도 있다.

 

1. 언리얼 카테고리나, 디테일창에 나오는 항목들은 직렬화가 되었기 때문에 등장하게된다.

2. 그 한줄 한줄은 Property Row로 불러왔다.

 

더보기
#include "StaticMesh_Detail.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "DetailWidgetRow.h"

TSharedRef<IDetailCustomization> FStaticMesh_Detail::MakeInstance()
{
	// 자신의 자료형 return 해준다.
	return MakeShareable(new FStaticMesh_Detail());
}

void FStaticMesh_Detail::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
	// 다른 누군가가 접근해서 건드리면 안되는 부분은 그 카테고리를 숨겨놓는다.
	IDetailCategoryBuilder& actor = DetailBuilder.EditCategory("Actor");
	// actor.SetCategoryVisibility(false);

	// 식별자
    // 숨기고, 값 넣기, 기본값 가져오기 등 다 handle로 하게된다.
	TArray<TSharedRef<IPropertyHandle>> handles;
	actor.GetDefaultProperties(handles);

	for (TSharedRef<IPropertyHandle> handle : handles)
	{
		GLog->Log(handle->GetProperty()->GetName());
		GLog->Log(handle->GetProperty()->GetPathName());
		GLog->Log(handle->GetProperty()->GetFullName());
	}
}

1. 식별자인 Handle를 사용하여 로그를 출력해본다.

2. 대상을 맵에 올려놓으면 자연스레 로그안에 bCanBeDamaget, InitialLifeSpan등 출력이 되는걸 확인 할 수 있다.

더보기
#include "StaticMesh_Detail.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "DetailWidgetRow.h"

TSharedRef<IDetailCustomization> FStaticMesh_Detail::MakeInstance()
{
	// 자신의 자료형 return 해준다.
	return MakeShareable(new FStaticMesh_Detail());
}

void FStaticMesh_Detail::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
	// 다른 누군가가 접근해서 건드리면 안되는 부분은 그 카테고리를 숨겨놓는다.
	IDetailCategoryBuilder& actor = DetailBuilder.EditCategory("Actor");
	// actor.SetCategoryVisibility(false);

	// 식별자
	// 숨기고, 값 넣기, 기본값 가져오기 등 다 handle로 하게된다.
	TArray<TSharedRef<IPropertyHandle>> handles;
	actor.GetDefaultProperties(handles);

	for (TSharedRef<IPropertyHandle> handle : handles)
	{
		/*GLog->Log(handle->GetProperty()->GetName());
		GLog->Log(handle->GetProperty()->GetPathName());
		GLog->Log(handle->GetProperty()->GetFullName());*/

		// 0과 같다면 handle 숨겨주기.
		if (handle->GetProperty()->GetName().Compare("bCanBeDamaged") == 0)
			DetailBuilder.HideProperty(handle);
	}
}

1. 로그 출력 코드 아래에 코드를 보면 추가되어있다. 이유는 핸들을 숨겨보겠다.

2. 입력했던 부분이 숨겨져서 안보이는걸 확인 할 수 있다.

3. 이렇게 공개하지 말아야 할 것들은 숨겨줘야한다.

더보기
#pragma once

#include "CoreMinimal.h"
#include "IDetailCustomization.h"

// 싱글톤으로 만들거라 생성, 소멸자 제거
class EXAMPLE_API FStaticMesh_Detail
	: public IDetailCustomization
{

public:
	static TSharedRef<IDetailCustomization> MakeInstance();

public:
	void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;

private:
	FReply OnClicked_Paint();
};
더보기

 

#include "StaticMesh_Detail.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "DetailWidgetRow.h"

TSharedRef<IDetailCustomization> FStaticMesh_Detail::MakeInstance()
{
	// 자신의 자료형 return 해준다.
	return MakeShareable(new FStaticMesh_Detail());
}

void FStaticMesh_Detail::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
	// 다른 누군가가 접근해서 건드리면 안되는 부분은 그 카테고리를 숨겨놓는다.
	IDetailCategoryBuilder& actor = DetailBuilder.EditCategory("Actor");
	// actor.SetCategoryVisibility(false);

	// 식별자
	// 숨기고, 값 넣기, 기본값 가져오기 등 다 handle로 하게된다.
	TArray<TSharedRef<IPropertyHandle>> handles;
	actor.GetDefaultProperties(handles);

	for (TSharedRef<IPropertyHandle> handle : handles)
	{
		/*GLog->Log(handle->GetProperty()->GetName());
		GLog->Log(handle->GetProperty()->GetPathName());
		GLog->Log(handle->GetProperty()->GetFullName());*/

		// 0과 같다면 handle 숨겨주기.
		if (handle->GetProperty()->GetName().Compare("bCanBeDamaged") == 0)
			DetailBuilder.HideProperty(handle);
	}


	// IDetailCategoryBuilder : 편집하라는 의미
	// 검색어 명, 카테고리 명
	IDetailCategoryBuilder& mesh = DetailBuilder.EditCategory("Mesh");

	// 커스텀해서 카테고리 행을 추가
	mesh.AddCustomRow(FText::FromString("Mesh"))
		.NameContent() // 이름 영역
		[
			// SNew 슬레이트 UI들을 동적할당 해준다.

			SNew(STextBlock)
			.Text(FText::FromString("Color"))
		]
	.ValueContent() // 값 영역
	[
		SNew(SButton) // 버튼 올리기
		.VAlign(VAlign_Center) // 수직 정렬
		.HAlign(HAlign_Fill) // 가로 정렬
		.OnClicked(this, &FStaticMesh_Detail::OnClicked_Paint)
		//.Content() // 컨텐츠 영역을 사용하지 않아도, []이 영여이 나오면 자연스레 Content 영역으로 인식한다.
		[
			SNew(STextBlock)
			.Text(FText::FromString("Paint"))
		]
	];
}


FReply FStaticMesh_Detail::OnClicked_Paint()
{
	// 클릭용
	return FReply::Handled();
}

 

1. 버튼을 하나 생성해 볼 것이다.

2. 정렬을 시켜서 카테고리 안에 보이도록 설정. 

3. Color에 Paint 버튼이 생성되었으며, 누를수가 있는 버튼이 되었다.

4. 클릭에 관하여서는 아직 만들지 않았다.

'언리얼' 카테고리의 다른 글

UE4 StaticMesh  (0) 2023.04.12
UE4 StaticMesh  (0) 2023.04.11
UE4 Console, Command  (0) 2023.04.05
UE4 DrawDebugLine  (0) 2023.04.04
UE4 Slate UI, Plug In  (0) 2023.04.03
Comments