#pragma once #include #include #include #include "UnrealWrapper.hpp" #include "Widget.hpp" #include "UserWidget.hpp" #include "WrapBox.hpp" namespace PalUIExtension::Api { // ================================================================== // WBP_PalCharacterScrollList_C -- the end of the chain. This is the // widget that creates, owns and destroys the slot tiles. // // PalBoxWidget // -> WBP_BoxPalList -> WBP_BoxPalListBase -> WBP_BoxPalScrollList // -> WBP_BaseCampPalList ------------------------> (same class) // == THIS // -> MyBlock (UWrapBox) // -> the tiles // ================================================================== class PalCharacterScrollList : public UserWidget { public: static auto ClassPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C"); } static auto DebugTag() -> const TCHAR* { return STR("PalCharacterScrollList"); } PalCharacterScrollList() = default; explicit PalCharacterScrollList(UObject* Obj) : UserWidget(Obj, ClassOf(), DebugTag()) {} // ============================================================== // THE TILES // ============================================================== auto TileContainer() const -> WrapBox { UObject* O = BoundObject(STR("MyBlock")); return O ? WrapBox{ O } : WrapBox{}; } auto Tiles() -> std::vector { WrapBox Box = TileContainer(); if (!Box.IsValid()) return {}; return Box.GetChildObjects(); } auto TileClass() const -> UClass* { return PropertyValue(STR("slotWidgetClass")).value_or(nullptr); } auto TileClassName() const -> RC::StringType { UClass* C = TileClass(); return C ? C->GetFullName() : RC::StringType{ STR("") }; } // ============================================================== // HOOK TARGETS // ============================================================== static auto CreateSlotWidgetPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:CreateSlotWidget"); } static auto AddSlotButtonToScrollListPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:AddSlotButtonToScrollList"); } static auto BindButtonEventsPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:BindButtonEvents"); } static auto OnUpdateSlotBindedPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:OnUpdateSlot_Binded"); } static auto OnSlotSyncedInternalPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:OnSlotSynced_Internal"); } static auto OnEmptySlotInternalPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:OnEmptySlot_Internal"); } static auto AddCharacterSlotPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:AddCharacterSlot"); } static auto ClearAllChildrenPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:ClearAllChildren"); } static auto ClearInnerChildrenPath() -> const TCHAR* { return STR("/Game/Pal/Blueprint/UI/CommonWidget/CommonScrollList/" "WBP_PalCharacterScrollList.WBP_PalCharacterScrollList_C:ClearInnnerChildren"); } // ---- frames -------------------------------------------------- struct CreateSlotWidgetFrame { UObject* TargetSlot; UObject* createdSlotButton; }; // Covers AddSlotButtonToScrollList (createdSlotButton), // BindButtonEvents (createdSlotButton), OnUpdateSlot_Binded // (SlotButton), OnSlotSynced_Internal (SelfButton), // OnEmptySlot_Internal (SlotButton), OnHovered_Internal / // OnUnhovered_Internal / OnFocused_Internal / // OnUnfocused_Internal (Widget), and "On Right Clicked Internal" // (ButtonBase). Eleven functions, one shape -- a single tile // pointer at 0x00. Naming it once is the honest version. struct TileFrame { UObject* Tile; }; struct AddCharacterSlotFrame { UObject* TargetSlot; }; struct TileClickFrame { UObject* Widget; // 0x00 uint8 PressType; // 0x08 }; struct AddCharacterSlotsFrame { UObject** Data; int32 Num; int32 Max; }; protected: PalCharacterScrollList(UObject* Obj, UClass* Expected, const TCHAR* Tag) : UserWidget(Obj, Expected, Tag) {} }; }