[TIL] 250918

๊น€์„ธํฌยท2025๋…„ 9์›” 18์ผ
0

โœ๏ธToday I Learned

๐Ÿ“… 2025-09-18

  • ์ธ๋ฒคํ† ๋ฆฌ, ์žฅ๋น„์ฐฝ ๊ตฌํ˜„ ๊ณ„ํš

์ธ๋ฒคํ† ๋ฆฌ, ์žฅ๋น„์ฐฝ ๊ตฌํ˜„ ๊ณ„ํš

1. ํŠน์ • ํ‚ค๋กœ ์œ„์ ฏ ๋„์šฐ๊ธฐ

์–ด๋นŒ๋ฆฌํ‹ฐ๋กœ Push To Layer ์‚ฌ์šฉ

  • ์ฐธ๊ณ : GAB_ShowWidget_WhenInputPressed
  • ๊ฒฝ๋กœ: ShooterExplorer โ†’ Inventory Test
  • ๊ตฌํ˜„ ๋ฐฉ์‹: ์–ด๋นŒ๋ฆฌํ‹ฐ ์‹œ์Šคํ…œ์„ ํ™œ์šฉํ•ด ์ž…๋ ฅ ์ฒ˜๋ฆฌ์™€ UI ํ‘œ์‹œ๋ฅผ ์—ฐ๊ฒฐ
// ์–ด๋นŒ๋ฆฌํ‹ฐ์—์„œ PushContentToLayerForPlayer ์‚ฌ์šฉ
// AfterPush์—์„œ ์œ„์ ฏ ๋น„ํ™œ์„ฑํ™” ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ

2. ESC๋กœ ์œ„์ ฏ ๋‹ซ๊ธฐ

Universal Actions ํ™œ์šฉ

  • ์ฐธ๊ณ : W_LyraGameMenu
  • ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”: DT_UniversalActions

์œ„์ ฏ ์„ค์ •:

  • Is Back Handler: โœ… (ESC๋กœ ์œ„์ ฏ ๋‹ซ๊ธฐ)
  • Is Back Action Displayed in Action Bar: โœ… (๊ฒŒ์ž„ ๋ฉ”๋‰ด์— ํ‘œ์‹œ)

์šฉ๋„๋ณ„ ์„ค์ •:

  • ์ธ๋ฒคํ† ๋ฆฌ: Is Back Handler๋งŒ ์ฒดํฌ
  • ๊ฒŒ์ž„ ๋ฉ”๋‰ด: Is Back Action Displayed in Action Bar๋„ ์ฒดํฌ โ†’ Escape Menu์— ์œ„์ ฏ ์ถ”๊ฐ€

3. ์ธ๋ฒคํ† ๋ฆฌ ๊ทธ๋ฆฌ๋“œ ๊ตฌํ˜„

TileViewWidget ์‚ฌ์šฉ

// Event Construct์—์„œ ์ฒ˜๋ฆฌ (์œ„์ ฏ์ด ๋งค๋ฒˆ ์ƒˆ๋กœ ์ƒ์„ฑ๋˜๋ฏ€๋กœ)
void UInventoryWidget::NativeConstruct()
{
    Super::NativeConstruct();
    
    // ์ „์ฒด ์•„์ดํ…œ ๊ฐ€์ ธ์˜ค๊ธฐ
    RefreshInventoryGrid();
}

void RefreshInventoryGrid()
{
    // ์žฅ์ฐฉ ์ค‘์ด ์•„๋‹Œ ์•„์ดํ…œ๋งŒ ํ‘œ์‹œ
    for (const auto& Item : AllItems)
    {
        if (!Item.bIsEquipped)
        {
            InventoryTileView->AddItem(Item);
        }
    }
}

์•„์ดํ…œ ์ƒํƒœ ๊ด€๋ฆฌ

  • ์žฅ์ฐฉ ์—ฌ๋ถ€ ํ™•์ธ: bool bIsEquipped ๋ณ€์ˆ˜ ์ถ”๊ฐ€
  • ํ•„ํ„ฐ๋ง ๋กœ์ง: ์žฅ์ฐฉ ์ค‘ โ†’ ์žฅ๋น„์ฐฝ, ๋ฏธ์žฅ์ฐฉ โ†’ ์ธ๋ฒคํ† ๋ฆฌ

4. ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ ์‹œ์Šคํ…œ

๊ธฐ๋ณธ ๊ตฌ์กฐ

