claude-code-arcane 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +54 -6
  3. package/agents/game/ue-blueprint-specialist.md +125 -0
  4. package/agents/game/ue-gas-specialist.md +133 -0
  5. package/agents/game/ue-umg-specialist.md +131 -0
  6. package/dist/cli.js +5 -0
  7. package/docs/SKILLS-CATALOG.md +42 -3
  8. package/docs/USER-GUIDE.md +2 -2
  9. package/hooks/detect-unreal.sh +90 -0
  10. package/package.json +1 -1
  11. package/profiles/unreal-dev.yaml +97 -0
  12. package/rules/gamedev/unreal-code.md +125 -0
  13. package/skills/install-mcp/SKILL.md +135 -46
  14. package/skills/install-mcp/references/unreal-operations.md +55 -0
  15. package/skills/ue-actor-component-architecture/SKILL.md +509 -0
  16. package/skills/ue-actor-component-architecture/references/actor-lifecycle.md +301 -0
  17. package/skills/ue-actor-component-architecture/references/component-types.md +592 -0
  18. package/skills/ue-ai-navigation/SKILL.md +526 -0
  19. package/skills/ue-ai-navigation/references/behavior-tree-patterns.md +392 -0
  20. package/skills/ue-ai-navigation/references/behavior-tree-workflow.md +107 -0
  21. package/skills/ue-ai-navigation/references/custom-bttask.md +104 -0
  22. package/skills/ue-ai-navigation/references/eqs-reference.md +423 -0
  23. package/skills/ue-animation-system/SKILL.md +521 -0
  24. package/skills/ue-animation-system/references/anim-notify-reference.md +486 -0
  25. package/skills/ue-animation-system/references/locomotion-setup.md +550 -0
  26. package/skills/ue-async-threading/SKILL.md +433 -0
  27. package/skills/ue-async-threading/references/thread-safety-guide.md +213 -0
  28. package/skills/ue-async-threading/references/threading-patterns.md +345 -0
  29. package/skills/ue-audio-system/SKILL.md +527 -0
  30. package/skills/ue-audio-system/references/audio-setup-patterns.md +700 -0
  31. package/skills/ue-blueprints/SKILL.md +134 -0
  32. package/skills/ue-blueprints/references/communication.md +82 -0
  33. package/skills/ue-character-movement/SKILL.md +475 -0
  34. package/skills/ue-character-movement/references/cmc-extension-patterns.md +335 -0
  35. package/skills/ue-character-movement/references/movement-pipeline.md +189 -0
  36. package/skills/ue-cpp-foundations/SKILL.md +533 -0
  37. package/skills/ue-cpp-foundations/references/components-and-gc.md +107 -0
  38. package/skills/ue-cpp-foundations/references/container-patterns.md +544 -0
  39. package/skills/ue-cpp-foundations/references/delegate-patterns.md +497 -0
  40. package/skills/ue-cpp-foundations/references/gameplay-classes-cpp.md +136 -0
  41. package/skills/ue-cpp-foundations/references/property-specifiers.md +306 -0
  42. package/skills/ue-data-assets-tables/SKILL.md +527 -0
  43. package/skills/ue-data-assets-tables/references/asset-loading-patterns.md +306 -0
  44. package/skills/ue-data-assets-tables/references/data-driven-design.md +378 -0
  45. package/skills/ue-editor-tools/SKILL.md +523 -0
  46. package/skills/ue-editor-tools/references/detail-customization-patterns.md +395 -0
  47. package/skills/ue-editor-tools/references/editor-module-setup.md +480 -0
  48. package/skills/ue-game-features/SKILL.md +477 -0
  49. package/skills/ue-game-features/references/experience-system.md +222 -0
  50. package/skills/ue-game-features/references/game-feature-patterns.md +308 -0
  51. package/skills/ue-gameplay-abilities/SKILL.md +518 -0
  52. package/skills/ue-gameplay-abilities/references/ability-task-reference.md +391 -0
  53. package/skills/ue-gameplay-abilities/references/gameplay-effect-reference.md +397 -0
  54. package/skills/ue-gameplay-abilities/references/gas-setup-patterns.md +369 -0
  55. package/skills/ue-gameplay-framework/SKILL.md +466 -0
  56. package/skills/ue-gameplay-framework/references/framework-class-map.md +243 -0
  57. package/skills/ue-input-system/SKILL.md +394 -0
  58. package/skills/ue-input-system/references/cpp-setup.md +131 -0
  59. package/skills/ue-input-system/references/enhanced-input-workflow.md +117 -0
  60. package/skills/ue-input-system/references/input-action-reference.md +731 -0
  61. package/skills/ue-mass-entity/SKILL.md +476 -0
  62. package/skills/ue-mass-entity/references/mass-entity-patterns.md +319 -0
  63. package/skills/ue-mass-entity/references/mass-fragment-reference.md +119 -0
  64. package/skills/ue-materials-rendering/SKILL.md +526 -0
  65. package/skills/ue-materials-rendering/references/material-parameter-reference.md +216 -0
  66. package/skills/ue-materials-rendering/references/post-process-settings.md +383 -0
  67. package/skills/ue-module-build-system/SKILL.md +487 -0
  68. package/skills/ue-module-build-system/references/build-cs-reference.md +418 -0
  69. package/skills/ue-module-build-system/references/common-build-errors.md +381 -0
  70. package/skills/ue-naming-conventions/SKILL.md +142 -0
  71. package/skills/ue-naming-conventions/references/asset-name-modifiers.md +233 -0
  72. package/skills/ue-naming-conventions/references/content-structure.md +83 -0
  73. package/skills/ue-networking-replication/SKILL.md +452 -0
  74. package/skills/ue-networking-replication/references/replication-patterns.md +526 -0
  75. package/skills/ue-networking-replication/references/rpc-decision-guide.md +393 -0
  76. package/skills/ue-niagara-effects/SKILL.md +531 -0
  77. package/skills/ue-niagara-effects/references/niagara-data-interfaces.md +491 -0
  78. package/skills/ue-niagara-effects/references/niagara-parameter-types.md +153 -0
  79. package/skills/ue-niagara-effects/references/niagara-workflow.md +115 -0
  80. package/skills/ue-packaging/SKILL.md +116 -0
  81. package/skills/ue-physics-collision/SKILL.md +423 -0
  82. package/skills/ue-physics-collision/references/collision-channel-setup.md +218 -0
  83. package/skills/ue-physics-collision/references/trace-patterns.md +499 -0
  84. package/skills/ue-procedural-generation/SKILL.md +505 -0
  85. package/skills/ue-procedural-generation/references/pcg-node-reference.md +381 -0
  86. package/skills/ue-procedural-generation/references/procedural-mesh-patterns.md +940 -0
  87. package/skills/ue-project-context/SKILL.md +305 -0
  88. package/skills/ue-sequencer-cinematics/SKILL.md +506 -0
  89. package/skills/ue-sequencer-cinematics/references/sequencer-patterns.md +629 -0
  90. package/skills/ue-serialization-savegames/SKILL.md +524 -0
  91. package/skills/ue-serialization-savegames/references/save-system-architecture.md +705 -0
  92. package/skills/ue-state-trees/SKILL.md +489 -0
  93. package/skills/ue-state-trees/references/state-tree-mass-integration.md +184 -0
  94. package/skills/ue-state-trees/references/state-tree-patterns.md +321 -0
  95. package/skills/ue-testing-debugging/SKILL.md +520 -0
  96. package/skills/ue-testing-debugging/references/automation-test-patterns.md +387 -0
  97. package/skills/ue-testing-debugging/references/profiling-commands.md +357 -0
  98. package/skills/ue-ui-umg-slate/SKILL.md +431 -0
  99. package/skills/ue-ui-umg-slate/references/common-ui-setup.md +484 -0
  100. package/skills/ue-ui-umg-slate/references/widget-types.md +487 -0
  101. package/skills/ue-world-level-streaming/SKILL.md +518 -0
  102. package/skills/ue-world-level-streaming/references/streaming-patterns.md +414 -0
  103. package/templates/gamedev/unreal-project-context.md +107 -0
