초보 코린이의 성장 일지

UE4 Weapon Plugin (7) 본문

언리얼

UE4 Weapon Plugin (7)

코오린이 2023. 6. 12. 16:18

이제 체크박스를 클릭시 알맞은 데이터가 노출되고, 선택하지 않은 데이터는 안보이도록 만들어 볼 것이다.

위에 조건도 수용하면서, 새로고침이 되면 CreateCheckBoxes로 만들어진 체크박스는 사라지는게 아닌 유지가 되어야한다. 그 이유는 한번 클릭할때마다 박스가 생성이된다면 그전에 있던 박스에 정보들을 지우고 새롭게 생성하기 때문에 가지고 있는 정보를 소유하고 있어야한다.


더보기
#pragma once

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

class WEAPON_API SWeaponDetailsView
	: public IDetailCustomization
{
public:
	void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;

public:
	// 외부에서 바꿔줄 수 있도록 return 함수
	static void OnRefreshByCheckBoxes() { bRefreshByCheckBoxes = true; }
	static void OffRefreshByCheckBoxes() { bRefreshByCheckBoxes = false; }


private:
	static bool bRefreshByCheckBoxes;

};
#include "SWeaponDetailsView.h"
#include "SWeaponCheckBoxes.h"
#include "SWeaponEquipmentData.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "IDetailPropertyRow.h"
#include "Weapons/CWeaponAsset.h"

bool SWeaponDetailsView::bRefreshByCheckBoxes = false;

void SWeaponDetailsView::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
	//GLog->Log("CustomizeDetails");
	UClass* type = UCWeaponAsset::StaticClass(); // 타입 받아오기.

	DetailBuilder.HideCategory("CWeaponAsset"); // 카테고리 숨기기

	// Class Settings
	{
		// 언리얼에 보여질 식별자 이름, 실제로 보여질 카테고리 이름
		IDetailCategoryBuilder& category = DetailBuilder.EditCategory("ClassSettings", FText::FromString("Class Settings"));
		category.AddProperty("AttachmentClass", type);
		category.AddProperty("EquipmentClass", type);
		category.AddProperty("DoActionClass", type);

	}

	// EquipmentData
	{
		IDetailCategoryBuilder& category = DetailBuilder.EditCategory("EquipmentData", FText::FromString("Equipment Data"));
		IDetailPropertyRow& row = category.AddProperty("EquipmentData", type);

		// 새로고침이 아닐때만 실행되도록, Properties로 인해 추가되므로 한번만 실행되게 해야한다.
		if (bRefreshByCheckBoxes == false)
		{
			// 처음에 만들어질때 CheckBox 생성
			TSharedPtr<SWeaponCheckBoxes> checkBoxes = SWeaponEquipmentData::CreateCheckBoxes();
			checkBoxes->AddProperties(row.GetPropertyHandle()); // 실제로 가진 Handle 추가해준다.
		}
	}

}

1. 처음에 그려지는지, 새로고침이 일어나면 그려지는지 판단할 수 있는 변수를 선언해준다.

2. bRefreshByCheckBoxes로 조건 체크후 생성할수 있도록 만들어준다.


더보기
#include "SweaponEquipmentData.h"
#include "IPropertyUtilities.h"
#include "IDetailPropertyRow.h"
#include "IDetailChildrenBuilder.h"
#include "DetailWidgetRow.h"
#include "IDetailCustomization.h"
#include "SWeaponCheckBoxes.h"

// 매개변수 InPropertyHandle가 해당 변수에 식별자를 나타낸다.
void SWeaponEquipmentData::CustomizeHeader(TSharedRef<IPropertyHandle> InPropertyHandle, FDetailWidgetRow& InHeaderRow, IPropertyTypeCustomizationUtils& InCustomizationUtils)
{
    // CheckBoxes로 넘겨줄 객체, 커스텀 마이징할때 도움을 주는 기능
    CheckBoxes->SetUtilities(InCustomizationUtils.GetPropertyUtilities());
   // GLog->Log("CustomizeHeader");

 
}

1. CheckBoxes로 넘겨줄 객체가 SWeaponEquipmentData기 때문에 이곳에서 처리를 해준다.


1. WeqponEquipmentData에 있는 내용이 들어올 것이므로, 주석처리 후 옮겨줄 것이다.

더보기

 

#pragma once

#include "CoreMinimal.h"

class WEAPON_API SWeaponCheckBoxes
	: public TSharedFromThis<SWeaponCheckBoxes> // 직접적으로 상속받으면 주소가 일치하게된다.
{
public:
	// 해당 Properties를 그릴지 말지 결정
	void DrawProperties(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder* InChildrenBuilder);
	
    // 객체를 외부에서 받기위해,
	void SetUtilities(TSharedPtr<class IPropertyUtilities> InUtilities);

private:
	// 내부 구조체 생성, 관리를 위해 사용
	struct FInternalData
	{
		bool bChecked;
		FString Name;
		TSharedPtr<IPropertyHandle> Handle;

		FInternalData(TSharedPtr<IPropertyHandle> InHandle)
		{
			bChecked = false;
			Handle = InHandle;

			// 출력할 이름
			Name = Handle->GetPropertyDisplayName().ToString();
		}
	};
	TArray<FInternalData> InternalDatas;

	TSharedPtr<class IPropertyUtilities> Utilities;
};

 