// UDragDropOperation ์ƒ์† ํด๋ž˜์Šค ๊ตฌํ˜„
class UItemDragDropOperation : public UDragDropOperation
{
    UPROPERTY()
    FInventoryItem ItemData;
    
    UPROPERTY()
    ESlotType SourceSlotType;
};

// ๋“œ๋ž˜๊ทธ ๊ฐ์ง€
FReply OnMouseButtonDown() override
{
    return FReply::Handled().DetectDrag(SharedThis(this), EKeys::LeftMouseButton);
}

// ๋“œ๋ž˜๊ทธ ์‹œ์ž‘
void OnDragDetected(const FPointerEvent& PointerEvent, UDragDropOperation*& Operation) override
{
    UItemDragDropOperation* DragOp = NewObject<UItemDragDropOperation>();
    DragOp->ItemData = MyItemData;
    Operation = DragOp;
}

// ๋“œ๋กญ ์ฒ˜๋ฆฌ
bool OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent, UDragDropOperation* Operation) override
{
    // ๋“œ๋กญ ๋กœ์ง ์ฒ˜๋ฆฌ
    return true;
}

5. ์žฅ๋น„์ฐฝ ์Šฌ๋กฏ ์‹œ์Šคํ…œ

์Šฌ๋กฏ ์œ„์ ฏ ๊ตฌ์กฐ

// ์Šคํ‚ฌ ์Šฌ๋กฏ๊ณผ ์œ ์‚ฌํ•œ ๊ตฌ์กฐ
class UEquipmentSlotWidget : public UUserWidget
{
    UPROPERTY(EditAnywhere, BlueprintReadOnly)
    EEquipmentSlotType SlotType; // Helmet, Armor, Weapon ๋“ฑ
    
    UPROPERTY()
    FInventoryItem CurrentEquippedItem;
};

Enum์œผ๋กœ ์Šฌ๋กฏ ํƒ€์ž… ๊ด€๋ฆฌ

UENUM(BlueprintType)
enum class EEquipmentSlotType : uint8
{
    None,
    Helmet,
    Armor,
    MainHand,
    OffHand,
    // ...
};

6. ์žฅ๋น„ ๋ณ€๊ฒฝ ํ”„๋กœ์„ธ์Šค (์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜)

์ „์ฒด ํ”Œ๋กœ์šฐ

sequenceDiagram
    participant I as ์ธ๋ฒคํ† ๋ฆฌ UI
    participant E as ์žฅ๋น„์ฐฝ UI
    participant EC as Equipment Component
    participant Other as ๊ธฐํƒ€ UI๋“ค
    
    I->>E: 1. ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ
    E->>E: 2. ์žฅ๋น„ ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ
    E->>EC: 3. Equipment Component๊ฐ€ ์ด๋ฒคํŠธ ์ˆ˜์‹ 
    EC->>EC: 4. ์‹ค์ œ ์žฅ์ฐฉ ์ฒ˜๋ฆฌ
    EC->>Other: 5. ์žฅ๋น„ ๋ณ€๊ฒฝ ์™„๋ฃŒ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ
    Other->>I: 6. ์ธ๋ฒคํ† ๋ฆฌ UI ๊ฐฑ์‹ 
    Other->>E: 7. ์žฅ๋น„์ฐฝ UI ๊ฐฑ์‹   
    Other->>Other: 8. ์Šคํƒฏ UI ๊ฐฑ์‹ 

์ฝ”๋“œ ๊ตฌํ˜„

// 1. ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ ์™„๋ฃŒ ์‹œ
bool UEquipmentSlotWidget::OnDrop(UDragDropOperation* Operation)
{
    // 2. ์žฅ๋น„ ๋ณ€๊ฒฝ ์š”์ฒญ ์ด๋ฒคํŠธ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ
    OnEquipmentChangeRequested.Broadcast(ItemData, MySlotType);
    return true;
}

// 3. Equipment Component์—์„œ ์ด๋ฒคํŠธ ์ˆ˜์‹ 
void UEquipmentComponent::HandleEquipmentChangeRequest(const FInventoryItem& Item, EEquipmentSlotType SlotType)
{
    // 4. ์‹ค์ œ ์žฅ์ฐฉ ์ฒ˜๋ฆฌ
    EquipItem(Item, SlotType);
    
    // 5. ์žฅ๋น„ ๋ณ€๊ฒฝ ์™„๋ฃŒ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ
    OnEquipmentChanged.Broadcast(SlotType, Item);
}

