[TIL] 251117

김세희·4일 전
0

알겠어! TIL 수정할게.

✍️Today I Learned

📅 2025-11-17

  • OnPreviewMouseButtonDown vs OnMouseButtonDown 차이점
  • 드래그앤드롭에서 좌클릭/우클릭 분기 처리
  • DragDropOperation에 데이터 저장하는 패턴
  • 언리얼 이벤트 버블링 순서 (Tunneling vs Bubbling)

OnPreviewMouseButtonDown vs OnMouseButtonDown 차이점

언리얼 엔진의 마우스 이벤트는 두 단계로 처리된다:

1. Tunneling 단계 (Preview)

OnPreviewMouseButtonDown
- 부모 → 자식 방향으로 전파 ⬇️
- 원본 이벤트 정보를 그대로 받음
- Get Effecting Button이 정확하게 동작함

2. Bubbling 단계 (일반)

OnMouseButtonDown
- 자식 → 부모 방향으로 전파 ⬆️
- 자식 위젯이 이벤트를 먼저 처리
- 이벤트 정보가 변형되거나 손상될 수 있음

실제 문제 상황

Button (또는 Canvas Panel)
├─ Image
└─ TextBlock
  • OnMouseButtonDown 사용: Image/TextBlock이 먼저 이벤트를 받아 변형 → 부모가 받을 때는 버튼 정보 손상
  • OnPreviewMouseButtonDown 사용: 부모가 먼저 원본 이벤트 받음 → 버튼 정보 정확함 ✅

결론: 드래그앤드롭 구현 시 OnPreviewMouseButtonDown을 사용해야 한다. 위젯 타입(Button, Canvas Panel 등)과 무관하게 자식 위젯이 있으면 Preview를 써야 한다.


드래그앤드롭에서 좌클릭/우클릭 분기 처리

요구사항

  • 좌클릭 드래그: 아이템 전체 이동 (bIsFullStack = true)
  • 우클릭 드래그: 아이템 1개만 이동 (bIsFullStack = false)

잘못된 접근 ❌

OnMouseButtonDown의 반환값(true/false)이
→ OnDragDetected나 OnDrop으로 전달된다고 생각

전달되지 않는다! 각 이벤트의 FPointerEvent 파라미터에서 독립적으로 확인해야 함.

올바른 접근 ✅

1단계: 버튼 정보 캐싱

OnPreviewMouseButtonDown:
  Mouse Event → Get Effecting Button
    → Set CachedMouseButton (위젯 변수에 저장)
    → Branch (Left or Right?)
       True: Detect Drag 반환
       False: Unhandled 반환

2단계: DragOperation에 정보 저장

OnDragDetected:
  CachedMouseButton 사용
    → Branch (Left?)
       True: 
         - bIsFullStack = true
         - TransferQuantity = CurrentStackSize
       False:
         - bIsFullStack = false
         - TransferQuantity = 1
    → DragOperation 생성 및 반환

3단계: OnDrop에서 사용

OnDrop:
  DragOperation → bIsFullStack 읽기
    → ServerTransferItem(..., bIsFullStack)

DragDropOperation에 데이터 저장하는 패턴

핵심 원칙

버튼 확인은 한 번만, 저장해서 재사용

구조

UCLASS()
class UMyDragDropOperation : public UDragDropOperation
{
    UPROPERTY(BlueprintReadWrite)
    bool bIsFullStack;
    
    UPROPERTY(BlueprintReadWrite)
    int32 TransferQuantity;
};

장점

  1. 중복 확인 제거: OnDragDetected에서 한 번만 확인
  2. 드래그 비주얼: TransferQuantity로 개수 표시 가능
  3. OnDrop 간소화: 저장된 값만 읽으면 됨

흐름

OnPreviewMouseButtonDown (버튼 확인 및 캐싱)
    ↓
OnDragDetected (DragOperation에 데이터 저장)
    ↓
OnDrop (저장된 데이터 사용)

추가 학습 내용

OnMouseButtonDown 반환값의 의미

  • Detect Drag: 드래그 감지 시작 (가장 일반적)
  • Handled: 이벤트만 소비, 드래그 안 함
  • Unhandled: 이벤트 무시, 부모로 전파

OnDragDetected의 버그

OnDragDetected의 Pointer Event에서 Get Effecting Button → None 반환

  • 드래그 감지 후 시점이라 원본 버튼 정보 손실
  • 해결책: OnPreviewMouseButtonDown에서 미리 캐싱

💡 느낀 점 (What I Felt)

언리얼의 이벤트 시스템이 생각보다 복잡하다는 걸 깨달았다. 처음에는 단순히 OnMouseButtonDown에서 반환값을 조작하면 되는 줄 알았는데, 실제로는:

  1. 이벤트 전파 순서 (Preview → Normal)
  2. 자식/부모 위젯 간 이벤트 흐름
  3. 각 이벤트 함수의 Pointer Event 독립성

이 모든 것을 이해해야 제대로 동작시킬 수 있었다.

특히 OnPreviewMouseButtonDown의 존재를 몰랐다면 계속 삽질했을 것 같다. 위젯 안에 Image나 TextBlock 같은 자식 위젯이 있으면 이들이 이벤트를 먼저 받아서 버튼 정보를 망가뜨린다는 것도 직접 겪지 않았으면 상상도 못했을 문제다.

결국 프레임워크의 내부 동작 원리를 이해하는 것이 중요하다는 걸 다시 한번 배웠다. 표면적인 사용법만 아는 것과 내부 메커니즘을 이해하는 것의 차이를 체감했다.

0개의 댓글