초보 코린이의 성장 일지
UE4 Weapon Plugin (7) 본문
이제 체크박스를 클릭시 알맞은 데이터가 노출되고, 선택하지 않은 데이터는 안보이도록 만들어 볼 것이다.
위에 조건도 수용하면서, 새로고침이 되면 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