// 6-8. ๊ฐ UI๋“ค์—์„œ ๊ฐฑ์‹  ์ฒ˜๋ฆฌ
void UInventoryWidget::OnEquipmentChanged()
{
    RefreshInventoryGrid(); // ์žฅ์ฐฉ๋œ ์•„์ดํ…œ ํ•„ํ„ฐ๋ง
}

void UEquipmentScreenWidget::OnEquipmentChanged()
{
    RefreshEquipmentSlots(); // ์žฅ๋น„ ์Šฌ๋กฏ ์—…๋ฐ์ดํŠธ
}

void UStatsWidget::OnEquipmentChanged()
{
    UpdateCharacterStats(); // ์Šคํƒฏ ์žฌ๊ณ„์‚ฐ
}

ํ•ต์‹ฌ ํฌ์ธํŠธ

1. ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์„ค๊ณ„์˜ ์žฅ์ 

  • ๋””์ปคํ”Œ๋ง: UI์™€ ๋กœ์ง ์™„์ „ ๋ถ„๋ฆฌ
  • ํ™•์žฅ์„ฑ: ์ƒˆ๋กœ์šด ์‹œ์Šคํ…œ ์ถ”๊ฐ€ ์šฉ์ด
  • ์žฌ์‚ฌ์šฉ์„ฑ: ์ปดํฌ๋„ŒํŠธ ๋…๋ฆฝ์  ์‚ฌ์šฉ ๊ฐ€๋Šฅ

2. UI ๊ฐฑ์‹  ์ฃผ์˜์‚ฌํ•ญ

  • Drag & Drop โ‰  ์ž๋™ UI ๊ฐฑ์‹ 
  • ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ๊ณผ UI ๊ฐฑ์‹ ์€ ๋ณ„๊ฐœ ํ”„๋กœ์„ธ์Šค
  • ์ด๋ฒคํŠธ ์‹œ์Šคํ…œ์œผ๋กœ ์—ฐ๊ฒฐ ํ•„์š”

3. ์œ„์ ฏ ์ƒ๋ช…์ฃผ๊ธฐ ๊ณ ๋ ค

  • ๋งค๋ฒˆ ์ƒˆ๋กœ ์ƒ์„ฑ๋˜๋Š” ์œ„์ ฏ โ†’ NativeConstruct์—์„œ ์ดˆ๊ธฐํ™”
  • ์ง€์†์  ์—…๋ฐ์ดํŠธ ํ•„์š” ์‹œ โ†’ ์ด๋ฒคํŠธ ๊ตฌ๋… ๋ฐฉ์‹ ์‚ฌ์šฉ

๋‹ค์Œ ๋‹จ๊ณ„

  • ์•„์ดํ…œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ (์Šฌ๋กฏ ํƒ€์ž… ํ˜ธํ™˜์„ฑ)
  • ๋“œ๋ž˜๊ทธ ์ค‘ ์‹œ๊ฐ์  ํ”ผ๋“œ๋ฐฑ
  • ๋„คํŠธ์›Œํฌ ๋™๊ธฐํ™” (๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด์–ด)
  • ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฐ ์‚ฌ์šด๋“œ ํšจ๊ณผ

๐Ÿ’ก ๋А๋‚€ ์  (What I Felt)

CommonUI์™€ Universal Actions ๊ฐ™์€ ์–ธ๋ฆฌ์–ผ์˜ ๊ธฐ๋ณธ ์‹œ์Šคํ…œ๋“ค์ด ์ƒ๊ฐ๋ณด๋‹ค ๊ฐ•๋ ฅํ•˜๋‹ค๋Š” ๊ฑธ
๊นจ๋‹ฌ์•˜๋‹ค. ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ–ˆ๋˜ ESC ์ฒ˜๋ฆฌ๋‚˜ ๋ ˆ์ด์–ด ๊ด€๋ฆฌ ๊ฐ™์€ ๊ฒƒ๋“ค์ด ์ด๋ฏธ ์ž˜ ๋งŒ๋“ค์–ด์ง„
์‹œ์Šคํ…œ์œผ๋กœ ์ œ๊ณต๋˜๊ณ  ์žˆ์—ˆ๋‹ค. ๋ผ์ด๋ผ ํ”„๋กœ์ ํŠธ๋ฅผ ๋” ์ž์„ธํžˆ ๋œฏ์–ด๋ด์•ผ๊ฒ ๋‹ค.


0๊ฐœ์˜ ๋Œ“๊ธ€