@@ -0,0 +1,484 @@
1
+ # Common UI Plugin — Setup and Patterns
2
+
3
+ > Source: `Engine/Plugins/Runtime/CommonUI/Source/CommonUI/Public/`
4
+
5
+ Common UI is Epic's cross-platform UI framework built on top of UMG. It handles input method detection (gamepad vs. mouse vs. touch), input routing through an activation tree, and provides base classes for platform-agnostic buttons and screens.
6
+
7
+ ---
8
+
9
+ ## Plugin Setup
10
+
11
+ ### 1. Enable the Plugin
12
+
13
+ In `<ProjectName>.uproject`:
14
+
15
+ ```json
16
+ {
17
+ "Plugins": [
18
+ { "Name": "CommonUI", "Enabled": true },
19
+ { "Name": "CommonInput", "Enabled": true }
20
+ ]
21
+ }
22
+ ```
23
+
24
+ ### 2. Build.cs Dependencies
25
+
26
+ ```csharp
27
+ // <ProjectName>.Build.cs
28
+ PrivateDependencyModuleNames.AddRange(new string[]
29
+ {
30
+ "CommonUI",
31
+ "CommonInput",
32
+ });
33
+ ```
34
+
35
+ ### 3. Configure the Game Viewport Client
36
+
37
+ Common UI requires a custom viewport client to detect input method changes.
38
+
39
+ **Project Settings → Maps & Modes → Game Viewport Client Class** → set to `CommonGameViewportClient`.
40
+
41
+ Or in `DefaultEngine.ini`:
42
+
43
+ ```ini
44
+ [/Script/Engine.Engine]
45
+ GameViewportClientClassName=/Script/CommonUI.CommonGameViewportClient
46
+ ```
47
+
48
+ `UCommonGameViewportClient` detects whether the most recent input was from a gamepad, mouse, or touch, and broadcasts this change via `UCommonInputSubsystem`. All `UCommonButtonBase` and `UCommonActivatableWidget` instances respond to this automatically.
49
+
50
+ ### 4. Configure Common Input Settings
51
+
52
+ In **Project Settings → Common Input Settings**:
53
+
54
+ - **Default Joystick Name**: Gamepad action icon set to display
55
+ - **Input Data**: Map platform + input type combinations to icon data tables
56
+ - **Platform Input**: Define which input types each target platform supports
57
+
58
+ Or via `DefaultInput.ini`:
59
+
60
+ ```ini
61
+ [/Script/CommonInput.CommonInputSettings]
62
+ InputData=/Game/UI/CommonInputData.CommonInputData
63
+ bEnableInputMethodTrigger=True
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Core Classes
69
+
70
+ ### UCommonActivatableWidget
71
+
72
+ The foundation of Common UI's screen management. A widget that can be activated (brought to focus) and deactivated without being created or destroyed.
73
+
74
+ **Header:** `CommonActivatableWidget.h`
75
+ **Base class:** `UCommonUserWidget` → `UUserWidget`
76
+
77
+ ```cpp
78
+ // Activation state
79
+ bool IsActivated() const;
80
+ void ActivateWidget();
81
+ void DeactivateWidget();
82
+
83
+ // Delegates (non-dynamic multicast)
84
+ FSimpleMulticastDelegate& OnActivated() const;
85
+ FSimpleMulticastDelegate& OnDeactivated() const;
86
+
87
+ // Focus
88
+ UWidget* GetDesiredFocusTarget() const;
89
+ void ClearFocusRestorationTarget();
90
+ void RequestRefreshFocus();
91
+ ```
92
+
93
+ **Key UPROPERTY settings (configure in Blueprint defaults or C++ constructor):**
94
+
95
+ ```cpp
96
+ // Auto-activate when constructed (false by default)
97
+ UPROPERTY(EditAnywhere, Category = Activation)
98
+ bool bAutoActivate = false;
99
+
100
+ // Acts as a modal — blocks input routing to all ancestors
101
+ UPROPERTY(EditAnywhere, Category = Activation)
102
+ bool bIsModal = false;
103
+
104
+ // Receives "Back" action and deactivates on it
105
+ UPROPERTY(EditAnywhere, Category = Back)
106
+ bool bIsBackHandler = false;
107
+
108
+ // Restore focus to the previously-focused widget when re-activating
109
+ UPROPERTY(EditAnywhere, Category = Activation)
110
+ bool bAutoRestoreFocus = false;
111
+
112
+ // Set visibility automatically on activation/deactivation
113
+ UPROPERTY(EditAnywhere, Category = Activation)
114
+ bool bSetVisibilityOnActivated = false;
115
+ UPROPERTY(EditAnywhere, Category = Activation)
116
+ ESlateVisibility ActivatedVisibility = ESlateVisibility::SelfHitTestInvisible;
117
+ UPROPERTY(EditAnywhere, Category = Activation)
118
+ bool bSetVisibilityOnDeactivated = false;
119
+ UPROPERTY(EditAnywhere, Category = Activation)
120
+ ESlateVisibility DeactivatedVisibility = ESlateVisibility::Collapsed;
121
+ ```
122
+
123
+ **Subclassing pattern:**
124
+
125
+ ```cpp
126
+ // MyMenuScreen.h
127
+ #pragma once
128
+ #include "CommonActivatableWidget.h"
129
+ #include "MyMenuScreen.generated.h"
130
+
131
+ UCLASS()
132
+ class MYGAME_API UMyMenuScreen : public UCommonActivatableWidget
133
+ {
134
+ GENERATED_BODY()
135
+
136
+ protected:
137
+ virtual void NativeOnActivated() override;
138
+ virtual void NativeOnDeactivated() override;
139
+ virtual UWidget* NativeGetDesiredFocusTarget() const override;
140
+ virtual TOptional<FUIInputConfig> GetDesiredInputConfig() const override;
141
+
142
+ UPROPERTY(meta=(BindWidget)) TObjectPtr<UCommonButtonBase> CloseButton;
143
+ UPROPERTY(meta=(BindWidget)) TObjectPtr<UCommonButtonBase> ConfirmButton;
144
+ };
145
+ ```
146
+
147
+ ```cpp
148
+ // MyMenuScreen.cpp
149
+ void UMyMenuScreen::NativeOnActivated()
150
+ {
151
+ Super::NativeOnActivated();
152
+ CloseButton->OnClicked().AddUObject(this, &UMyMenuScreen::DeactivateWidget);
153
+ ConfirmButton->OnClicked().AddUObject(this, &UMyMenuScreen::HandleConfirm);
154
+ }
155
+
156
+ void UMyMenuScreen::NativeOnDeactivated()
157
+ {
158
+ CloseButton->OnClicked().RemoveAll(this);
159
+ ConfirmButton->OnClicked().RemoveAll(this);
160
+ Super::NativeOnDeactivated();
161
+ }
162
+
163
+ UWidget* UMyMenuScreen::NativeGetDesiredFocusTarget() const
164
+ {
165
+ // The first focusable button receives focus when this screen activates
166
+ return ConfirmButton;
167
+ }
168
+
169
+ TOptional<FUIInputConfig> UMyMenuScreen::GetDesiredInputConfig() const
170
+ {
171
+ // ECommonInputMode::Menu — enables gamepad menu navigation, hides cursor on gamepad
172
+ return FUIInputConfig(ECommonInputMode::Menu, EMouseCaptureMode::NoCapture);
173
+ }
174
+ ```
175
+
176
+ ---
177
+
178
+ ### UCommonActivatableWidgetStack
179
+
180
+ **Header:** `Widgets/CommonActivatableWidgetContainer.h`
181
+ **Base class:** `UCommonActivatableWidgetContainerBase`
182
+
183
+ The correct class for screen layer stacks. Shows only the topmost widget; deactivating the top widget reveals the previous one. Use this for game layer, menu layer, and modal layer containers — do NOT use `UCommonActivatableWidgetSwitcher` here, which inherits from `UCommonAnimatedSwitcher`/`UWidgetSwitcher` and is a different (index-based switcher) widget that does not have `AddWidget()`.
184
+
185
+ ```cpp
186
+ // In a root HUD widget:
187
+ UPROPERTY(meta=(BindWidget))
188
+ TObjectPtr<UCommonActivatableWidgetStack> MenuLayer;
189
+
190
+ // Push a new screen onto the stack:
191
+ void UMyHUDWidget::ShowOptionsScreen()
192
+ {
193
+ UMyOptionsScreen* Screen = Cast<UMyOptionsScreen>(
194
+ MenuLayer->AddWidget(UMyOptionsScreen::StaticClass()));
195
+ // AddWidget creates and activates the widget internally
196
+ }
197
+
198
+ // Go back (deactivate top widget — stack re-activates the previous one):
199
+ void UMyHUDWidget::GoBack()
200
+ {
201
+ if (UCommonActivatableWidget* Active = MenuLayer->GetActiveWidget())
202
+ {
203
+ Active->DeactivateWidget();
204
+ }
205
+ }
206
+ ```
207
+
208
+ **Important:** `UCommonActivatableWidgetStack::AddWidget(TSubclassOf<UCommonActivatableWidget>)` creates the widget and pushes it. It returns `UCommonActivatableWidget*` (cast to your type). Deactivating the top widget automatically re-activates the widget beneath it.
209
+
210
+ ---
211
+
212
+ ### UCommonButtonBase
213
+
214
+ **Header:** `CommonButtonBase.h`
215
+ **Base class:** `UCommonUserWidget`
216
+
217
+ A replacement for `UButton` that is aware of the current input method (mouse, gamepad, touch) and can display platform-appropriate icons (e.g., "A button" on Xbox, "Cross" on PlayStation).
218
+
219
+ ```cpp
220
+ // OnClicked returns FCommonButtonEvent (DECLARE_EVENT-based) — NOT a DYNAMIC delegate
221
+ // Use AddUObject or AddWeakLambda instead of AddDynamic
222
+ FCommonButtonEvent& OnClicked();
223
+
224
+ // Example binding in NativeOnActivated (remove in NativeOnDeactivated)
225
+ MyButton->OnClicked().AddUObject(this, &UMyScreen::HandleButtonClicked);
226
+ MyButton->OnClicked().RemoveAll(this);
227
+
228
+ // Enable/disable
229
+ MyButton->SetIsEnabled(false);
230
+
231
+ // Selected state (toggle-style buttons)
232
+ MyButton->SetIsSelected(true);
233
+ bool bSelected = MyButton->GetSelected();
234
+
235
+ // Hovering
236
+ MyButton->SetIsInteractionEnabled(true);
237
+ ```
238
+
239
+ **Styling:** `UCommonButtonBase` uses a `UCommonButtonStyle` data asset instead of `FButtonStyle`. Configure this in the widget Blueprint.
240
+
241
+ ---
242
+
243
+ ### UCommonUIActionRouter
244
+
245
+ **Header:** Not typically subclassed — managed by the Common UI subsystem.
246
+
247
+ The action router manages which activatable widget receives input actions (confirm, cancel/back, etc.) based on the current activation tree. When `UCommonActivatableWidget::ActivateWidget()` is called, the widget registers as a node in the action routing tree. Input actions are routed to the leaf-most active node first.
248
+
249
+ **You rarely interact with `UCommonUIActionRouter` directly.** Instead, configure per-widget behavior via:
250
+ - `bIsBackHandler` on `UCommonActivatableWidget`
251
+ - `GetDesiredInputConfig()` override
252
+ - `InputMapping` (Enhanced Input context) on `UCommonActivatableWidget`
253
+
254
+ ---
255
+
256
+ ### UCommonInputSubsystem
257
+
258
+ Provides runtime information about the current input method and allows observing changes.
259
+
260
+ ```cpp
261
+ // Get the subsystem
262
+ UCommonInputSubsystem* InputSubsystem = UCommonInputSubsystem::Get(GetOwningLocalPlayer());
263
+
264
+ // Query current input type
265
+ ECommonInputType CurrentType = InputSubsystem->GetCurrentInputType();
266
+ // ECommonInputType: None, MouseAndKeyboard, Gamepad, Touch
267
+
268
+ // Is gamepad active?
269
+ bool bGamepad = CurrentType == ECommonInputType::Gamepad;
270
+
271
+ // Observe input type changes
272
+ InputSubsystem->OnInputMethodChangedNative.AddUObject(
273
+ this, &UMyWidget::HandleInputMethodChanged);
274
+
275
+ UFUNCTION()
276
+ void UMyWidget::HandleInputMethodChanged(ECommonInputType NewInputType)
277
+ {
278
+ // Update cursor visibility, icon display, etc.
279
+ bool bShowMouse = NewInputType == ECommonInputType::MouseAndKeyboard
280
+ || NewInputType == ECommonInputType::Touch;
281
+ GetOwningPlayer()->SetShowMouseCursor(bShowMouse);
282
+ }
283
+ ```
284
+
285
+ ---
286
+
287
+ ## Input Configuration
288
+
289
+ ### FUIInputConfig
290
+
291
+ Returned from `UCommonActivatableWidget::GetDesiredInputConfig()` to define how input is handled while this widget is the active leaf.
292
+
293
+ ```cpp
294
+ // Menu mode: gamepad navigates widgets, no mouse capture
295
+ return FUIInputConfig(ECommonInputMode::Menu, EMouseCaptureMode::NoCapture);
296
+
297
+ // Game mode: game receives all input
298
+ return FUIInputConfig(ECommonInputMode::Game, EMouseCaptureMode::CapturePermanently);
299
+
300
+ // All mode: both game and UI receive input (e.g., for HUD with tooltips)
301
+ return FUIInputConfig(ECommonInputMode::All, EMouseCaptureMode::NoCapture);
302
+ ```
303
+
304
+ | `ECommonInputMode` | Description |
305
+ |---|---|
306
+ | `Menu` | Game input suspended. UI navigation active. |
307
+ | `Game` | Game receives input. UI does not route actions. |
308
+ | `All` | Both game and UI receive input simultaneously. |
309
+
310
+ ### Enhanced Input Integration
311
+
312
+ `UCommonActivatableWidget` supports an `InputMapping` property for adding an `UInputMappingContext` while the widget is active:
313
+
314
+ ```cpp
315
+ // Set in the widget's Blueprint defaults or C++ constructor:
316
+ UPROPERTY(EditAnywhere, Category="Input")
317
+ TObjectPtr<UInputMappingContext> InputMapping;
318
+
319
+ UPROPERTY(EditAnywhere, Category="Input")
320
+ int32 InputMappingPriority = 0;
321
+ ```
322
+
323
+ The mapping context is added when `ActivateWidget()` is called and removed when `DeactivateWidget()` is called via `ActivateMappingContext()` / `DeactivateMappingContext()`.
324
+
325
+ ---
326
+
327
+ ## UI Layer Architecture Pattern
328
+
329
+ A typical Common UI hierarchy for a game with main menu, pause, and HUD:
330
+
331
+ ```
332
+ AHUD or PlayerController
333
+ └── URootUIWidget (UUserWidget, AddToViewport ZOrder=0)
334
+ ├── UCommonActivatableWidgetStack "GameLayer"
335
+ │ └── UMyHUDWidget (always active during gameplay)
336
+ ├── UCommonActivatableWidgetStack "MenuLayer"
337
+ │ ├── UMyMainMenuWidget
338
+ │ ├── UMyOptionsScreen
339
+ │ └── UMyPauseMenuWidget
340
+ └── UCommonActivatableWidgetStack "ModalLayer"
341
+ └── UMyConfirmationDialog (modal, bIsModal=true)
342
+ ```
343
+
344
+ **Implementation:**
345
+
346
+ ```cpp
347
+ // URootUIWidget.h
348
+ UCLASS()
349
+ class MYGAME_API URootUIWidget : public UUserWidget
350
+ {
351
+ GENERATED_BODY()
352
+
353
+ public:
354
+ template<typename T>
355
+ T* PushMenuWidget(TSubclassOf<T> WidgetClass)
356
+ {
357
+ return Cast<T>(MenuLayer->AddWidget(WidgetClass));
358
+ // AddWidget creates, pushes, and activates the widget
359
+ }
360
+
361
+ void PopMenuWidget()
362
+ {
363
+ if (UCommonActivatableWidget* Active = MenuLayer->GetActiveWidget())
364
+ {
365
+ Active->DeactivateWidget();
366
+ }
367
+ }
368
+
369
+ protected:
370
+ UPROPERTY(meta=(BindWidget))
371
+ TObjectPtr<UCommonActivatableWidgetStack> GameLayer;
372
+
373
+ UPROPERTY(meta=(BindWidget))
374
+ TObjectPtr<UCommonActivatableWidgetStack> MenuLayer;
375
+
376
+ UPROPERTY(meta=(BindWidget))
377
+ TObjectPtr<UCommonActivatableWidgetStack> ModalLayer;
378
+ };
379
+ ```
380
+
381
+ ---
382
+
383
+ ## Common UI Gamepad Navigation
384
+
385
+ Common UI provides automatic focus management for gamepad navigation. When a `UCommonActivatableWidget` activates:
386
+
387
+ 1. `GetDesiredFocusTarget()` is called.
388
+ 2. The returned widget receives Slate keyboard focus.
389
+ 3. Directional pad / left stick navigates between focusable widgets automatically.
390
+ 4. "Back" / B-button / Escape triggers the back action if `bIsBackHandler = true`.
391
+
392
+ **Focus target best practices:**
393
+
394
+ ```cpp
395
+ UWidget* UMyMenuScreen::NativeGetDesiredFocusTarget() const
396
+ {
397
+ // Return the first interactive widget in tab order
398
+ // This is the widget that gets focus when the screen activates
399
+ return FirstButton;
400
+ }
401
+ ```
402
+
403
+ **Ensure your buttons are focusable:**
404
+
405
+ In `UCommonButtonBase` Blueprint defaults or via C++:
406
+ ```cpp
407
+ // IsFocusable is true by default on UCommonButtonBase
408
+ // For standard UButton, explicitly set it:
409
+ MyButton->InitIsFocusable(true); // Call before Slate widget is constructed
410
+ ```
411
+
412
+ ---
413
+
414
+ ## Common Mistakes
415
+
416
+ **Not removing the delegate binding when deactivated**
417
+ ```cpp
418
+ // BAD: leaks bindings, fires after the screen is gone
419
+ void UMyScreen::NativeOnActivated() {
420
+ MyButton->OnClicked().AddUObject(this, &UMyScreen::HandleClick);
421
+ // Never removed!
422
+ }
423
+
424
+ // GOOD
425
+ void UMyScreen::NativeOnActivated() {
426
+ MyButton->OnClicked().AddUObject(this, &UMyScreen::HandleClick);
427
+ }
428
+ void UMyScreen::NativeOnDeactivated() {
429
+ MyButton->OnClicked().RemoveAll(this);
430
+ }
431
+ ```
432
+
433
+ **Using AddDynamic with UCommonButtonBase::OnClicked()**
434
+ ```cpp
435
+ // WRONG: OnClicked() returns FCommonButtonEvent, not a DYNAMIC delegate
436
+ MyButton->OnClicked().AddDynamic(this, &UMyScreen::HandleClick); // Compile error
437
+
438
+ // CORRECT
439
+ MyButton->OnClicked().AddUObject(this, &UMyScreen::HandleClick);
440
+ ```
441
+
442
+ **Skipping the viewport client configuration**
443
+
444
+ Common UI's input method detection requires `UCommonGameViewportClient`. Without it, `UCommonInputSubsystem::GetCurrentInputType()` always returns `MouseAndKeyboard` on non-console platforms, and `UCommonButtonBase` icon display does not work.
445
+
446
+ **Mixing Common UI and raw SetInputMode calls**
447
+
448
+ Once Common UI is active, avoid calling `GetOwningPlayer()->SetInputMode(FInputModeUIOnly())`. Common UI manages input mode internally through `FUIInputConfig`. Direct calls bypass the activation tree and cause conflicts.
449
+
450
+ ```cpp
451
+ // BAD with Common UI
452
+ GetOwningPlayer()->SetInputMode(FInputModeUIOnly());
453
+
454
+ // GOOD: return the config from the activatable widget
455
+ TOptional<FUIInputConfig> UMyScreen::GetDesiredInputConfig() const {
456
+ return FUIInputConfig(ECommonInputMode::Menu, EMouseCaptureMode::NoCapture);
457
+ }
458
+ ```
459
+
460
+ **Not calling Super in activation overrides**
461
+ ```cpp
462
+ // REQUIRED — Super sets up internal state, delegates, and focus routing
463
+ void UMyScreen::NativeOnActivated() {
464
+ Super::NativeOnActivated(); // Must be called
465
+ // Your code
466
+ }
467
+ void UMyScreen::NativeOnDeactivated() {
468
+ // Your cleanup
469
+ Super::NativeOnDeactivated(); // Must be called
470
+ }
471
+ ```
472
+
473
+ ---
474
+
475
+ ## Checklist: Adding a New Screen
476
+
477
+ 1. Create a `UCommonActivatableWidget` subclass (C++ or BP).
478
+ 2. In C++: override `NativeOnActivated`, `NativeOnDeactivated`, `NativeGetDesiredFocusTarget`, `GetDesiredInputConfig`.
479
+ 3. In the UMG Blueprint: design the layout using `UCommonButtonBase` for all interactive buttons.
480
+ 4. Set `bIsBackHandler = true` if this screen should close on Back/Escape/B-button.
481
+ 5. Set `bAutoActivate = false` (default) unless you need activation on construction.
482
+ 6. Push via the appropriate layer stack (game, menu, or modal).
483
+ 7. Verify focus flows correctly on gamepad by testing `NativeGetDesiredFocusTarget`.
484
+ 8. Verify `GetDesiredInputConfig` returns the correct `ECommonInputMode`.