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,480 @@
1
+ # Editor Module Setup
2
+
3
+ Complete boilerplate and registration patterns for Unreal Engine editor modules. All editor extension code must live in a module with `"Type": "Editor"` to ensure it is excluded from packaged builds.
4
+
5
+ ---
6
+
7
+ ## Project Configuration
8
+
9
+ ### .uproject Module Entries
10
+
11
+ ```json
12
+ {
13
+ "Modules": [
14
+ {
15
+ "Name": "MyGame",
16
+ "Type": "Runtime",
17
+ "LoadingPhase": "Default"
18
+ },
19
+ {
20
+ "Name": "MyGameEditor",
21
+ "Type": "Editor",
22
+ "LoadingPhase": "PostEngineInit"
23
+ }
24
+ ]
25
+ }
26
+ ```
27
+
28
+ **LoadingPhase guidance**:
29
+
30
+ | Phase | Use When |
31
+ |---|---|
32
+ | `Default` | Module has no editor-UI dependencies |
33
+ | `PostEngineInit` | Module registers detail customizations, menus, or editor modes — use this for all editor extension modules |
34
+ | `PreDefault` | Module provides services needed before other modules load |
35
+
36
+ ---
37
+
38
+ ## Directory Layout
39
+
40
+ ```
41
+ MyProject/
42
+ Source/
43
+ MyGame/ ← Runtime module
44
+ MyGame.Build.cs
45
+ MyGame.h
46
+ Public/
47
+ Private/
48
+ MyGameEditor/ ← Editor module
49
+ MyGameEditor.Build.cs
50
+ MyGameEditor.h
51
+ Public/
52
+ Customizations/
53
+ FMyDataAssetCustomization.h
54
+ Modes/
55
+ MyEditorMode.h
56
+ AssetTypes/
57
+ FMyAssetTypeActions.h
58
+ Private/
59
+ MyGameEditorModule.cpp
60
+ Customizations/
61
+ FMyDataAssetCustomization.cpp
62
+ Modes/
63
+ MyEditorMode.cpp
64
+ AssetTypes/
65
+ FMyAssetTypeActions.cpp
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Build.cs
71
+
72
+ ```csharp
73
+ // MyGameEditor.Build.cs
74
+ using UnrealBuildTool;
75
+
76
+ public class MyGameEditor : ModuleRules
77
+ {
78
+ public MyGameEditor(ReadOnlyTargetRules Target) : base(Target)
79
+ {
80
+ PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
81
+
82
+ PublicDependencyModuleNames.AddRange(new string[]
83
+ {
84
+ "Core",
85
+ "CoreUObject",
86
+ "Engine",
87
+ });
88
+
89
+ PrivateDependencyModuleNames.AddRange(new string[]
90
+ {
91
+ // Editor framework
92
+ "UnrealEd",
93
+ "EditorFramework",
94
+
95
+ // Slate for editor UI
96
+ "Slate",
97
+ "SlateCore",
98
+ "EditorStyle", // FEditorStyle / FAppStyle
99
+
100
+ // Detail panel customization
101
+ "PropertyEditor", // IDetailCustomization, FPropertyEditorModule
102
+
103
+ // Editor subsystems
104
+ "EditorSubsystem", // UEditorSubsystem base class
105
+
106
+ // Blutility (editor utility widgets & scripted actions)
107
+ "Blutility", // UEditorUtilityWidget, UAssetActionUtility, UActorActionUtility
108
+
109
+ // Menus and toolbars
110
+ "ToolMenus", // UToolMenus
111
+
112
+ // Asset type actions and content browser integration
113
+ "AssetTools", // FAssetTypeActions_Base, IAssetTools
114
+ "ContentBrowser", // Content browser integration (if needed)
115
+
116
+ // Editor mode framework
117
+ "EditorInteractiveToolsFramework", // for UInteractiveTool-based modes (UE5)
118
+
119
+ // Input
120
+ "InputCore", // FKey, EKeys
121
+
122
+ // Your runtime module
123
+ "MyGame",
124
+ });
125
+
126
+ // Only include these when building for editor targets
127
+ if (Target.bBuildEditor)
128
+ {
129
+ PrivateDependencyModuleNames.AddRange(new string[]
130
+ {
131
+ "EditorScriptingUtilities", // UEditorAssetLibrary, UEditorLevelLibrary
132
+ });
133
+ }
134
+ }
135
+ }
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Module Header
141
+
142
+ ```cpp
143
+ // MyGameEditor.h
144
+ #pragma once
145
+
146
+ #include "Modules/ModuleManager.h"
147
+
148
+ class FMyGameEditorModule : public IModuleInterface
149
+ {
150
+ public:
151
+ // IModuleInterface
152
+ virtual void StartupModule() override;
153
+ virtual void ShutdownModule() override;
154
+
155
+ private:
156
+ void RegisterDetailCustomizations();
157
+ void UnregisterDetailCustomizations();
158
+
159
+ void RegisterAssetTypeActions();
160
+ void UnregisterAssetTypeActions();
161
+
162
+ void RegisterEditorModes();
163
+ void UnregisterEditorModes();
164
+
165
+ void RegisterMenuExtensions();
166
+
167
+ // Keep alive references for registered asset type actions
168
+ TArray<TSharedPtr<class IAssetTypeActions>> RegisteredAssetTypeActions;
169
+ };
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Module Implementation
175
+
176
+ ```cpp
177
+ // MyGameEditorModule.cpp
178
+ #include "MyGameEditor.h"
179
+
180
+ // Detail customizations
181
+ #include "Customizations/FMyDataAssetCustomization.h"
182
+ #include "Customizations/FMyStructCustomization.h"
183
+
184
+ // Editor modes
185
+ #include "Modes/MyEditorMode.h"
186
+
187
+ // Asset type actions
188
+ #include "AssetTypes/FMyAssetTypeActions.h"
189
+
190
+ // Runtime types (from MyGame module)
191
+ #include "MyDataAsset.h"
192
+ #include "MyStruct.h"
193
+
194
+ // UE headers
195
+ #include "PropertyEditorModule.h"
196
+ #include "AssetToolsModule.h"
197
+ #include "EditorModeRegistry.h"
198
+ #include "ToolMenus.h"
199
+ #include "Framework/Application/SlateApplication.h"
200
+ #include "Styling/AppStyle.h"
201
+
202
+ IMPLEMENT_MODULE(FMyGameEditorModule, MyGameEditor)
203
+
204
+ // ---- StartupModule ----------------------------------------------------------
205
+
206
+ void FMyGameEditorModule::StartupModule()
207
+ {
208
+ RegisterDetailCustomizations();
209
+ RegisterAssetTypeActions();
210
+ RegisterEditorModes();
211
+
212
+ // Defer menu registration until Slate is ready
213
+ UToolMenus::RegisterStartupCallback(
214
+ FSimpleMulticastDelegate::FDelegate::CreateRaw(
215
+ this, &FMyGameEditorModule::RegisterMenuExtensions));
216
+ }
217
+
218
+ // ---- ShutdownModule ---------------------------------------------------------
219
+
220
+ void FMyGameEditorModule::ShutdownModule()
221
+ {
222
+ // Menus must be unregistered before PropertyEditor / AssetTools modules unload
223
+ UToolMenus::UnRegisterStartupCallback(this);
224
+ if (UToolMenus* ToolMenus = UToolMenus::TryGet())
225
+ {
226
+ ToolMenus->UnregisterOwner(this);
227
+ }
228
+
229
+ UnregisterEditorModes();
230
+ UnregisterAssetTypeActions();
231
+ UnregisterDetailCustomizations();
232
+ }
233
+
234
+ // ---- Detail Customizations --------------------------------------------------
235
+
236
+ void FMyGameEditorModule::RegisterDetailCustomizations()
237
+ {
238
+ if (!FModuleManager::Get().IsModuleLoaded("PropertyEditor"))
239
+ {
240
+ return;
241
+ }
242
+ FPropertyEditorModule& PropertyModule =
243
+ FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
244
+
245
+ PropertyModule.RegisterCustomClassLayout(
246
+ UMyDataAsset::StaticClass()->GetFName(),
247
+ FOnGetDetailCustomizationInstance::CreateStatic(
248
+ &FMyDataAssetCustomization::MakeInstance));
249
+
250
+ PropertyModule.RegisterCustomPropertyTypeLayout(
251
+ FMyStruct::StaticStruct()->GetFName(),
252
+ FOnGetPropertyTypeCustomizationInstance::CreateStatic(
253
+ &FMyStructCustomization::MakeInstance));
254
+
255
+ PropertyModule.NotifyCustomizationModuleChanged();
256
+ }
257
+
258
+ void FMyGameEditorModule::UnregisterDetailCustomizations()
259
+ {
260
+ if (!FModuleManager::Get().IsModuleLoaded("PropertyEditor"))
261
+ {
262
+ return;
263
+ }
264
+ FPropertyEditorModule& PropertyModule =
265
+ FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
266
+
267
+ PropertyModule.UnregisterCustomClassLayout(
268
+ UMyDataAsset::StaticClass()->GetFName());
269
+ PropertyModule.UnregisterCustomPropertyTypeLayout(
270
+ FMyStruct::StaticStruct()->GetFName());
271
+ }
272
+
273
+ // ---- Asset Type Actions -----------------------------------------------------
274
+
275
+ void FMyGameEditorModule::RegisterAssetTypeActions()
276
+ {
277
+ IAssetTools& AssetTools =
278
+ FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
279
+
280
+ TSharedPtr<FMyAssetTypeActions> Actions =
281
+ MakeShareable(new FMyAssetTypeActions);
282
+ AssetTools.RegisterAssetTypeActions(Actions.ToSharedRef());
283
+ RegisteredAssetTypeActions.Add(Actions);
284
+ }
285
+
286
+ void FMyGameEditorModule::UnregisterAssetTypeActions()
287
+ {
288
+ if (!FModuleManager::Get().IsModuleLoaded("AssetTools"))
289
+ {
290
+ return;
291
+ }
292
+ IAssetTools& AssetTools =
293
+ FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get();
294
+
295
+ for (const TSharedPtr<IAssetTypeActions>& Action : RegisteredAssetTypeActions)
296
+ {
297
+ AssetTools.UnregisterAssetTypeActions(Action.ToSharedRef());
298
+ }
299
+ RegisteredAssetTypeActions.Empty();
300
+ }
301
+
302
+ // ---- Editor Modes -----------------------------------------------------------
303
+
304
+ void FMyGameEditorModule::RegisterEditorModes()
305
+ {
306
+ FEditorModeRegistry::Get().RegisterMode<FMyEditorMode>(
307
+ FMyEditorMode::EM_MyMode,
308
+ FText::FromString("My Editor Mode"),
309
+ FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.SelectMode"),
310
+ true // bVisible in the mode toolbar
311
+ );
312
+ }
313
+
314
+ void FMyGameEditorModule::UnregisterEditorModes()
315
+ {
316
+ FEditorModeRegistry::Get().UnregisterMode(FMyEditorMode::EM_MyMode);
317
+ }
318
+
319
+ // ---- Menu Extensions --------------------------------------------------------
320
+
321
+ void FMyGameEditorModule::RegisterMenuExtensions()
322
+ {
323
+ FToolMenuOwnerScoped OwnerScoped(this);
324
+
325
+ // Main menu extension
326
+ UToolMenu* WindowMenu =
327
+ UToolMenus::Get()->ExtendMenu("LevelEditor.MainMenu.Window");
328
+ {
329
+ FToolMenuSection& Section =
330
+ WindowMenu->FindOrAddSection("MyGameSection");
331
+ Section.Label = FText::FromString("My Game");
332
+
333
+ Section.AddMenuEntry(
334
+ "OpenMyPanel",
335
+ FText::FromString("My Tool Panel"),
336
+ FText::FromString("Open the My Game tool panel"),
337
+ FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Settings"),
338
+ FUIAction(FExecuteAction::CreateLambda([]()
339
+ {
340
+ // GEditor->GetEditorSubsystem<UEditorUtilitySubsystem>()
341
+ // ->SpawnAndRegisterTab(WidgetBP);
342
+ }))
343
+ );
344
+ }
345
+ }
346
+ ```
347
+
348
+ ---
349
+
350
+ ## WITH_EDITOR Guards in Runtime Modules
351
+
352
+ If a Runtime module needs to reference editor-only functionality (uncommon but valid for things like editor hints):
353
+
354
+ ```cpp
355
+ // SomeRuntimeClass.h
356
+ UCLASS()
357
+ class MYGAME_API UMyRuntimeClass : public UObject
358
+ {
359
+ GENERATED_BODY()
360
+
361
+ public:
362
+ #if WITH_EDITOR
363
+ // Editor-only virtual, e.g. for detail panel hints
364
+ virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
365
+ virtual bool CanEditChange(const FProperty* InProperty) const override;
366
+ #endif
367
+ };
368
+
369
+ // SomeRuntimeClass.cpp
370
+ #if WITH_EDITOR
371
+ void UMyRuntimeClass::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
372
+ {
373
+ Super::PostEditChangeProperty(PropertyChangedEvent);
374
+ const FName PropertyName = PropertyChangedEvent.GetPropertyName();
375
+ if (PropertyName == GET_MEMBER_NAME_CHECKED(UMyRuntimeClass, Speed))
376
+ {
377
+ Speed = FMath::Clamp(Speed, 0.f, MaxSpeed);
378
+ }
379
+ }
380
+
381
+ bool UMyRuntimeClass::CanEditChange(const FProperty* InProperty) const
382
+ {
383
+ if (!Super::CanEditChange(InProperty))
384
+ {
385
+ return false;
386
+ }
387
+ if (InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(UMyRuntimeClass, AdvancedSetting))
388
+ {
389
+ return bEnableAdvanced;
390
+ }
391
+ return true;
392
+ }
393
+ #endif
394
+ ```
395
+
396
+ ---
397
+
398
+ ## Asset Factory (UFactory) Boilerplate
399
+
400
+ Required to support "right-click > Create" in the Content Browser for a custom asset type:
401
+
402
+ ```cpp
403
+ // MyCustomAssetFactory.h
404
+ #pragma once
405
+ #include "Factories/Factory.h"
406
+ #include "MyCustomAssetFactory.generated.h"
407
+
408
+ UCLASS()
409
+ class UMyCustomAssetFactory : public UFactory
410
+ {
411
+ GENERATED_BODY()
412
+
413
+ public:
414
+ UMyCustomAssetFactory();
415
+
416
+ virtual UObject* FactoryCreateNew(
417
+ UClass* Class,
418
+ UObject* InParent,
419
+ FName Name,
420
+ EObjectFlags Flags,
421
+ UObject* Context,
422
+ FFeedbackContext* Warn) override;
423
+
424
+ virtual bool ShouldShowInNewMenu() const override { return true; }
425
+ };
426
+
427
+ // MyCustomAssetFactory.cpp
428
+ #include "MyCustomAssetFactory.h"
429
+ #include "MyCustomAsset.h"
430
+
431
+ UMyCustomAssetFactory::UMyCustomAssetFactory()
432
+ {
433
+ SupportedClass = UMyCustomAsset::StaticClass();
434
+ bCreateNew = true;
435
+ bEditAfterNew = true; // open editor immediately after creation
436
+ }
437
+
438
+ UObject* UMyCustomAssetFactory::FactoryCreateNew(
439
+ UClass* Class,
440
+ UObject* InParent,
441
+ FName Name,
442
+ EObjectFlags Flags,
443
+ UObject* Context,
444
+ FFeedbackContext* Warn)
445
+ {
446
+ return NewObject<UMyCustomAsset>(InParent, Class, Name, Flags);
447
+ }
448
+ ```
449
+
450
+ The factory is auto-discovered by the editor; no explicit registration is needed. The `UFactory` subclass must be in the editor module.
451
+
452
+ ---
453
+
454
+ ## Module Dependency Graph
455
+
456
+ ```
457
+ MyGameEditor (Type: Editor)
458
+ depends on → MyGame (Type: Runtime)
459
+ depends on → PropertyEditor, UnrealEd, Blutility, ToolMenus, AssetTools
460
+ depends on → Slate, SlateCore, EditorStyle
461
+
462
+ MyGame (Type: Runtime)
463
+ no editor dependencies
464
+ uses WITH_EDITOR guards for PostEditChangeProperty etc.
465
+ ```
466
+
467
+ ---
468
+
469
+ ## Checklist: New Editor Module
470
+
471
+ - [ ] `"Type": "Editor"` in .uproject
472
+ - [ ] `"LoadingPhase": "PostEngineInit"` in .uproject
473
+ - [ ] `Build.cs` references `UnrealEd`, `PropertyEditor`, `ToolMenus`, `Blutility` as needed
474
+ - [ ] `IMPLEMENT_MODULE(FMyEditorModule, MyEditorModuleName)` in .cpp
475
+ - [ ] All registrations in `StartupModule`
476
+ - [ ] All unregistrations in `ShutdownModule` (guarded with `IsModuleLoaded` checks)
477
+ - [ ] Menu registrations wrapped in `UToolMenus::RegisterStartupCallback`
478
+ - [ ] Menu unregistration: `UnRegisterStartupCallback` + `UnregisterOwner`
479
+ - [ ] `NotifyCustomizationModuleChanged()` called after detail customization registration
480
+ - [ ] No `#include "EdMode.h"` or other editor headers pulled into Runtime module headers