[UE] Weapon Plugin 7: Check Box와 데이터 연결하기
목차
Plugins |
||||
Weapon |
||||
Resource |
||||
Icon128.png weapon_thumbnail_icon.png |
||||
Source |
||||
Weapon | ||||
SWeaponCheckBoxes.h .cpp SWeaponDetailsView.h .cpp SWeaponEquipmentData.h .cpp SWeaponLeftArea.h .cpp Weapon.Build.cs WeaponAssetEditor.h .cpp WeaponAssetFactory.h .cpp WeaponCommand.h .cpp WeaponContextMenu.h .cpp WeaponModule.h .cpp WeaponStyle.h .cpp |
||||
CheckBox와 데이터 연결하기
일반적인 프로그래밍과 게임 프로그래밍의 차이
일반적인 프로그래밍
Client | → ← |
Server |
- DB - MVC |
게임 프로그래밍
Client | ↔ | Server |
- Memory Map - 렌더링 데이터 |
동기화 (Replication) | - Memory Map - 게임 운용 데이터 |
- Thread 구조로 처리 | ||
Session Socket 생성 | Thread 할당( → Socket 생성 → 메모리 영역 생성) |
SWeaponCheckBoxes
SWeaponCheckBoxes.h
더보기
#pragma once
#include "CoreMinimal.h"
//스마트 포인터 내부에서 this를 참조해야 되는 경우, 아래와 같이 자기 자신을 명시해서 상속받는다. TSharedFromThis<자기 자신>
class WEAPON_API SWeaponCheckBoxes
: public TSharedFromThis<SWeaponCheckBoxes>
{
public:
//IPropertyHandle는 하나의 Property에 대한 식별자
void AddProperties(TSharedPtr<IPropertyHandle> InHandle);
TSharedRef<SWidget> Draw(bool bBackground = false);
void DrawProperties(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder* InChildrenBuilder);//해당 프로퍼티를 그릴지말지 결정
void SetUtilities(TSharedPtr<class IPropertyUtilities> InUtilities);//새로고침 값을 넘기는 역할
private:
void OnCheckStateChanged(ECheckBoxState InState, int32 InIndex);//CheckBox의 true, false를 바꾸어주는 함수
private:
//내부 구조체
struct FInternalData
{
bool bChecked;//체크 되었는가
FString Name;//이름
TSharedPtr<IPropertyHandle> Handle;//식별자
FInternalData(TSharedPtr<IPropertyHandle> InHandle)
{
bChecked = false;//기본값은 false로 설정.
Handle = InHandle;
Name = Handle->GetPropertyDisplayName().ToString();//핸들 내의 DisplayName을 출력이름으로 설정.
}
};
TArray<FInternalData> InternalDatas;//구조체 Data 전부를 포괄한 배열변수
TSharedPtr<class IPropertyUtilities> Utilities;//멤버 변수
};
함수 추가
- void DrawProperties(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder* InChildrenBuilder);
- void SetUtilities(TSharedPtr<class IPropertyUtilities> InUtilities);
변수 추가
- TSharedPtr<class IPropertyUtilities> Utilities;
SWeaponCheckBoxes.cpp
더보기
#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::AddProperties(TSharedPtr<IPropertyHandle> InHandle)
{
uint32 number = 0;
InHandle->GetNumChildren(number);//핸들 내의 자식 property가 몇 개 있는지 가져온다.
for (uint32 i = 0; i < number; i++)
InternalDatas.Add(FInternalData(InHandle->GetChildHandle(i)));
}
TSharedRef<SWidget> SWeaponCheckBoxes::Draw(bool bBackground)
{
TSharedPtr<SUniformGridPanel> panel;
SAssignNew(panel, SUniformGridPanel);
panel->SetMinDesiredSlotWidth(150);//최소폭 150으로 설정.
for(int32 i=0; i< InternalDatas.Num(); i++)
{
//그려서 넣는 부분
panel->AddSlot(i, 0)//한줄로 넣는다.
[
SNew(SCheckBox)
.IsChecked(InternalDatas[i].bChecked)
.OnCheckStateChanged(this, &SWeaponCheckBoxes::OnCheckStateChanged, i)//i는 가변 파라미터
[
SNew(STextBlock)
.Text(FText::FromString(InternalDatas[i].Name))//InternalDatas의 이름들 출력
]
];
}
return panel.ToSharedRef();
}
void SWeaponCheckBoxes::DrawProperties(TSharedRef<IPropertyHandle> InPropertyHandle,
IDetailChildrenBuilder* InChildrenBuilder)
{
for (int32 i = 0; i < InternalDatas.Num(); i++)//uint가 아닌 int를 사용해야 한다.
{
if (InternalDatas[i].bChecked == false)//그릴 필요가 없는 경우
continue;
TSharedPtr<IPropertyHandle> handle = InPropertyHandle->GetChildHandle(i);
IDetailPropertyRow& row = InChildrenBuilder->AddProperty(handle.ToSharedRef());//handle를 가지고 기본모양을 추가하여 만들어준다.
row.CustomWidget()
.NameContent()
[
handle->CreatePropertyNameWidget()
]
//줄이거나 늘렸을 때 Min 이하로는 고정. Max 이상으로는 고정.
.ValueContent()
.MinDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
.MaxDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MaxDesiredSlotWidth"))
[
handle->CreatePropertyValueWidget()
];
}
}
void SWeaponCheckBoxes::SetUtilities(TSharedPtr<IPropertyUtilities> InUtilities)
{
Utilities = InUtilities;
}
void SWeaponCheckBoxes::OnCheckStateChanged(ECheckBoxState InState, int32 InIndex)
{
InternalDatas[InIndex].bChecked = !InternalDatas[InIndex].bChecked;//bChecked값을 뒤집어준다.
SWeaponDetailsView::OnRefreshByCheckBoxes();
{
Utilities->ForceRefresh();//새로고침이 된다.
}
SWeaponDetailsView::OffRefreshByCheckBoxes();
}
헤더 추가
- #include "SWeaponDetailsView.h"
함수 정의
- void SWeaponCheckBoxes::DrawProperties(TShaderRef<IPropertyHandle> InPropertyHandle,
IDetailChildrenBuilder* InChildrenBuilder) - void SWeaponCheckBoxes::OnCheckStateChanged(ECheckBoxState InState, int32 InIndex)
uint가 아닌 int를 사용해야 하는 이유는?
- void SWeaponCheckBoxes::DrawProperties(TSharedRef<IPropertyHandle> InPropertyHandle,
IDetailChildrenBuilder* InChildrenBuilder)
{
for (int32 i = 0; i < InternalDatas.Num(); i++) //uint가 아닌 int를 사용해야 한다.
{ ... } }
SWeaponDetailsView
SWeaponDetailsView.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "IDetailCustomization.h"
class WEAPON_API SWeaponDetailsView
: public IDetailCustomization
{
public:
static TSharedRef<IDetailCustomization> MakeInstance();
void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;
public:
//외부에서 CheckBoxes 바꿔주는 역할
static void OnRefreshByCheckBoxes() { bRefreshByCheckBoxes = true; }
static void OffRefreshByCheckBoxes() { bRefreshByCheckBoxes = false; }
private:
static bool bRefreshByCheckBoxes;
};
static 함수 추가: 외부에서 CheckBoxes를 바꿔주는 역할을 수행하는 static 함수.
- static void OnRefreshByCheckBoxes() { bRefreshByCheckBoxes = true; }
- static void OffRefreshByCheckBoxes() { bRefreshByCheckBoxes = false; }
static 변수 추가
- static bool bRefreshByCheckBoxes;
SWeaponDetailsView.cpp
더보기
#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;//static 변수 초기화.
TSharedRef<IDetailCustomization> SWeaponDetailsView::MakeInstance()
{
//자신의 클래스 타입을 만들어서 return해준다.
return MakeShareable(new SWeaponDetailsView());
}
void SWeaponDetailsView::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
UClass* type = UCWeaponAsset::StaticClass();//UClass 타입 하나를 받아온다.
DetailBuilder.HideCategory("CWeaponAsset");//CWeaponAsset 카테고리를 숨겨준다. 현재 작업의 편의를 위해 숨겨주고 추후에 보여주게 만들 예정이다.
//Class Settings
{
//.EditCategory 해당 타입에 해당 카테고리가 있으면 그 카테고리를 return, 없으면 새로 만들어서 return
//ClassSettings는 없으므로 새로 만들어서 return
IDetailCategoryBuilder& category = DetailBuilder.EditCategory("ClassSettings", FText::FromString("Class Settings"));
//CWeaponAsset에서 직렬화된 변수들을 카테고리에 추가한다.
category.AddProperty("AttachmentClass", type);//CWeaponAsset의 AttachmentClass를 카테고리에 추가.
category.AddProperty("EquipmentClass", type);//CWeaponAsset의 EquipmentClass를 카테고리에 추가.
category.AddProperty("DoActionClass", type);//CWeaponAsset의 DoActionClass를 카테고리에 추가.
}
//EquipmentData
{
//.EditCategory 해당 타입에 해당 카테고리가 있으면 그 카테고리를 return, 없으면 새로 만들어서 return
IDetailCategoryBuilder& category = DetailBuilder.EditCategory("EquipmentData", FText::FromString("Equipment Data"));
IDetailPropertyRow& row = category.AddProperty("EquipmentData", type);
if (bRefreshByCheckBoxes == false)//새로고침이 아닐 때
{
TSharedPtr<SWeaponCheckBoxes> checkBoxes = SWeaponEquipmentData::CreateCheckBoxes();//카테고리가 처음에 만들어질 때 checkBox를 만든다.
checkBoxes->AddProperties(row.GetPropertyHandle());//checkBoxes에 실제로 가진 Handle를 추가
}
}
}
static 변수 초기화
- bool SWeaponDetailsView::bRefreshByCheckBoxes = false;
- SWeaponDetailsView에서 선언한 static 변수를 초기화해준다.
함수 정의 수정
- void SWeaponDetailsView::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
- EquipmentData 부분 수정
- if (bRefreshByCheckBoxes == false) {
TSharedPtr<SWeaponCheckBoxes> checkBoxes = SWeaponEquipmentData::CreateCheckBoxes();
checkBoxes->AddProperties(row.GetPropertyHandle());
}
SWeaponEuipmentData
SWeaponEuipmentData.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "IPropertyTypeCustomization.h"
class WEAPON_API SWeaponEquipmentData
: public IPropertyTypeCustomization
{
public:
static TSharedRef<IPropertyTypeCustomization> MakeInstance();
static TSharedPtr<class SWeaponCheckBoxes> CreateCheckBoxes();
void CustomizeHeader(TSharedRef<IPropertyHandle> InPropertyHandle, FDetailWidgetRow& InHeaderRow, IPropertyTypeCustomizationUtils& InCustomizationUtils) override;
void CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) override;
private:
static TSharedPtr<class SWeaponCheckBoxes> CheckBoxes;
};
변동사항 없음
SWeaponEuipmentData.cpp
더보기
#include "SWeaponEquipmentData.h"
#include "IPropertyUtilities.h"
#include "IDetailPropertyRow.h"
#include "IDetailChildrenBuilder.h"
#include "SWeaponCheckBoxes.h"
#include "DetailWidgetRow.h"
TSharedPtr<SWeaponCheckBoxes> SWeaponEquipmentData::CheckBoxes;//초기화
TSharedRef<IPropertyTypeCustomization> SWeaponEquipmentData::MakeInstance()
{
//자신의 클래스 타입을 만들어서 return해준다.
return MakeShareable(new SWeaponEquipmentData());
}
TSharedPtr<SWeaponCheckBoxes> SWeaponEquipmentData::CreateCheckBoxes()
{
if (CheckBoxes.IsValid())
{
CheckBoxes.Reset();
CheckBoxes = nullptr;
}
return CheckBoxes = MakeShareable(new SWeaponCheckBoxes());
}
void SWeaponEquipmentData::CustomizeHeader(TSharedRef<IPropertyHandle> InPropertyHandle, FDetailWidgetRow& InHeaderRow, IPropertyTypeCustomizationUtils& InCustomizationUtils)
{
CheckBoxes->SetUtilities(InCustomizationUtils.GetPropertyUtilities());
InHeaderRow
.NameContent()
[
InPropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
.MinDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
.MaxDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MaxDesiredSlotWidth"))
[
CheckBoxes->Draw()//CheckBoxes를 그려준다(=생성한다).
];
}
void SWeaponEquipmentData::CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils)
{
//uint32 number = 0;
//InPropertyHandle->GetNumChildren(number);
//for(uint32 i = 0; i < number; i++)
//{
// TSharedPtr<IPropertyHandle> handle = InPropertyHandle->GetChildHandle(i);
// IDetailPropertyRow& row = InChildBuilder.AddProperty(handle.ToSharedRef());//handle를 가지고 기본모양을 추가하여 만들어준다.
//
// row.CustomWidget()
// .NameContent()
// [
// handle->CreatePropertyNameWidget()
// ]
// //줄이거나 늘렸을 때 Min 이하로는 고정. Max 이상으로는 고정.
// .ValueContent()
// .MinDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
// .MaxDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MaxDesiredSlotWidth"))
// [
// handle->CreatePropertyValueWidget()
// ];
//}
CheckBoxes->DrawProperties(InPropertyHandle, &InChildBuilder);
}
함수 정의 수정
- void SWeaponEquipmentData::CustomizeHeader(TSharedRef<IPropertyHandle> InPropertyHandle, FDetailWidgetRow& InHeaderRow, IPropertyTypeCustomizationUtils& InCustomizationUtils)
- 체크박스를 세팅하는 부분 추가
- CheckBoxes->SetUtilities(InCustomizationUtils.GetPropertyUtilities());
- 체크박스를 세팅하는 부분 추가
- void SWeaponEquipmentData::CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils)
- 체크박스를 그리는 부분 추가
- CheckBoxes->DrawProperties(InPropertyHandle, &InChildBuilder);
- 체크박스를 그리는 부분 추가
실행화면
'⭐ Unreal Engine > UE Plugin - Slate UI' 카테고리의 다른 글
[UE] Weapon Plugin 9: DoAction Data 연동하기 II (0) | 2023.06.14 |
---|---|
[UE] Weapon Plugin 8: DoAction Data 연동하기 (0) | 2023.06.13 |
[UE] Weapon Plugin 6: 체크박스 만들기 (0) | 2023.06.08 |
[UE] Weapon Plugin 5: 창 내부 Header, Child 구분하기 (0) | 2023.06.07 |
[UE] Weapon Plugin 4: 창 내에 데이터 넣어주기, 검색 기능 넣기 (0) | 2023.06.01 |
댓글
이 글 공유하기
다른 글
-
[UE] Weapon Plugin 9: DoAction Data 연동하기 II
[UE] Weapon Plugin 9: DoAction Data 연동하기 II
2023.06.14 -
[UE] Weapon Plugin 8: DoAction Data 연동하기
[UE] Weapon Plugin 8: DoAction Data 연동하기
2023.06.13 -
[UE] Weapon Plugin 6: 체크박스 만들기
[UE] Weapon Plugin 6: 체크박스 만들기
2023.06.08 -
[UE] Weapon Plugin 5: 창 내부 Header, Child 구분하기
[UE] Weapon Plugin 5: 창 내부 Header, Child 구분하기
2023.06.07