[UE] Weapon Plugin 8: DoAction Data 연동하기
목차
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 |
||||
DoAction Data 연동하기
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);
//해당 Properties를 그릴지 말지 결정
void DrawProperties(TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder* InChildrenBuilder);
//객체를 외부에서 받기위해,
void SetUtilities(TSharedPtr<class IPropertyUtilities> InUtilities);
private:
//체크가 완료되었는지
void OnCheckStateChanged(ECheckBoxState InState, int32 InIndex);
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;//멤버 변수
};
함수 추가
- 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);
- InIndex에는 Property 번호가 InValue에는 값이 들어간다.
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의 이름들 출력
]
];
}
return panel.ToSharedRef();//추가를 하게되면, 추가된 그자체를 return
}
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();
}
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;
}
헤더 추가
- #include "WeaponStyle.h"
함수 내용 추가
- void SWeaponCheckBoxes::DrawProperties()
- WeaponStyle.h에서 선언한 const FVector2D DesiredWidth = FVector2D(250, 1000); 변수 값을 가져다가 사용.
- 해당 변수는 창의 너비와 높이의 최소, 최대값을 설정할 때 사용한다.
- 수정 코드
- .MinDesiredWidth(FWeaponStyle::Get()->DesiredWidth.X)
- .MaxDesiredWidth(FWeaponStyle::Get()->DesiredWidth.Y)
함수 정의
- void SWeaponCheckBoxes::CheckDefaultObject(int32 InIndex, UObject* InValue)
- void SWeaponCheckBoxes::CheckDefaultValue(int32 InIndex, float InValue)
- void SWeaponCheckBoxes::CheckDefaultValue(int32 InIndex, bool InValue)
- void SWeaponCheckBoxes::CheckDefaultValue(int32 InIndex, const FVector& InValue)
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;
public:
const FVector2D DesiredWidth = FVector2D(250, 1000);
};
변수 추가
- const FVector2D DesiredWidth = FVector2D(250, 1000);
- SWeaponCheckBoxes.cpp의 void SWeaponCheckBoxes::DrawProperties()에서 창의 너비와 높이 최소 최대값으로 사용한다.
SWeaponDoActionData 생성
새 C++ 클래스 - 없음 - 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 "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)
{
GLog->Log("CustomizeHeader");
}
void SWeaponDoActionData::CustomizeChildren(TSharedRef<IPropertyHandle> InPropertyHandle,
IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils)
{
GLog->Log("CustomizeChildren");
}
SWeaponDetailsView
SWeaponDetailsView.h
변동사항 없음
SWeaponDetailsView.cpp
더보기
#include "SWeaponDetailsView.h"
#include "SWeaponCheckBoxes.h"
#include "SWeaponEquipmentData.h"
#include "SWeaponDoActionData.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "IDetailPropertyRow.h"
#include "Weapons/CWeaponAsset.h"
#include "Animation/AnimMontage.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를 추가
FEquipmentData data;//변수 선언한다. FEquipmentData의 변수 data 기본값을 아래에서 사용한다.
int32 index = 0;
checkBoxes->CheckDefaultObject(index++, data.Montage);
checkBoxes->CheckDefaultValue(index++, data.PlayRate);
checkBoxes->CheckDefaultValue(index++, data.bCanMove);
checkBoxes->CheckDefaultValue(index++, data.bUseControlRotation);
}
}
//DoActionData
{
//.EditCategory 해당 타입에 해당 카테고리가 있으면 그 카테고리를 return, 없으면 새로 만들어서 return
IDetailCategoryBuilder& category = DetailBuilder.EditCategory("DoActionData", FText::FromString("DoAction Data"));
IDetailPropertyRow& row = category.AddProperty("DoActionDatas", type);//변수 추가 //WeaponAsset에 있는 데이터명과 일치시킨다. DoActionDatas
if (bRefreshByCheckBoxes == false)
{
uint32 count = 0;
row.GetPropertyHandle()->GetNumChildren(count);
SWeaponDoActionData::EmptyCheckBoxes();//비워놓고 시작.
FDoActionData data;//기본값 사용할 변수
for (uint32 i =0; i < count; i++)
{
TSharedPtr<IPropertyHandle> handle = row.GetPropertyHandle()->GetChildHandle(i);//헤더의 handle
TSharedPtr<SWeaponCheckBoxes> checkBoxes = SWeaponDoActionData::AddCheckBoxes();//카테고리가 처음에 만들어질 때 checkBox를 만든다.
checkBoxes->AddProperties(handle);
}
}//if(bRefreshByCheckBoxes)
}
}
헤더 추가
- #include "SWeaponDoActionData.h"
- #include "Animation/AnimMontage.h"
void SWeaponDetailsView::CustomizeDetails()에 Equipment Data 추가, DoActionData 추가
- Equipment Data
- FEquipmentData data;
- int32 index = 0;
- checkBoxes->CheckDefaultObject(index++, data.Montage);
- checkBoxes->CheckDefaultValue(index++, data.PlayRate);
- checkBoxes->CheckDefaultValue(index++, data.bCanMove);
- checkBoxes->CheckDefaultValue(index++, data.bUseControlRotation);
- DoAction Data
- IDetailCategoryBuilder& category = DetailBuilder.EditCategory("DoActionData", FText::FromString("DoAction Data"));
- IDetailPropertyRow& row = category.AddProperty("DoActionDatas", type);
WeaponAssetEditor
WeaponAssetEditor.cpp
더보기
#include "WeaponAssetEditor.h"
#include "SWeaponLeftArea.h"
#include "SWeaponDetailsView.h"
#include "SWeaponEquipmentData.h"
#include "SWeaponDoActionData.h"
#include "Weapons/CWeaponAsset.h"
//설정한 이름들
const FName FWeaponAssetEditor::EditorName = "WeaponAssetEditor";
const FName FWeaponAssetEditor::LeftAreaTabId = "LeftArea";
const FName FWeaponAssetEditor::DetailTabId = "Details";
TSharedPtr<FWeaponAssetEditor> FWeaponAssetEditor::Instance = nullptr;//헤더에서 선언한 static 외부 초기화.
void FWeaponAssetEditor::OpenWindow(FString InAssetName)
{
//아래의 코드 대신에 Shutdown()을 사용하면 안 된다! Shutdown()은 다른 곳에서도 콜이 되기 때문에 아래의 코드 대신에 사용하면 문제가 된다.
if (Instance.IsValid()) //창이 만들어졌다면
{
Instance->CloseWindow();//창을 닫는다.
Instance.Reset();
Instance = nullptr;
}
Instance = MakeShareable(new FWeaponAssetEditor());
Instance->Open(InAssetName);
}
void FWeaponAssetEditor::Shutdown()
{
if (Instance.IsValid())
{
Instance->CloseWindow();
Instance.Reset();
Instance = nullptr;
}
}
void FWeaponAssetEditor::Open(FString InAssetName)
{
LeftArea = SNew(SWeaponLeftArea)//SWeaponLeftArea에서 받은 자료형을 생성하여 넣어준다.
.OnSelectedItem(this, &FWeaponAssetEditor::OnListViewSelectedItem);//LeftArea에서 선택한 데이터
FPropertyEditorModule& prop = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
//DetailsView
{
FDetailsViewArgs args(false, false, true, FDetailsViewArgs::HideNameArea);//기본값 설정. ActorsUserNameArea, ObjectsUserNameArea, HideNameArea
args.ViewIdentifier = "WeaponAssetEditorDetailsView";//식별자 설정. 게임 Editor쪽에서 DetailView 접근시 이 식별자로 찾을 수 있다.
DetailsView = prop.CreateDetailView(args);//Detail 창 띄우기.
FOnGetDetailCustomizationInstance detailView;
detailView.BindStatic(&SWeaponDetailsView::MakeInstance);//Static은 객체가 필요없다. 그래서 함수 주소로 바로 연결한다.
DetailsView->SetGenericLayoutDetailsDelegate(detailView);//Delegate를 연결해준다.
}
//EquipmentData
{
FOnGetPropertyTypeCustomizationInstance instance;
instance.BindStatic(&SWeaponEquipmentData::MakeInstance);
prop.RegisterCustomPropertyTypeLayout("EquipmentData", instance);//instance를 delegate 등록
}
//DoActionData
{
FOnGetPropertyTypeCustomizationInstance instance;
instance.BindStatic(&SWeaponDoActionData::MakeInstance);
prop.RegisterCustomPropertyTypeLayout("DoActionData", instance);//instance를 delegate 등록
}
//Layout 설정
TSharedRef<FTabManager::FLayout> layout = FTabManager::NewLayout("WeaponAssetEditor_Layout")
->AddArea //전체화면의 메인 영역
(
FTabManager::NewPrimaryArea()->SetOrientation(Orient_Vertical)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.1f)//10%만 사용하겠다.
->AddTab(GetToolbarTabId(), ETabState::OpenedTab)
)
->Split
(
FTabManager::NewSplitter()->SetOrientation(Orient_Horizontal)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.175f)//왼쪽 17.5% 사용
->AddTab(LeftAreaTabId, ETabState::OpenedTab)//ListViewTabId
->SetHideTabWell(true)
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.725f)//오른쪽 72.5% 사용
->AddTab(DetailTabId, ETabState::OpenedTab)//DetailTabId
->SetHideTabWell(true)
)
)
);
UCWeaponAsset* asset = nullptr;
asset = LeftArea->GetFirstDataPtr()->Asset;//LeftArea의 맨 위 첫번째 데이터 선택
FAssetEditorToolkit::InitAssetEditor(EToolkitMode::Standalone, TSharedPtr<IToolkitHost>(), EditorName, layout, true, true, asset);
//DetailsView->SetObject(asset);//어느 DetailView든 asset객체가 세팅된다. 창은 여러개지만 실제 관리는 내부적으로 하나로 관리한다. 그래서 창이 종료될 때 DetailsView가 해제 안 되어 있으면 터진다.
LeftArea->SelectDataPtr(asset);
}
bool FWeaponAssetEditor::OnRequestClose()
{
if (!!DetailsView)
{
//AssetEditorSubsystem안에(=DetailView 안에)
//GetEditingObject()가 등록되어 있었다면 해제하고 Editor에 알린다.
if (!!GEditor && !!GEditor->GetEditorSubsystem<UAssetEditorSubsystem>())
GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->NotifyAssetClosed(GetEditingObject(), this);
//해당 모듈이 읽힌적이 있다면 해제.
if (FModuleManager::Get().IsModuleLoaded("PropertyEditor"))
{
FPropertyEditorModule& prop = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");//해당모듈을 가져온다.
prop.UnregisterCustomClassLayout("EquipmentData");//등록 해제
prop.UnregisterCustomClassLayout("DoActionData");//등록 해제
}
}
if (LeftArea.IsValid())
LeftArea.Reset();
if (DetailsView.IsValid())
DetailsView.Reset();
return true;
//false 리턴인 경우 창이 닫힐 수 없다는 것을 의미한다.
}
void FWeaponAssetEditor::RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
{
FAssetEditorToolkit::RegisterTabSpawners(InTabManager);
FOnSpawnTab tab;
tab.BindSP(this, &FWeaponAssetEditor::Spawn_LeftAreaTab);
TabManager->RegisterTabSpawner(LeftAreaTabId, tab);
FOnSpawnTab tab2;
tab2.BindSP(this, &FWeaponAssetEditor::Spawn_DetailsViewTab);
TabManager->RegisterTabSpawner(DetailTabId, tab2);
}
TSharedRef<SDockTab> FWeaponAssetEditor::Spawn_LeftAreaTab(const FSpawnTabArgs& InArgs)
{
//TSharedPtr<SDockTab> tab = SNew(SDockTab)
//[
// SNew(SButton)
// .OnClicked(this, &FWeaponAssetEditor::OnClicked)//OnClicked 함수 연결
// [
// SNew(STextBlock)
// .Text(FText::FromString("Test"))
// ]
//];
//return tab.ToSharedRef();
return SNew(SDockTab)
[
LeftArea.ToSharedRef()
];
}
TSharedRef<SDockTab> FWeaponAssetEditor::Spawn_DetailsViewTab(const FSpawnTabArgs& InArgs)
{
return SNew(SDockTab)
[
DetailsView.ToSharedRef()
];
}
void FWeaponAssetEditor::OnListViewSelectedItem(FWeaponRowDataPtr InDataPtr)
{
if (InDataPtr == nullptr)//LeftArea에서 선택한게 없다면(또는 빈 공간을 선택했다면)
return;
if (!!GetEditingObject())//편집하는 객체가 있다면
RemoveEditingObject(GetEditingObject());//현재 창에서 편집중인 애들 제거한다.
AddEditingObject(InDataPtr->Asset);//현재 창에 편집해줄 객체를 등록해준다.
DetailsView->SetObject(InDataPtr->Asset);//창 안의 DetailsView도 변경해준다.
}
FName FWeaponAssetEditor::GetToolkitFName() const
{
return EditorName;//외부에서 어떤 에디터 이름을 쓸 지 정해준다.
}
FText FWeaponAssetEditor::GetBaseToolkitName() const
{
return FText::FromName(EditorName);//외부에서 어떤 에디터 이름을 쓸 지 정해준다.
}
FString FWeaponAssetEditor::GetWorldCentricTabPrefix() const
{
return EditorName.ToString();////외부에서 어떤 식별자를 쓸 지 정해준다.
}
FLinearColor FWeaponAssetEditor::GetWorldCentricTabColorScale() const
{
return FLinearColor(0, 0, 1);//파란색으로 설정.
}
FReply FWeaponAssetEditor::OnClicked()
{
GLog->Log("Test");
return FReply::Handled();//Handled()는 처리하고 끝낸다.
}
헤더 추가
- #include "SWeaponDoActionData.h"
void FWeaponAssetEditor::Open(FString InAssetName)에 DoActionData 추가
- FOnGetPropertyTypeCustomizationInstance instance;
- instance.BindStatic(&SWeaponDoActionData::MakeInstance);
- prop.RegisterCustomPropertyTypeLayout("DoActionData", instance);//instance를 delegate 등록
bool FWeaponAssetEditor::OnRequestClose()에 DoActionData 등록 해제 추가하기
- prop.UnregisterCustomClassLayout("DoActionData");
실행화면
'⭐ Unreal Engine > UE Plugin - Slate UI' 카테고리의 다른 글
[UE] Weapon Plugin 10: 삽입,삭제,복제 기능 추가, HitData 카테고리 추가 (0) | 2023.06.15 |
---|---|
[UE] Weapon Plugin 9: DoAction Data 연동하기 II (0) | 2023.06.14 |
[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 9: DoAction Data 연동하기 II
[UE] Weapon Plugin 9: DoAction Data 연동하기 II
2023.06.14 -
[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