#include "SWeaponCheckBoxes.h"
#include "SWeaponDetailsView.h"
#include "Widgets/Layout/SUniformGridPanel.h"
#include "IPropertyUtilities.h"
#include "IDetailPropertyRow.h"
#include "IDetailChildrenBuilder.h"
#include "DetailWidgetRow.h"

void SWeaponCheckBoxes::SetUtilities(TSharedPtr<IPropertyUtilities> InUtilities)
{
	// 외부 객체 받아오기
	Utilities = InUtilities;
}

void SWeaponCheckBoxes::DrawProperties(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder* InChildrenBuilder)
{
	for (int32 i = 0; i < InternalDatas.Num(); i++)
	{
  	  // 체크박스에 체크를 바꾸게 되는지 확인, 바꾸지 안았다면 그릴 필요가 없다.
		if (InternalDatas[i].bChecked == false)
			continue;
		// 각 줄에 식별자
		TSharedPtr<IPropertyHandle> handle = InPropertyHandle->GetChildHandle(i);
		// 자식부분을 담당, 이 Handle이 기본모양을 추가해서 만들어준다. 커스텀 마이징도 가능하다
		IDetailPropertyRow& row = InChildrenBuilder->AddProperty(handle.ToSharedRef());

		FString name = FString("Name ") + FString::FromInt(i + 1);

		row.CustomWidget()
			.NameContent()
			[
				handle->CreatePropertyNameWidget()
			]
		.ValueContent()
			.MinDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
			.MaxDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MaxDesiredSlotWidth"))
			[
				handle->CreatePropertyValueWidget()
			];
	}
}

void SWeaponCheckBoxes::OnCheckStateChanged(ECheckBoxState InState, int32 InIndex)
{
	//// 로그로 출력 확인
	//GLog->Log(FString::FromInt(InIndex));
	//GLog->Log(StaticEnum<ECheckBoxState>()->GetValueAsString(InState));

	// 상태를 바뀌는걸 확인했기때문에, 값을 뒤집어 줘서 다시 안그려지게 만들어준다.
	InternalDatas[InIndex].bChecked = !InternalDatas[InIndex].bChecked;

	SWeaponDetailsView::OnRefreshByCheckBoxes(); 
	{
		// ForceRefresh이 콜이되면 새로고침이 되면서 다시 그려진다.
		Utilities->ForceRefresh();
	}
	SWeaponDetailsView::OffRefreshByCheckBoxes();

}

1. SWeaponEquipmentData에서 넘겨주는 객체를 받아온다.

2. 새로고침되면 정보를 받아서 다시 그려준다.


더보기
#pragma once

#include "CoreMinimal.h"
#include "IPropertyTypeCustomization.h"

class WEAPON_API SWeaponEquipmentData
	: public IPropertyTypeCustomization
{
public:
	void CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) override;

};
#include "SweaponEquipmentData.h"
#include "IPropertyUtilities.h"
#include "IDetailPropertyRow.h"
#include "IDetailChildrenBuilder.h"
#include "DetailWidgetRow.h"
#include "IDetailCustomization.h"
#include "SWeaponCheckBoxes.h"

void SWeaponEquipmentData::CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils)
{
   // GLog->Log("CustomizeChildren");

    //uint32 number = 0;
    //InPropertyHandle->GetNumChildren(number); // HeaderHandle를 통해서 자식이 몇개가 있는지 알아내야한다.

    //for (uint32 i = 0; i < number; i++)
    //{
    //    // 각 줄에 식별자
    //    TSharedPtr<IPropertyHandle> handle = InPropertyHandle->GetChildHandle(i);
    //    // 자식부분을 담당, 이 Handle이 기본모양을 추가해서 만들어준다. 커스텀 마이징도 가능하다
    //    IDetailPropertyRow& row = InChildBuilder.AddProperty(handle.ToSharedRef());

    //    FString name = FString("Name ") + FString::FromInt(i + 1);

    //    row.CustomWidget()
    //        .NameContent()
    //        [
    //           handle->CreatePropertyNameWidget()
    //        ]
    //	    .ValueContent()
    //        .MinDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
    //        .MaxDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MaxDesiredSlotWidth"))
    //        [
    //            handle->CreatePropertyValueWidget()
    //        ];
    //}

    CheckBoxes->DrawProperties(InPropertyHandle, &InChildBuilder);
}

1. SWeaponCheckBoxes로 옮긴 정보들을 간략하게 함수로 콜해주면서 끝낸다.

 


https://www.youtube.com/watch?v=rVA53qNKIHk 

 

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

UE4 Weapon Plugin (9)  (0) 2023.06.14
UE4 Weapon Plugin (8)  (2) 2023.06.13
UE4 Weapon Plugin (6)  (0) 2023.06.09
UE4 Weapon Plugin (5)  (2) 2023.06.07
UE4 Weapon Plugin (4)  (0) 2023.06.01
Comments