[UE] Weapon Plugin 9: DoAction Data 연동하기 II
목차
Plugins |
||||
Weapon |
||||
Resource |
||||
Icon128.png weapon_thumbnail_icon.png |
||||
Source |
||||
Weapon | ||||
SWeaponCheckBoxes.h .cpp SWeaponDetailsView.h .cpp SWeaponDoActionData.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 |
||||
Source | ||
Characters | ||
CAnimInstance.h .cpp CEnemy.h .cpp CPlayer.h .cpp ICharacter.h .cpp |
||
Components | ||
CMontagesComponent.h .cpp CMovementComponent.h .cpp CStateComponent.h .cpp CWeaponComponent.h .cpp |
||
Notifies | ||
CAnimNotifyState_BeginAction.h .cpp CAnimNotify_CameraShake.h .cpp CAnimNotifyState_EndAction.h .cpp CAnimNotify_EndState.h .cpp CAnimNotifyState_Collision.h .cpp CAnimNotifyState_Combo.h .cpp CAnimNotifyState_Equip.h .cpp |
||
Utilities | ||
CHelper.h CLog.h .cpp |
||
Weapons | ||
CDoAction_Combo.h .cpp CAttachment.h .cpp CDoAction.h .cpp CEquipment.h .cpp CWeaponAsset.h .cpp CWeaponStructures.h .cpp |
||
Global.h CGameMode.h .cpp .Build.cs |
||
.uproject | ||
DoAction Data 연동하기 II
'ProjectName'.Build.cs
'ProjectName'.Build.cs
더보기
using UnrealBuildTool;
public class U2212_06 : ModuleRules
{
public U2212_06(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.Add(ModuleDirectory);
PublicDependencyModuleNames.Add("Core");
PrivateDependencyModuleNames.Add("CoreUObject");
PrivateDependencyModuleNames.Add("Engine");
PrivateDependencyModuleNames.Add("InputCore");
PublicDependencyModuleNames.Add("Niagara");
}
}
Dependency Module 접근 범위 변경
- 게임 프로젝트 뿐만 아니라 Plugin쪽에서도 Niagara 접근을 할 수 있도록 private을 public으로 변경한다.
- 변경 전: PrivateDependencyModuleNames.Add("Niagara");
- 변경 후: PublicDependencyModuleNames.Add("Niagara");
SWeaponDoActionData
SWeaponDoActionData.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "IPropertyTypeCustomization.h"
class WEAPON_API SWeaponDoActionData
: public IPropertyTypeCustomization
{
public:
static TSharedRef<IPropertyTypeCustomization> MakeInstance();
static TSharedPtr<class SWeaponCheckBoxes> AddCheckBoxes();
static void EmptyCheckBoxes();//한번에 비워주는 역할의 함수
void CustomizeHeader(TSharedRef<IPropertyHandle> InPropertyHandle, FDetailWidgetRow& InHeaderRow, IPropertyTypeCustomizationUtils& InCustomizationUtils) override;
void CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) override;
private:
static TArray<TSharedPtr<class SWeaponCheckBoxes>> CheckBoxes;
};
변동사항 없음.
SWeaponDoActionData.cpp
더보기
#include "SWeaponDoActionData.h"
#include "WeaponStyle.h"
#include "IPropertyUtilities.h"
#include "IDetailPropertyRow.h"
#include "IDetailChildrenBuilder.h"
#include "SWeaponCheckBoxes.h"
#include "DetailWidgetRow.h"
TArray<TSharedPtr<SWeaponCheckBoxes>> SWeaponDoActionData::CheckBoxes;
TSharedRef<IPropertyTypeCustomization> SWeaponDoActionData::MakeInstance()
{
//자신의 클래스 타입을 만들어서 return해준다.
return MakeShareable(new SWeaponDoActionData());
}
TSharedPtr<SWeaponCheckBoxes> SWeaponDoActionData::AddCheckBoxes()
{
TSharedPtr<SWeaponCheckBoxes> checkBoxes = MakeShareable(new SWeaponCheckBoxes());
int32 index = CheckBoxes.Add(checkBoxes);
return CheckBoxes[index];
}
void SWeaponDoActionData::EmptyCheckBoxes()
{
for (TSharedPtr<SWeaponCheckBoxes> ptr : CheckBoxes)
{
if (ptr.IsValid())
ptr.Reset();
}
CheckBoxes.Empty();
}
void SWeaponDoActionData::CustomizeHeader(TSharedRef<IPropertyHandle> InPropertyHandle, FDetailWidgetRow& InHeaderRow,
IPropertyTypeCustomizationUtils& InCustomizationUtils)
{
if (SWeaponCheckBoxes::CanDraw(InPropertyHandle, CheckBoxes.Num()) == false)
return;//CanDraw가 false면 그리지 않고 리턴.
int32 index = InPropertyHandle->GetIndexInArray();//GetIndexInArray()는 Array 안에서의 번호를 리턴.
CheckBoxes[index]->SetUtilities(InCustomizationUtils.GetPropertyUtilities());//Header,Children,Header,Children..순서로 콜된다.
FString name = InPropertyHandle->GetPropertyDisplayName().ToString();//0,1,2..표시하는 name
name = "DoAction Data - " + name;
InHeaderRow
.NameContent()
[
SNew(SBorder)//SBorder는 한 줄을 출력할 때 사용.
.BorderImage(FWeaponStyle::Get()->Array_Image.Get())
[
InPropertyHandle->CreatePropertyNameWidget(FText::FromString(name))
]
]
.ValueContent()
.MinDesiredWidth(FWeaponStyle::Get()->DesiredWidth.X)
.MaxDesiredWidth(FWeaponStyle::Get()->DesiredWidth.Y)
[
CheckBoxes[index]->Draw(true)//CheckBoxes를 그려준다(=생성한다).bBackground에 true값을 넣어주어 alpha값이 0.1f인 흰색 이미지가 겹쳐저 해당 줄이 띠처럼 보이게 만들어준다.
];
}
void SWeaponDoActionData::CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle,
IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils)
{
if (SWeaponCheckBoxes::CanDraw(InPropertyHandle, CheckBoxes.Num()) == false)
return;//CanDraw가 false면 그리지 않고 리턴.
int32 index = InPropertyHandle->GetIndexInArray();//GetIndexInArray()는 Array 안에서의 번호를 리턴.
CheckBoxes[index]->DrawProperties(InPropertyHandle, &InChildBuilder);
}
헤더 추가
- #include "WeaponStyle.h"
함수 정의
- void SWeaponDoActionData::CustomizeHeader(TSharedRef<IPropertyHandle> InPropertyHandle, FDetailWidgetRow& InHeaderRow, IPropertyTypeCustomizationUtils& InCustomizationUtils)
- int32 index = InPropertyHandle->GetIndexInArray();
- GetIndexInArray()는 Array 안에서의 번호를 리턴.
- CheckBoxes[index]->SetUtilities(InCustomizationUtils.GetPropertyUtilities());
- //Header, Children, Header, Children...순서로 콜된다.
- int32 index = InPropertyHandle->GetIndexInArray();
SWeaponEquipmentData - 창의 너비와 폭의 최소 최대값 변경
마이너한 변경사항.
SWeaponEquipmentData.h
변동사항 없음.
SWeaponEquipmentData.cpp
더보기
#include "SWeaponEquipmentData.h"
#include "WeaponStyle.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(FWeaponStyle::Get()->DesiredWidth.X)
.MaxDesiredWidth(FWeaponStyle::Get()->DesiredWidth.Y)
[
CheckBoxes->Draw()//CheckBoxes를 그려준다(=생성한다).
];
}
void SWeaponEquipmentData::CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils)
{
CheckBoxes->DrawProperties(InPropertyHandle, &InChildBuilder);
}
헤더 추가
- #include "WeaponStyle.h"
함수 내용수정
- 창의 너비와 폭의 최소, 최대값을 설정. FWeaponStyle 내의 변수 DesiredWidth를 사용.
- 변경 전: .MinDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
.MaxDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MaxDesiredSlotWidth"))
- 변경 후: .MinDesiredWidth(FWeaponStyle::Get()->DesiredWidth.X)
.MaxDesiredWidth(FWeaponStyle::Get()->DesiredWidth.Y)
- 변경 전: .MinDesiredWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth"))
WeaponStyle
WeaponStyle.h
더보기
#pragma once
#include "CoreMinimal.h"
class WEAPON_API FWeaponStyle
{
public:
static TSharedRef<FWeaponStyle> Get();
static void Shutdown();
private:
static TSharedPtr<FWeaponStyle> Instance;
public:
FWeaponStyle();
~FWeaponStyle();
private:
void RegisterIcon(const FString& InName, const FString& InPath, const FVector2D& InIconSize, FSlateIcon& OutSlateIcon);
private:
static const FName StyleSetName;
private:
TSharedPtr<class FSlateStyleSet> StyleSet;
public:
FSlateIcon ToolBar_Icon;
TSharedPtr<struct FSlateImageBrush> Array_Image;
public:
const FVector2D DesiredWidth = FVector2D(250, 1000);
};
변수 추가
- TSharedPtr<struct FSlateImageBrush> Array_Image;
WeaponStyle.cpp
더보기
#include "WeaponStyle.h"
#include "Styling/SlateStyle.h"
#include "Styling/SlateStyleRegistry.h"
const FName FWeaponStyle::StyleSetName = "WeaponStyle";
TSharedPtr<FWeaponStyle> FWeaponStyle::Instance = nullptr;
TSharedRef<FWeaponStyle> FWeaponStyle::Get()
{
if (Instance == nullptr)
Instance = MakeShareable(new FWeaponStyle());
return Instance.ToSharedRef();
}
void FWeaponStyle::Shutdown()
{
if (Instance.IsValid())
Instance.Reset();
}
FWeaponStyle::FWeaponStyle()
{
StyleSet = MakeShareable(new FSlateStyleSet(StyleSetName));
FString path = "";
path = FPaths::ProjectPluginsDir() / "Weapon" / "Resources";
RegisterIcon("ToolBar_Icon", path / "weapon_thumnail_icon.png", FVector2D(40, 40), ToolBar_Icon);
FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get());
path = FPaths::EngineConfigDir() / "Editor" / "Slate" / "Common/Selection.png";//Engine이 설치된 Config 경로에 있는 해당 png 이미지의 파일 경로
Array_Image = MakeShareable(new FSlateImageBrush(path, FVector2D(8, 8), FLinearColor(1, 1, 1, 0.1f)));//path 경로의 이미지를 (8, 8)사이즈로 해당 색과 alpha값으로 생성한다.
}
FWeaponStyle::~FWeaponStyle()
{
if (Array_Image.IsValid())
Array_Image.Reset();
if (StyleSet.IsValid() == false) return;
FSlateStyleRegistry::UnRegisterSlateStyle(StyleSetName);
StyleSet.Reset();
}
void FWeaponStyle::RegisterIcon(const FString& InName, const FString& InPath, const FVector2D& InIconSize, FSlateIcon& OutSlateIcon)
{
FSlateImageBrush* brush = new FSlateImageBrush(InPath, InIconSize);
FString name = StyleSetName.ToString() + "." + InName;
StyleSet->Set(FName(name), brush);
OutSlateIcon = FSlateIcon(FName(StyleSetName), FName(name));
}
함수 내용 추가
- FWeaponStyle::FWeaponStyle()
- path = FPaths::EngineConfigDir() / "Editor" / "Slate" / "Common/Selection.png";
- Engine이 설치된 Config 경로를 적어준다.
- 아래의 이미지가 경로에 있는 이미지.
- Array_Image = MakeShareable(new FSlateImageBrush(path, FVector2D(8, 8), FLinearColor(1, 1, 1, 0.1f)));
- 이미지를 생성하여 넣어준다.
- path는 가져오는 이미지 경로.
- Opacity를 떨어뜨리기 위해 (1, 1, 1, 0.1f)로 alpha값을 10%로 설정해준다.
- path = FPaths::EngineConfigDir() / "Editor" / "Slate" / "Common/Selection.png";
※ 참고) Engine\UE4.26\Engine\Content\Editor\Slate\Common 내의 아이콘 이미지 파일들
SWeaponCheckBoxes
SWeaponCheckBoxes.h
더보기
#pragma once
#include "CoreMinimal.h"
class WEAPON_API SWeaponCheckBoxes
: public TSharedFromThis<SWeaponCheckBoxes> // 직접적으로 상속받으면 주소가 일치하게된다.
{
public:
//IPropertyHandle는 하나의 Property에 대한 식별자
void AddProperties(TSharedPtr<IPropertyHandle> InHandle);
//SNew에 최상의 부모가 SWidget이 된다. 레퍼런스를 사용하기 때문에 동일하게 쓰기위함
TSharedRef<SWidget> Draw(bool bBackground = false);//디폴트 파라미터로 기본값을 false로 설정.
//해당 Properties를 그릴지 말지 결정
void DrawProperties(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder* InChildrenBuilder);
//객체를 외부에서 받기위해,
void SetUtilities(TSharedPtr<class IPropertyUtilities> InUtilities);
private:
//체크가 완료되었는지
void OnCheckStateChanged(ECheckBoxState InState, int32 InIndex);
public:
static bool CanDraw(TSharedPtr<IPropertyHandle> InHandle, int InCount);//사용자가 체크한 InHandle이 들어와서 배열이 개수와 일치하는지 판단. 배열 범위를 벗어나면 그리지 않도록 false를 리턴.
public:
//InIndex에는 Property 번호가 InValue에는 값.
void CheckDefaultObject(int32 InIndex, UObject* InValue);
void CheckDefaultValue(int32 InIndex, float InValue);
void CheckDefaultValue(int32 InIndex, bool InValue);
void CheckDefaultValue(int32 InIndex, const FVector& InValue);
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;//멤버 변수
};
변수 추가
- TSharedRef<SWidget> Draw(bool bBackground = false);
- 디폴트 파라미터로 기본값을 false로 설정.
static 함수 추가
- static bool CanDraw(TSharedPtr<IPropertyHandle> InHandle, int InCount);
- 사용자가 체크한 InHandle이 들어와서 배열이 개수와 일치하는지 판단. 배열 범위를 벗어나면 그리지 않도록 false를 리턴.
SWeaponCheckBoxes.cpp
더보기
#include "SWeaponCheckBoxes.h"
#include "WeaponStyle.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);//SNew와 다르게 변수를 선언해 놓는 SAssignNew
panel->SetMinDesiredSlotWidth(150);//최소폭 150으로 설정.
for (int32 i = 0; i < InternalDatas.Num(); i++)
{
panel->AddSlot(i, 0)//한줄만 사용, 여러줄사용하려면 ex) i % 5
[
SNew(SCheckBox)//체크박스는 컨텐츠 영역을 가지고 있다.
.IsChecked(InternalDatas[i].bChecked)//체크 여부 출력, 0과 1로만 판단
.OnCheckStateChanged(this, &SWeaponCheckBoxes::OnCheckStateChanged, i)//체크 했는지 판단
[
SNew(STextBlock)
.Text(FText::FromString(InternalDatas[i].Name))//InternalDatas의 이름들 출력
]
];
}
if(bBackground == false)
return panel.ToSharedRef();//추가를 하게되면, 추가된 그자체를 return
TSharedPtr<SBorder> border = SNew(SBorder)//한 줄 생성.
.BorderImage(FWeaponStyle::Get()->Array_Image.Get())
[
panel.ToSharedRef()//panel를 컨텐츠 영역으로 넣어준다.
];
return border.ToSharedRef();//border를 리턴.
}
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()
]
//줄이거나 늘렸을 때 Min 이하로는 고정. Max 이상으로는 고정.
.ValueContent()
.MinDesiredWidth(FWeaponStyle::Get()->DesiredWidth.X)
.MaxDesiredWidth(FWeaponStyle::Get()->DesiredWidth.Y)
[
handle->CreatePropertyValueWidget()
];
}
}
void SWeaponCheckBoxes::SetUtilities(TSharedPtr<IPropertyUtilities> InUtilities)
{
//외부 객체 받아오기
Utilities = InUtilities;
}
void SWeaponCheckBoxes::OnCheckStateChanged(ECheckBoxState InState, int32 InIndex)
{
//상태를 바뀌는걸 확인했기때문에, 값을 뒤집어 줘서 다시 안그려지게 만들어준다.
InternalDatas[InIndex].bChecked = !InternalDatas[InIndex].bChecked;
SWeaponDetailsView::OnRefreshByCheckBoxes();
{
// ForceRefresh이 콜이되면 새로고침이 되면서 다시 그려진다.
Utilities->ForceRefresh();
}
SWeaponDetailsView::OffRefreshByCheckBoxes();
}
bool SWeaponCheckBoxes::CanDraw(TSharedPtr<IPropertyHandle> InHandle, int InCount)
{
bool bCheck = true;
bCheck &= InCount > 0;//배열의 개수 InCount가 0보다 큰지
int32 index = InHandle->GetIndexInArray();//InHandle에서 배열 인덱스번호를 가져온다.
bCheck &= index >= 0;
bCheck &= index < InCount;//인덱스가 InCount 배열의 개수보다 작은지//크면 범위를 벗어나서 그릴 수 없다.
return bCheck;
}
void SWeaponCheckBoxes::CheckDefaultObject(int32 InIndex, UObject* InValue)
{
UObject* val = nullptr;//기본값
InternalDatas[InIndex].Handle->GetValue(val);//해당 Property에 선택한 값
if (!!val && InValue != val)//nullptr이거나 선택한 값이랑 기본값이 다르다면
InternalDatas[InIndex].bChecked = true;
}
void SWeaponCheckBoxes::CheckDefaultValue(int32 InIndex, float InValue)
{
float val = 0.0f;//기본값
InternalDatas[InIndex].Handle->GetValue(val);//해당 Property에 선택한 값
if (InValue != val)//선택한 값이랑 기본값이 다르다면
InternalDatas[InIndex].bChecked = true;
}
void SWeaponCheckBoxes::CheckDefaultValue(int32 InIndex, bool InValue)
{
bool val = false;//기본값
InternalDatas[InIndex].Handle->GetValue(val);//해당 Property에 선택한 값
if (InValue != val)//선택한 값이랑 기본값이 다르다면
InternalDatas[InIndex].bChecked = true;
}
void SWeaponCheckBoxes::CheckDefaultValue(int32 InIndex, const FVector& InValue)
{
FVector val = FVector::ZeroVector;//기본값
InternalDatas[InIndex].Handle->GetValue(val);//해당 Property에 선택한 값
if (InValue != val)//선택한 값이랑 기본값이 다르다면
InternalDatas[InIndex].bChecked = true;
}
함수 정의
- TSharedRef<SWidget> SWeaponCheckBoxes::Draw(bool bBackground)
- bool SWeaponCheckBoxes::CanDraw(TSharedPtr<IPropertyHandle> InHandle, int InCount)
실행화면
Source 파일 수정
WeaponAsset
WeaponAsset.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "Weapons/CWeaponStructures.h"
#include "CWeaponAsset.generated.h"
UCLASS()
class U2212_06_API UCWeaponAsset : public UDataAsset
{
GENERATED_BODY()
private:
UPROPERTY(EditAnywhere)
TSubclassOf<class ACAttachment> AttachmentClass;
UPROPERTY(EditAnywhere)
FEquipmentData EquipmentData;
UPROPERTY(EditAnywhere)
TSubclassOf<class UCEquipment> EquipmentClass;
UPROPERTY(EditAnywhere)
TSubclassOf<class UCDoAction> DoActionClass;
UPROPERTY(EditAnywhere)
TArray<FDoActionData> DoActionDatas; //CWeaopnStructure내의 FDoActionData
UPROPERTY(EditAnywhere)
TArray<FHitData> HitDatas; //CWeaopnStructure내의 FHitData
public:
FORCEINLINE class ACAttachment* GetAttachment() { return Attachment; }//외부에 생성된 것을 리턴해줌.
FORCEINLINE class UCEquipment* GetEquipment() { return Equipment; }//외부에 생성된 것을 리턴해줌.
FORCEINLINE class UCDoAction* GetDoAction() { return DoAction; }//외부에 생성된 것을 리턴해줌.
public:
UCWeaponAsset();
void BeginPlay(class ACharacter* InOwner);
private:
//UPROPERTY를 붙여 가비지 콜렉터가 제거하기 전까지 물고 있게 만든다.
//UWeaponAsset은 UObject로부터 상속받아 Actor의 생성주기에 영향을 받지 않아 가비지 콜렉터에 영향을 받는다.
UPROPERTY()
class ACAttachment* Attachment;
UPROPERTY()
class UCEquipment* Equipment;
UPROPERTY()
class UCDoAction* DoAction;
#if WITH_EDITOR //Editor 내에서만 수행
void PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent) override;
#endif
};
함수 추가
- void PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent) override;
- UObject의 함수 오버라이드
※참고) Object.h의 void PostEditChangeProperty() 함수
- property가 밖에서 바뀐 이후에 콜 된다.
WeaponAsset.cpp
더보기
#include "Weapons/CWeaponAsset.h"
#include "Global.h"
#include "CAttachment.h"
#include "CEquipment.h"
#include "CDoAction.h"
#include "GameFramework/Character.h"
UCWeaponAsset::UCWeaponAsset()
{
AttachmentClass = ACAttachment::StaticClass();//기본값
EquipmentClass = UCEquipment::StaticClass();//기본값
DoActionClass = UCDoAction::StaticClass();//기본값
}
void UCWeaponAsset::BeginPlay(ACharacter* InOwner)
{
if (!!AttachmentClass)//AttachmentClass가 선택되어 있다면
{
FActorSpawnParameters params;
params.Owner = InOwner;
Attachment = InOwner->GetWorld()->SpawnActor<ACAttachment>(AttachmentClass, params);
}
if (!!EquipmentClass)//EquipmentClass가 선택되어 있다면
{
Equipment = NewObject<UCEquipment>(this, EquipmentClass);
Equipment->BeginPlay(InOwner, EquipmentData);
if (!!Attachment)//Attachment가 있다면
{
Equipment->OnEquipmentBeginEquip.AddDynamic(Attachment, &ACAttachment::OnBeginEquip);
Equipment->OnEquipmentUnequip.AddDynamic(Attachment, &ACAttachment::OnUnequip);
}
}
if(!!DoActionClass)
{
DoAction = NewObject<UCDoAction>(this, DoActionClass);
DoAction->BeginPlay(Attachment, Equipment, InOwner, DoActionDatas, HitDatas);
if (!!Attachment)
{
Attachment->OnAttachmentBeginCollision.AddDynamic(DoAction, &UCDoAction::OnAttachmentBeginCollision);
Attachment->OnAttachmentEndCollision.AddDynamic(DoAction, &UCDoAction::OnAttachmentEndCollision);
Attachment->OnAttachmentBeginOverlap.AddDynamic(DoAction, &UCDoAction::OnAttachmentBeginOverlap);
Attachment->OnAttachmentEndOverlap.AddDynamic(DoAction, &UCDoAction::OnAttachmentEndOverlap);
}
}
}
#if WITH_EDITOR //Editor 내에서만 수행
void UCWeaponAsset::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
{
Super::PostEditChangeChainProperty(PropertyChangedEvent);
CLog::Log(PropertyChangedEvent.GetPropertyName().ToString());//어떤 변수가 바뀌었는지
CLog::Log((int32)PropertyChangedEvent.ChangeType);//어떤 명령에 의해 바뀌었는지
}
#endif
함수 정의
- void UCWeaponAsset::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
__VTableCtorCaller
Editor에서 Hot Reloading이 일어나면 __VTableCtorCaller이 콜 된다.
UObject에 있는 함수다.
CDO
Hot Reload는 CDO를 다시 읽어주는 역할을 수행한다.
'⭐ Unreal Engine > UE Plugin - Slate UI' 카테고리의 다른 글
[UE] Weapon Plugin 10: 삽입,삭제,복제 기능 추가, HitData 카테고리 추가 (0) | 2023.06.15 |
---|---|
[UE] Weapon Plugin 8: DoAction Data 연동하기 (0) | 2023.06.13 |
[UE] Weapon Plugin 7: Check Box와 데이터 연결하기 (0) | 2023.06.12 |
[UE] Weapon Plugin 6: 체크박스 만들기 (0) | 2023.06.08 |
[UE] Weapon Plugin 5: 창 내부 Header, Child 구분하기 (0) | 2023.06.07 |
댓글
이 글 공유하기
다른 글
-
[UE] Weapon Plugin 10: 삽입,삭제,복제 기능 추가, HitData 카테고리 추가
[UE] Weapon Plugin 10: 삽입,삭제,복제 기능 추가, HitData 카테고리 추가
2023.06.15 -
[UE] Weapon Plugin 8: DoAction Data 연동하기
[UE] Weapon Plugin 8: DoAction Data 연동하기
2023.06.13 -
[UE] Weapon Plugin 7: Check Box와 데이터 연결하기
[UE] Weapon Plugin 7: Check Box와 데이터 연결하기
2023.06.12 -
[UE] Weapon Plugin 6: 체크박스 만들기
[UE] Weapon Plugin 6: 체크박스 만들기
2023.06.08