Dev Tool Library
Every Crimson plugin ships its runtime debugging as a SlateIM window in its own editor module. Each plugin carries its own copy of the same component library (its names carry the plugin's short name, for example FCrimsonCameraSlateIMDevToolWindow), so no plugin depends on CrimsonCommonEditor. CrimsonCommonEditor keeps the reference copy - FCrimsonSlateIMDevToolWindow and the CrimsonIM components described below - and the gallery that shows every component live.
CrimsonCommonEditor is an editor module: none of this ships in a packaged game, and there is no Blueprint path. If you only use the dev tools, the page that walks through your plugin's window is the one you want.The window
A tool derives from FCrimsonSlateIMDevToolWindow (DevTools/CrimsonSlateIMDevToolWindow.h). The base constructor takes the window title, its size, the console command that opens it and that command's help text, plus an optional PIE gate - pass bRequiresPIE = false for a tool that is useful with the editor idle. The base gives every tool the same outer panel, the PIE gate note, OnPIEStarted / OnPIEEnded reset hooks, net-context enumeration with DrawNetContextPicker and DrawCompareClientPicker, and the shared Reset layout button at the top of the window. The one function a tool must implement is DrawTool.
Tabs and sections
Inside DrawTool, CrimsonIM::BeginToolTabs / CrimsonIM::ToolTab / CrimsonIM::EndToolTabs build the tool's tabs. A tab body does not scroll; its last child is one CrimsonIM::Sections call, whose FCrimsonIMSection list declares the tab's titled sections. Each section is a real dock tab in a splitter - the reader can reorder them, stack them, split them side by side, tear one off into its own window, or dock it to the sidebar (bSidebar picks the starting side, Stack starts two sections as tabs of one slot). The arrangement is saved per window and per group and comes back on the next editor run; Reset layout forgets it and rebuilds every group in code order.
// MyPluginEditor/Private/MyDevToolsWindow.cpp#include "DevTools/CrimsonSlateIMDevToolWindow.h"#include "DevTools/CrimsonIM.h"#include "DevTools/CrimsonIMPickers.h"class FMyDevToolsWindow : public FCrimsonSlateIMDevToolWindow{CrimsonIM::FCrimsonIMActorPickerState TargetPicker;virtual void DrawTool(float DeltaTime) override{// Gathered here, in the tab body - a section Body only runs while its section is in front.UWorld* World = DrawNetContextPicker();AActor* Target = CrimsonIM::ActorPicker(TEXT("Target"), World, TargetPicker,[](AActor* A) { return A->FindComponentByClass<UMyComponent>() != nullptr; });CrimsonIM::Sections(TEXT("MyToolMain"), {{ TEXT("State"), TEXT("State"), 160.f, [&]{CrimsonIM::LabelValue(TEXT("Target"), Target ? Target->GetName() : TEXT("-"),Target ? ECrimsonIMTone::Good : ECrimsonIMTone::Muted);} },{ TEXT("Notes"), TEXT("Notes"), 140.f, [&] { CrimsonIM::Note(TEXT("Reference text.")); },NAME_None, /*bSidebar=*/ true },});}};
The rules that follow
| Rule | Why |
|---|---|
| Declare every section unconditionally | The declared list is the layout identity. A section that appears only under some condition changes the set, so a saved arrangement no longer matches it and the tab falls back to code order. |
Gather data in the tab body, not in a section Body | A Body runs only while its section is the front tab of its slot. Anything another section - or the viewport - depends on is computed before the Sections call, in the tab body. |
Take sizes from CrimsonDevToolSize, colors from ECrimsonIMTone | Never hardcode either. A raw FLinearColor is legal only as sample data passed to CrimsonIM::Swatch or CrimsonIM::LegendItem. |
| Put a new component in the library first | A container, widget, picker or feature the library lacks is added to CrimsonCommonEditor/Public/DevTools/ with a gallery entry, CrimsonCommonEditor is compiled, and only then is it used from the plugin's tool. |
Tool-local helpers are fine for pure domain logic - turning your plugin's own enum into a label, building a row model. Anything that draws is library code.
Crimson.DevTools.Gallery in the console, or open Tools -> Crimson Dev Tools -> Crimson Dev Tool Gallery, for a live reference of every component in the library. It does not need PIE, and its own tabs are built from sections, so it is also the quickest place to try the docking out.