第一次提交
This commit is contained in:
35
Source/PHYInventory/Private/UI/ItemStacks/ItemData.cpp
Normal file
35
Source/PHYInventory/Private/UI/ItemStacks/ItemData.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
|
||||
|
||||
#include "UI/ItemStacks/ItemData.h"
|
||||
|
||||
#include "UI/ItemStacks/ItemStackContainer.h"
|
||||
|
||||
UItemStackContainer* UItemData::GetContainer() const
|
||||
{
|
||||
return OwningItemStackContainer.Get();
|
||||
}
|
||||
|
||||
void UItemData::SetContainer(UItemStackContainer* InContainer)
|
||||
{
|
||||
OwningItemStackContainer = InContainer;
|
||||
}
|
||||
|
||||
void UItemData::Reset()
|
||||
{
|
||||
ItemInfo = FGIS_ItemInfo();
|
||||
}
|
||||
|
||||
bool UItemData::IsValidItem() const
|
||||
{
|
||||
return ItemInfo.IsValid();
|
||||
}
|
||||
|
||||
int32 UItemData::GetItemSlotIndex() const
|
||||
{
|
||||
if (OwningItemStackContainer.IsValid())
|
||||
{
|
||||
return OwningItemStackContainer.Get()->FindItemSlotIndex(this);
|
||||
}
|
||||
return INDEX_NONE;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
|
||||
|
||||
#include "UI/ItemStacks/ItemDataDragDropOperation.h"
|
||||
#include "UI/ItemStacks/ItemData.h"
|
||||
#include "UI/ItemStacks/ItemStackContainer.h"
|
||||
|
||||
UItemStackContainer* UItemDataDragDropOperation::GetTargetItemStackView() const
|
||||
{
|
||||
return TargetItemStackView.Get();
|
||||
}
|
||||
|
||||
void UItemDataDragDropOperation::SetTargetItemStackView(UItemStackContainer* InItemStackContainer)
|
||||
{
|
||||
TargetItemStackView = TWeakObjectPtr<UItemStackContainer>(InItemStackContainer);
|
||||
}
|
||||
|
||||
UItemData* UItemDataDragDropOperation::GetTargetItemData() const
|
||||
{
|
||||
return TargetItemData.Get();
|
||||
}
|
||||
|
||||
void UItemDataDragDropOperation::SetTargetItemData(UItemData* InItemData)
|
||||
{
|
||||
TargetItemData = TWeakObjectPtr<UItemData>(InItemData);
|
||||
}
|
||||
|
||||
int32 UItemDataDragDropOperation::GetTargetItemIndex() const
|
||||
{
|
||||
return TargetItemIndex;
|
||||
}
|
||||
|
||||
void UItemDataDragDropOperation::SetTargetItemIndex(int32 InTargetItemIndex)
|
||||
{
|
||||
TargetItemIndex = InTargetItemIndex;
|
||||
}
|
||||
|
||||
UItemStackContainer* UItemDataDragDropOperation::GetSourceItemStackView() const
|
||||
{
|
||||
return SourceItemStackView.Get();
|
||||
}
|
||||
|
||||
void UItemDataDragDropOperation::SetSourceItemStackView(UItemStackContainer* InItemStackContainer)
|
||||
{
|
||||
SourceItemStackView = TWeakObjectPtr<UItemStackContainer>(InItemStackContainer);
|
||||
}
|
||||
|
||||
UItemData* UItemDataDragDropOperation::GetSourceItemData() const
|
||||
{
|
||||
return SourceItemData.Get();
|
||||
}
|
||||
|
||||
void UItemDataDragDropOperation::SetSourceItemData(UItemData* InItemData)
|
||||
{
|
||||
SourceItemData = TWeakObjectPtr<UItemData>(InItemData);
|
||||
}
|
||||
|
||||
int32 UItemDataDragDropOperation::GwtSourceItemIndex() const
|
||||
{
|
||||
return SourceItemIndex;
|
||||
}
|
||||
|
||||
void UItemDataDragDropOperation::SetSourceItemIndex(int32 InSourceItemIndex)
|
||||
{
|
||||
SourceItemIndex = InSourceItemIndex;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
|
||||
|
||||
#include "UI/ItemStacks/ItemDataDraggingWidget.h"
|
||||
|
||||
#include "CommonTextBlock.h"
|
||||
#include "Components/Image.h"
|
||||
#include "Components/SizeBox.h"
|
||||
|
||||
void UItemDataDraggingWidget::NativePreConstruct()
|
||||
{
|
||||
Super::NativePreConstruct();
|
||||
if (MainSizeBox)
|
||||
{
|
||||
MainSizeBox->SetHeightOverride(Height);
|
||||
MainSizeBox->SetWidthOverride(Width);
|
||||
}
|
||||
SetAmount(ItemAmount);
|
||||
SetIcon(IconTexture);
|
||||
}
|
||||
|
||||
void UItemDataDraggingWidget::SetAmount(const int32 InAmount)
|
||||
{
|
||||
ItemAmount = InAmount;
|
||||
if (AmountText)
|
||||
{
|
||||
AmountText->SetText(FText::AsNumber(ItemAmount));
|
||||
}
|
||||
}
|
||||
|
||||
void UItemDataDraggingWidget::SetIcon(UTexture2D* InIconTexture)
|
||||
{
|
||||
IconTexture = InIconTexture;
|
||||
if (IconImage)
|
||||
{
|
||||
IconImage->SetBrushFromTexture(IconTexture);
|
||||
}
|
||||
}
|
||||
493
Source/PHYInventory/Private/UI/ItemStacks/ItemStackContainer.cpp
Normal file
493
Source/PHYInventory/Private/UI/ItemStacks/ItemStackContainer.cpp
Normal file
@@ -0,0 +1,493 @@
|
||||
//
|
||||
|
||||
|
||||
#include "UI/ItemStacks/ItemStackContainer.h"
|
||||
|
||||
#include "CommonTabListWidgetBase.h"
|
||||
#include "GIS_InventoryFunctionLibrary.h"
|
||||
#include "GIS_InventorySystemComponent.h"
|
||||
#include "GIS_ItemCollection.h"
|
||||
#include "GIS_ItemSlotCollection.h"
|
||||
#include "ItemFilterInterface.h"
|
||||
#include "Async/GIS_AsyncAction_WaitInventorySystem.h"
|
||||
#include "Components/ListView.h"
|
||||
|
||||
void UItemStackContainer::SetOwningActor_Implementation(AActor* NewOwningActor)
|
||||
{
|
||||
OwningActor = NewOwningActor;
|
||||
}
|
||||
|
||||
void UItemStackContainer::OnDeactivated_Implementation()
|
||||
{
|
||||
IGUIS_UserWidgetInterface::OnDeactivated_Implementation();
|
||||
}
|
||||
|
||||
void UItemStackContainer::HandleTabSelected(const FName TabId)
|
||||
{
|
||||
ApplyFilter(TabId);
|
||||
}
|
||||
|
||||
void UItemStackContainer::HandleInventorySystemInitialized()
|
||||
{
|
||||
WaitInventorySystem = nullptr;
|
||||
if (OwningActor.IsValid())
|
||||
{
|
||||
InventorySystemComponent = UGIS_InventorySystemComponent::GetInventorySystemComponent(OwningActor.Get());
|
||||
if (InventorySystemComponent.IsValid())
|
||||
{
|
||||
// 订阅库存系统的消息
|
||||
InventorySystemComponent.Get()->OnInventoryStackUpdate.AddDynamic(this,&UItemStackContainer::HandleInventoryStackChanged);
|
||||
}
|
||||
if (FilterTabsReference)
|
||||
{
|
||||
FilterTabsReference.Get()->OnTabSelected.AddDynamic(this,&UItemStackContainer::HandleTabSelected);
|
||||
}
|
||||
// 创建默认的item data槽位
|
||||
CreateDefaultItemDataSlots();
|
||||
// 同步数据
|
||||
SyncAll();
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::CreateDefaultItemDataSlots()
|
||||
{
|
||||
if (!InventorySystemComponent.IsValid()) return;
|
||||
UGIS_ItemCollection* OutCollection;
|
||||
// 从库存系统中获取集合,并添加到item data中
|
||||
if (InventorySystemComponent->FindTypedCollectionByTag(CollectionToTrackTag,UGIS_ItemSlotCollection::StaticClass(),OutCollection))
|
||||
{
|
||||
if (UGIS_ItemSlotCollection* SlotCollection = Cast<UGIS_ItemSlotCollection>(OutCollection))
|
||||
{
|
||||
const TArray<FGIS_ItemSlotDefinition>& Definitions = SlotCollection->GetMyDefinition()->GetSlotDefinitions();
|
||||
for (int i = 0; i < Definitions.Num(); ++i)
|
||||
{
|
||||
SetOrAddItemInfoToItemDataArray(FGIS_ItemInfo(),i);
|
||||
}
|
||||
for (int i = 0; i < ItemDataArray.Num(); ++i)
|
||||
{
|
||||
ItemDataArray[i]->SetItemSlotDefinition(Definitions[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 如果没有找到slot collection,则创建默认数量的item data槽位
|
||||
if (bCreateDefaultItemDataSlots)
|
||||
{
|
||||
for (int i = 0; i < DefaultItemDataSlotCount; ++i)
|
||||
{
|
||||
SetOrAddItemInfoToItemDataArray(FGIS_ItemInfo(),i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::OnActivated_Implementation()
|
||||
{
|
||||
// 注册list view events
|
||||
RegisterListViewEvents();
|
||||
OwningActor = Execute_GetOwningActor(this);
|
||||
if (OwningActor.IsValid())
|
||||
{
|
||||
WaitInventorySystem = UGIS_AsyncAction_WaitInventorySystemInitialized::WaitInventorySystemInitialized(this,OwningActor.Get());
|
||||
if (WaitInventorySystem)
|
||||
{
|
||||
WaitInventorySystem->OnCompleted.AddDynamic(this,&UItemStackContainer::HandleInventorySystemInitialized);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AActor* UItemStackContainer::GetOwningActor_Implementation()
|
||||
{
|
||||
if (!OwningActor.IsValid())
|
||||
{
|
||||
if (GetOwningPlayerPawn())
|
||||
{
|
||||
OwningActor = GetOwningPlayerPawn();
|
||||
}
|
||||
else
|
||||
{
|
||||
OwningActor = GetOwningPlayer();
|
||||
}
|
||||
}
|
||||
return OwningActor.Get();
|
||||
}
|
||||
|
||||
void UItemStackContainer::AddFilterObject(UObject* InFilterObject)
|
||||
{
|
||||
if (InFilterObject && InFilterObject->Implements<UItemFilterInterface>())
|
||||
{
|
||||
ItemFilterObjects.AddUnique(InFilterObject);
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::RemoveFilterObject(UObject* InFilterObject)
|
||||
{
|
||||
if (InFilterObject && InFilterObject->Implements<UItemFilterInterface>())
|
||||
{
|
||||
ItemFilterObjects.Remove(InFilterObject);
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::SetSelectedIndexForNewItem(const int32 NewSelectedIndex)
|
||||
{
|
||||
SelectedIndexForNewItem = NewSelectedIndex;
|
||||
}
|
||||
|
||||
bool UItemStackContainer::SwapItemDataSlots(const int32 IndexA, const int32 IndexB)
|
||||
{
|
||||
if (!CanMoveItem(IndexA,this,IndexB)) return false;
|
||||
if (ItemDataArray.IsValidIndex(IndexA) && ItemDataArray.IsValidIndex(IndexB))
|
||||
{
|
||||
// 缓存A的数据
|
||||
const UItemData* TempItemData = ItemDataArray[IndexA];
|
||||
const UItemData* TargetItemData = ItemDataArray[IndexB];
|
||||
// 缓存其中的数据
|
||||
TOptional<FGIS_ItemInfo> TempItemInfo = TempItemData ? TOptional<FGIS_ItemInfo>(TempItemData->GetItemInfo()) : TOptional<FGIS_ItemInfo>();
|
||||
// 交换数据
|
||||
if (TOptional<FGIS_ItemInfo> TempTargetItemInfo = TargetItemData ? TOptional<FGIS_ItemInfo>(TargetItemData->GetItemInfo()) : TOptional<FGIS_ItemInfo>(); TempTargetItemInfo.IsSet())
|
||||
{
|
||||
AssignItemInfoToItemData(TempTargetItemInfo.GetValue(), IndexA);
|
||||
}
|
||||
if (TempItemInfo.IsSet())
|
||||
{
|
||||
AssignItemInfoToItemData(TempItemInfo.GetValue(), IndexB);
|
||||
}
|
||||
LastDropIndex = IndexB;
|
||||
// 同步list view
|
||||
SyncItemDataToListView();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UItemStackContainer::SwapItemDataToOtherContainer(const int32 SourceIndex, UItemStackContainer* TargetContainer,
|
||||
const int32 TargetIndex)
|
||||
{
|
||||
if (!TargetContainer) return false;
|
||||
if (!CanMoveItem(SourceIndex,TargetContainer,TargetIndex)) return false;
|
||||
if (ItemDataArray.IsValidIndex(SourceIndex) && TargetContainer->GetItemDataArray().IsValidIndex(TargetIndex))
|
||||
{
|
||||
// 缓存A的数据
|
||||
const UItemData* TempItemData = ItemDataArray[SourceIndex];
|
||||
const UItemData* TargetItemData = TargetContainer->GetItemDataArray()[TargetIndex];
|
||||
// 缓存其中的数据
|
||||
TOptional<FGIS_ItemInfo> TempItemInfo = TempItemData ? TOptional<FGIS_ItemInfo>(TempItemData->GetItemInfo()) : TOptional<FGIS_ItemInfo>();
|
||||
if (TOptional<FGIS_ItemInfo> TempTargetItemInfo = TargetItemData ? TOptional<FGIS_ItemInfo>(TargetItemData->GetItemInfo()) : TOptional<FGIS_ItemInfo>(); TempTargetItemInfo.IsSet())
|
||||
{
|
||||
AssignItemInfoToItemData(TempTargetItemInfo.GetValue(), SourceIndex);
|
||||
}
|
||||
if (TempItemInfo.IsSet())
|
||||
{
|
||||
TargetContainer->AssignItemInfoToItemData(TempItemInfo.GetValue(), TargetIndex);
|
||||
}
|
||||
TargetContainer->LastDropIndex = TargetIndex;
|
||||
// 同步list view
|
||||
SyncItemDataToListView();
|
||||
TargetContainer->SyncItemDataToListView();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UItemStackContainer::CanMoveItem(const int32 IndexA,UItemStackContainer* TargetContainer,const int32 IndexB)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 UItemStackContainer::FindItemSlotIndex(const UItemData* InItemData) const
|
||||
{
|
||||
if (!InItemData) return INDEX_NONE;
|
||||
return ItemDataArray.IndexOfByKey(InItemData);
|
||||
}
|
||||
|
||||
void UItemStackContainer::AssignItemInfoToItemData(const FGIS_ItemInfo& InInfo, const int32 SlotIndex)
|
||||
{
|
||||
if (ItemDataArray.IsValidIndex(SlotIndex))
|
||||
{
|
||||
if (UItemData* ItemData = ItemDataArray[SlotIndex])
|
||||
{
|
||||
ItemData->SetItemInfo(InInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::UnassignItemInfoToItemData(const FGIS_ItemInfo& InInfo)
|
||||
{
|
||||
if (const int32 Index = FindItemIndexFromDataByStackID(InInfo.StackId); Index != INDEX_NONE)
|
||||
{
|
||||
const FGIS_ItemInfo EmptyInfo;
|
||||
AssignItemInfoToItemData(EmptyInfo, Index);
|
||||
}
|
||||
}
|
||||
|
||||
int32 UItemStackContainer::FindItemIndexFromDataByStackID(const FGuid& StackID) const
|
||||
{
|
||||
for (int32 Index = 0; Index < ItemDataArray.Num(); ++Index)
|
||||
{
|
||||
if (const UItemData* ItemData = ItemDataArray[Index])
|
||||
{
|
||||
if (ItemData->GetItemInfo().StackId == StackID)
|
||||
{
|
||||
return Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return INDEX_NONE;
|
||||
}
|
||||
|
||||
TArray<FGIS_ItemInfo> UItemStackContainer::GetItemInfoArrayFromInventorySystem()
|
||||
{
|
||||
TArray<FGIS_ItemInfo> LocalItemInfos;
|
||||
if (InventorySystemComponent.IsValid())
|
||||
{
|
||||
if (CollectionToTrackTag.IsValid())
|
||||
{
|
||||
if (const UGIS_ItemCollection* ItemCollection = InventorySystemComponent.Get()->GetCollectionByTag(CollectionToTrackTag))
|
||||
{
|
||||
LocalItemInfos = ItemCollection->GetAllItemInfos();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (LocalItemInfos.IsEmpty()) return LocalItemInfos;
|
||||
// 通过配置的name,和query 过滤
|
||||
if (ItemFilterMap.Num() > 0 && ItemFilterName.IsValid())
|
||||
{
|
||||
if (const FGameplayTagQuery* Query = ItemFilterMap.Find(ItemFilterName))
|
||||
{
|
||||
LocalItemInfos = UGIS_InventoryFunctionLibrary::FilterItemInfosByTagQuery(LocalItemInfos,*Query);
|
||||
}
|
||||
}
|
||||
// 通过Object过滤
|
||||
if (ItemFilterObjects.Num() > 0)
|
||||
{
|
||||
for (UObject* FilterObject : ItemFilterObjects)
|
||||
{
|
||||
if (FilterObject && FilterObject->Implements<UItemFilterInterface>())
|
||||
{
|
||||
LocalItemInfos = IItemFilterInterface::Execute_FilterItemInfo(FilterObject,LocalItemInfos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return LocalItemInfos;
|
||||
}
|
||||
|
||||
void UItemStackContainer::ResetItemDataArray()
|
||||
{
|
||||
for (UItemData* ItemData : ItemDataArray)
|
||||
{
|
||||
ItemData->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::SetOrAddItemInfoToItemDataArray(const FGIS_ItemInfo& InInfo, const int32 SlotIndex)
|
||||
{
|
||||
if (SlotIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// 确保数组大小足够
|
||||
if (ItemDataArray.Num() <= SlotIndex)
|
||||
{
|
||||
ItemDataArray.SetNum(SlotIndex + 1);
|
||||
}
|
||||
|
||||
// 确保该槽位有对象
|
||||
UItemData* ItemDataRef = ItemDataArray[SlotIndex];
|
||||
if (!ItemDataRef)
|
||||
{
|
||||
ItemDataRef = NewObject<UItemData>(this);
|
||||
}
|
||||
ItemDataRef->SetItemInfo(InInfo);
|
||||
}
|
||||
|
||||
void UItemStackContainer::SyncItemInfoToItemDataArray(const TArray<FGIS_ItemInfo>& InItemInfos)
|
||||
{
|
||||
if (InventorySystemComponent.IsValid() && CollectionToTrackTag.IsValid())
|
||||
{
|
||||
// 获取集合,如果是slotted collection则根据slot来赋值
|
||||
if (const UGIS_ItemSlotCollection* SlotCollection = Cast<UGIS_ItemSlotCollection>(InventorySystemComponent->GetCollectionByTag(CollectionToTrackTag)))
|
||||
{
|
||||
for (int i = 0; i < InItemInfos.Num(); ++i)
|
||||
{
|
||||
const FGIS_ItemInfo& Info = InItemInfos[i];
|
||||
const int32 SlotIndex = SlotCollection->GetItemSlotIndex(Info.Item);
|
||||
SetOrAddItemInfoToItemDataArray(Info, SlotIndex == INDEX_NONE ? i : SlotIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果是普通的集合,则直接按顺序赋值
|
||||
for (int i = 0; i < InItemInfos.Num(); ++i)
|
||||
{
|
||||
SetOrAddItemInfoToItemDataArray(InItemInfos[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::SyncItemDataToListView()
|
||||
{
|
||||
if (ItemListView == nullptr) return;
|
||||
ItemListView->ClearSelection();
|
||||
ItemListView->ClearListItems();
|
||||
ItemListView->SetListItems(ItemDataArray);
|
||||
ItemListView->RegenerateAllEntries();
|
||||
// 恢复上次拖拽的选中状态
|
||||
if (ItemDataArray.IsValidIndex(LastDropIndex) && LastDropIndex != INDEX_NONE)
|
||||
{
|
||||
ItemListView->SetSelectedItem(ItemDataArray[LastDropIndex]);
|
||||
LastDropIndex = INDEX_NONE;
|
||||
} else
|
||||
{
|
||||
// 默认选中第一个
|
||||
if (ItemDataArray.IsValidIndex(0) && ItemDataArray[0]->IsValidItem())
|
||||
{
|
||||
ItemListView->SetSelectedItem(ItemDataArray[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32 UItemStackContainer::FindSuitableItemDataSlotForNewItem()
|
||||
{
|
||||
if (SelectedIndexForNewItem == INDEX_NONE)
|
||||
{
|
||||
for (int i = 0; i < ItemDataArray.Num(); ++i)
|
||||
{
|
||||
if (const UItemData* ItemData = ItemDataArray[i])
|
||||
{
|
||||
if (!ItemData->IsValidItem())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ItemDataArray.Num();
|
||||
}
|
||||
const int32 ReturnIndex = SelectedIndexForNewItem;
|
||||
SelectedIndexForNewItem = INDEX_NONE;
|
||||
return ReturnIndex;
|
||||
}
|
||||
|
||||
void UItemStackContainer::SyncAll()
|
||||
{
|
||||
ResetItemDataArray();
|
||||
SyncItemInfoToItemDataArray(GetItemInfoArrayFromInventorySystem());
|
||||
SyncItemDataToListView();
|
||||
}
|
||||
|
||||
void UItemStackContainer::ApplyFilter(const FName& InFilterName)
|
||||
{
|
||||
if (InFilterName.IsNone()) return;
|
||||
if (ItemFilterMap.Contains(InFilterName))
|
||||
{
|
||||
ItemFilterName = InFilterName;
|
||||
SyncAll();
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::HandleItemSelectionChanged(UObject* Object) const
|
||||
{
|
||||
if (UItemData* SelectedItemData = Cast<UItemData>(Object))
|
||||
{
|
||||
OnItemSelectionChanged.Broadcast(SelectedItemData,true);
|
||||
return;
|
||||
}
|
||||
OnItemSelectionChanged.Broadcast(nullptr,false);
|
||||
}
|
||||
|
||||
void UItemStackContainer::HandleItemHoveredChanged(UObject* Object, bool bIsHovered) const
|
||||
{
|
||||
if (UItemData* HoveredItemData = Cast<UItemData>(Object))
|
||||
{
|
||||
OnItemHoveredChanged.Broadcast(HoveredItemData,bIsHovered);
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::HandleItemClicked(UObject* Object) const
|
||||
{
|
||||
if (UItemData* ClickedItemData = Cast<UItemData>(Object))
|
||||
{
|
||||
OnItemClicked.Broadcast(ClickedItemData);
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::HandleListViewEntryWidgetGenerated(UUserWidget& UserWidget) const
|
||||
{
|
||||
OnItemEntryGenerated.Broadcast(&UserWidget);
|
||||
}
|
||||
|
||||
void UItemStackContainer::HandleItemDoubleClicked(UObject* Object) const
|
||||
{
|
||||
if (UItemData* ClickedItemData = Cast<UItemData>(Object))
|
||||
{
|
||||
OnItemDoubleClicked.Broadcast(ClickedItemData);
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::RegisterListViewEvents()
|
||||
{
|
||||
if (ItemListView)
|
||||
{
|
||||
// 注册事件
|
||||
ItemSelectionChangedHandle = ItemListView->OnItemSelectionChanged().AddUObject(this, &UItemStackContainer::HandleItemSelectionChanged);
|
||||
ItemHoveredChangedHandle = ItemListView->OnItemIsHoveredChanged().AddUObject(this, &UItemStackContainer::HandleItemHoveredChanged);
|
||||
ItemClickedHandle = ItemListView->OnItemClicked().AddUObject(this, &UItemStackContainer::HandleItemClicked);
|
||||
ListViewEntryWidgetGeneratedHandle = ItemListView->OnEntryWidgetGenerated().AddUObject(this, &UItemStackContainer::HandleListViewEntryWidgetGenerated);
|
||||
ItemDoubleClickedHandle = ItemListView->OnItemDoubleClicked().AddUObject(this, &UItemStackContainer::HandleItemDoubleClicked);
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::UnregisterListViewEvents() const
|
||||
{
|
||||
if (ItemListView)
|
||||
{
|
||||
// 注销事件
|
||||
ItemListView->OnItemSelectionChanged().Remove(ItemSelectionChangedHandle);
|
||||
ItemListView->OnItemIsHoveredChanged().Remove(ItemHoveredChangedHandle);
|
||||
ItemListView->OnItemClicked().Remove(ItemClickedHandle);
|
||||
ItemListView->OnEntryWidgetGenerated().Remove(ListViewEntryWidgetGeneratedHandle);
|
||||
ItemListView->OnItemDoubleClicked().Remove(ItemDoubleClickedHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStackContainer::HandleInventoryStackChanged(const FGIS_InventoryStackUpdateMessage& Message)
|
||||
{
|
||||
if (const UGIS_InventorySystemComponent* Inventory = Message.Inventory)
|
||||
{
|
||||
// 仅处理关联的库存系统组件的消息
|
||||
if (!InventorySystemComponent.IsValid() && Inventory != InventorySystemComponent.Get()) return;
|
||||
// 获取集合
|
||||
if (UGIS_ItemCollection* ItemCollection = Inventory->GetCollectionById(Message.CollectionId))
|
||||
{
|
||||
// 仅处理配置的集合tag的消息
|
||||
if (ItemCollection->GetCollectionTag() != CollectionToTrackTag) return;
|
||||
FGIS_ItemInfo ChangedItemInfo = FGIS_ItemInfo(Message.Instance,Message.NewCount,ItemCollection,Message.StackId);
|
||||
switch (Message.ChangeType) {
|
||||
case EGIS_ItemStackChangeType::WasAdded:
|
||||
// 添加
|
||||
{
|
||||
const int32 SlotIndex = FindSuitableItemDataSlotForNewItem();
|
||||
SetOrAddItemInfoToItemDataArray(ChangedItemInfo, SlotIndex);
|
||||
}
|
||||
break;
|
||||
case EGIS_ItemStackChangeType::WasRemoved:
|
||||
// 移除
|
||||
{
|
||||
ChangedItemInfo.Amount = Message.NewCount - Message.Delta;
|
||||
UnassignItemInfoToItemData(ChangedItemInfo);
|
||||
}
|
||||
break;
|
||||
case EGIS_ItemStackChangeType::Changed:
|
||||
// 修改
|
||||
{
|
||||
if (const int32 ChangedIndex = FindItemIndexFromDataByStackID(Message.StackId); ChangedIndex != INDEX_NONE)
|
||||
{
|
||||
SetOrAddItemInfoToItemDataArray(ChangedItemInfo, ChangedIndex);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
SyncItemDataToListView();
|
||||
}
|
||||
}
|
||||
}
|
||||
186
Source/PHYInventory/Private/UI/ItemStacks/ItemStack_Base.cpp
Normal file
186
Source/PHYInventory/Private/UI/ItemStacks/ItemStack_Base.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
//
|
||||
|
||||
|
||||
#include "UI/ItemStacks/ItemStack_Base.h"
|
||||
|
||||
#include "GIS_ItemDefinition.h"
|
||||
#include "GIS_ItemInstance.h"
|
||||
#include "Components/ListView.h"
|
||||
#include "Components/MenuAnchor.h"
|
||||
#include "Components/OverlaySlot.h"
|
||||
#include "UI/Actions/GUIS_UIActionWidget.h"
|
||||
#include "UI/ItemStacks/ItemData.h"
|
||||
#include "UI/ItemStacks/ItemDataDragDropOperation.h"
|
||||
#include "UI/ItemStacks/ItemDataDraggingWidget.h"
|
||||
#include "UI/ItemStacks/ItemStackContainer.h"
|
||||
#include "UI/Widgets/Normal/AmountContainerBase.h"
|
||||
|
||||
void UItemStack_Base::UpdateAmount()
|
||||
{
|
||||
if (!AmountContainer) return;
|
||||
if (ItemData && ItemData->IsValidItem())
|
||||
{
|
||||
AmountContainer->UpdateAmount(ItemData->GetItemInfo().Amount);
|
||||
AmountContainer->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
||||
return;
|
||||
}
|
||||
AmountContainer->SetVisibility(ESlateVisibility::Collapsed);
|
||||
}
|
||||
|
||||
void UItemStack_Base::ResetState()
|
||||
{
|
||||
if (DynamicUIActionWidget) {
|
||||
DynamicUIActionWidget->UnregisterActions();
|
||||
}
|
||||
if (ActionsAnchor) {
|
||||
ActionsAnchor->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStack_Base::NativeOnListItemObjectSet(UObject* ListItemObject)
|
||||
{
|
||||
Super::NativeOnListItemObjectSet(ListItemObject);
|
||||
ItemData = Cast<UItemData>(ListItemObject);
|
||||
UpdateAmount();
|
||||
ResetState();
|
||||
//将UI数据与UI操作空间关联
|
||||
if (DynamicUIActionWidget) {
|
||||
DynamicUIActionWidget->SetAssociatedData(ItemData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UItemStack_Base::NativeOnEntryReleased()
|
||||
{
|
||||
Super::NativeOnEntryReleased();
|
||||
ResetState();
|
||||
if (DynamicUIActionWidget) {
|
||||
DynamicUIActionWidget->SetAssociatedData(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStack_Base::NativePreConstruct()
|
||||
{
|
||||
Super::NativePreConstruct();
|
||||
if (ActionsAnchor)
|
||||
{
|
||||
if (UOverlaySlot* OverlaySlot = Cast<UOverlaySlot>(ActionsAnchor->Slot))
|
||||
{
|
||||
OverlaySlot->SetHorizontalAlignment(ActionAnchorHorizontalAlignment);
|
||||
OverlaySlot->SetVerticalAlignment(ActionAnchorVerticalAlignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStack_Base::NativeOnDeselected(bool bBroadcast)
|
||||
{
|
||||
Super::NativeOnDeselected(bBroadcast);
|
||||
if (ItemData && ItemData->GetContainer())
|
||||
{
|
||||
if (ItemData->GetContainer()->IsItemActionAllowed())
|
||||
{
|
||||
if (DynamicUIActionWidget)
|
||||
{
|
||||
DynamicUIActionWidget->UnregisterActions();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UItemStack_Base::NativeOnSelected(bool bBroadcast)
|
||||
{
|
||||
Super::NativeOnSelected(bBroadcast);
|
||||
if (ItemData && ItemData->GetContainer())
|
||||
{
|
||||
if (ItemData->GetContainer()->IsItemActionAllowed())
|
||||
{
|
||||
if (DynamicUIActionWidget)
|
||||
{
|
||||
DynamicUIActionWidget->RegisterActionsWithFactory(UIActionFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UItemDataDragDropOperation* UItemStack_Base::DragFromSource(const FString& Tag)
|
||||
{
|
||||
if (!DraggingWidgetClass || !ItemData || !ItemData->IsValidItem()) return nullptr;
|
||||
|
||||
// 创建拖拽视觉widget
|
||||
UItemDataDraggingWidget* DraggingWidget = CreateWidget<UItemDataDraggingWidget>(this, DraggingWidgetClass);
|
||||
if (!DraggingWidget) return nullptr;
|
||||
if (const UGIS_ItemDefinition* ItemDef = ItemData->GetItemInfo().Item.Get()->GetDefinition(); ItemDef && ItemDef->Icon)
|
||||
{
|
||||
DraggingWidget->SetIcon(ItemDef->Icon);
|
||||
}
|
||||
DraggingWidget->SetAmount(ItemData->GetItemInfo().Amount);
|
||||
// 创建拖拽操作
|
||||
UItemDataDragDropOperation* DragDropOp = NewObject<UItemDataDragDropOperation>(this);
|
||||
DragDropOp->DefaultDragVisual = DraggingWidget;
|
||||
DragDropOp->Pivot = EDragPivot::CenterCenter;
|
||||
DragDropOp->Tag = Tag;
|
||||
// 设置源数据
|
||||
DragDropOp->SetSourceItemData(ItemData);
|
||||
DragDropOp->SetSourceItemStackView(ItemData->GetContainer());
|
||||
DragDropOp->SetSourceItemIndex(ItemData->GetItemSlotIndex());
|
||||
return DragDropOp;
|
||||
}
|
||||
|
||||
void UItemStack_Base::DropToDest(UItemDataDragDropOperation& DragOperation) const
|
||||
{
|
||||
if (!ItemData || !ItemData->IsValidItem()) return
|
||||
DragOperation.SetTargetItemData(ItemData);
|
||||
DragOperation.SetTargetItemStackView(ItemData->GetContainer());
|
||||
DragOperation.SetTargetItemIndex(ItemData->GetItemSlotIndex());
|
||||
}
|
||||
|
||||
void UItemStack_Base::NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent,
|
||||
UDragDropOperation*& OutOperation)
|
||||
{
|
||||
Super::NativeOnDragDetected(InGeometry, InMouseEvent, OutOperation);
|
||||
if (!ItemData || !ItemData->GetContainer()) return;
|
||||
if (ItemData->GetContainer()->IsItemActionAllowed() && ItemData->IsValidItem())
|
||||
{
|
||||
ActionsAnchor->Close();
|
||||
if (UItemDataDragDropOperation* DragOp = DragFromSource(TEXT("MoveIndex")))
|
||||
{
|
||||
OutOperation = DragOp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UItemStack_Base::NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent,
|
||||
UDragDropOperation* InOperation)
|
||||
{
|
||||
if (ItemData && ItemData->GetContainer() && ItemData->GetContainer()->IsItemActionAllowed())
|
||||
{
|
||||
if (UItemDataDragDropOperation* DragOp = Cast<UItemDataDragDropOperation>(InOperation))
|
||||
{
|
||||
DropToDest(*DragOp);
|
||||
if (DragOp->Tag == TEXT("MoveIndex"))
|
||||
{
|
||||
UItemStackContainer* SourceContainer = DragOp->GetSourceItemStackView();
|
||||
UItemStackContainer* TargetContainer = DragOp->GetTargetItemStackView();
|
||||
const int32 SourceIndex = DragOp->GwtSourceItemIndex();
|
||||
const int32 TargetIndex = DragOp->GetTargetItemIndex();
|
||||
if (SourceContainer && TargetContainer)
|
||||
{
|
||||
if (SourceContainer == TargetContainer)
|
||||
{
|
||||
// 交换数据槽位
|
||||
SourceContainer->SwapItemDataSlots(SourceIndex, TargetIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
// 跨容器交换数据槽位
|
||||
SourceContainer->SwapItemDataToOtherContainer(SourceIndex, TargetContainer, TargetIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation);
|
||||
}
|
||||
Reference in New Issue
Block a user