Editor Widgets
Shared, theme-aware ImGui widgets used across the Polyphase editor. Lives in Engine/Source/Editor/EditorWidgets.{h,cpp}. Everything in this header is #if EDITOR-gated — runtime code never sees it.
When you need any of the affordances below in an editor panel, use the widget. Do not hand-roll the equivalent — the widgets keep behavior, theming, drag-drop handling, and asset-system integration consistent across the whole editor.
Polyphase::Checkbox(label, bool*)
Drop-in replacement for ImGui::Checkbox that constrains the visual box size (gCheckboxSize, default 16px) without changing the row's layout height. The label baseline lines up with adjacent buttons / inputs / combos no matter what the theme's FramePadding is.
bool active = node->IsActive();
if (Polyphase::Checkbox("Active", &active))
{
node->SetActive(active);
}
Themes can override Polyphase::gCheckboxSize at theme-apply time — see Preferences/Appearance/Theme/EditorTheme.cpp and the CSS parser.
Polyphase::AssetRefPicker(...) — the unified asset picker
One widget for every "drop an asset here / pick / clear" affordance in the editor. Renders, left-to-right:
[Browse] [autocomplete InputText] [X clear] [Inspect] [Reveal]
It accepts a drag-drop payload from the Asset Panel, filters by asset type (with Material polymorphism — Material accepts MaterialBase / MaterialInstance / MaterialLite), and undo-wraps the assignment through ActionManager when given an undo context.
Signature
namespace Polyphase
{
enum AssetPickerFlags_ : uint32_t
{
AssetPickerFlags_None = 0,
AssetPickerFlags_NoAutocomplete = 1 << 0, // labelled button instead of InputText — compact table cells
AssetPickerFlags_NoBrowse = 1 << 1, // hide the Download/Upload/Info button + hover-delete shortcut
AssetPickerFlags_NoInspect = 1 << 2,
AssetPickerFlags_NoReveal = 1 << 3,
AssetPickerFlags_NoDragDrop = 1 << 4,
AssetPickerFlags_NoColorTint = 1 << 5,
};
using AssetPickerFlags = uint32_t;
struct AssetPickerUndoCtx
{
Object* mOwner = nullptr;
PropertyOwnerType mOwnerType = PropertyOwnerType::Count;
const char* mPropName = nullptr;
uint32_t mIndex = 0;
};
bool AssetRefPicker(const char* label,
AssetRef& ref,
TypeId typeFilter = 0,
AssetPickerFlags flags = 0,
const AssetPickerUndoCtx* undo = nullptr);
}
Returns true on the frame the AssetRef changes — handy for triggering a MarkDirty() callback.
Typical patterns
Bare slot in a custom panel (no Property, no undo):
Polyphase::AssetRefPicker("Brush Mask", mgr->mOptions.mBrushMask,
Texture::GetStaticType());
Compact cell in a table (drop + X only, no buttons or autocomplete):
const Polyphase::AssetPickerFlags kCompact =
Polyphase::AssetPickerFlags_NoAutocomplete |
Polyphase::AssetPickerFlags_NoBrowse |
Polyphase::AssetPickerFlags_NoInspect |
Polyphase::AssetPickerFlags_NoReveal;
ImGui::SetNextItemWidth(-32.0f);
if (Polyphase::AssetRefPicker("##spr", row.mSprite,
Texture::GetStaticType(), kCompact))
{
MarkDirty(map);
}
Property-backed (rare — the inspector does this for you): route through DrawAssetProperty in EditorImgui.cpp. It builds an AssetPickerUndoCtx from the Property+owner and delegates to the widget.
Width
The widget honors ImGui::SetNextItemWidth(...) / ImGui::PushItemWidth(...) for the central element (InputText in normal mode, labelled button in NoAutocomplete mode). Buttons after it are fixed-size.
Undo wrapping
undo == nullptr→ the widget mutates theAssetRefdirectly. Use this for non-Property panels (paint brush mask, table-cell pickers, etc.).undo != nullptrwithmOwnerType ∈ {Node, Asset}→ assignment routes throughActionManager::EXE_EditPropertyOnSelection, soCtrl+Zrestores the previous reference. The inspector path uses this.undo != nullptrwithmOwnerType == Count→ direct mutation, no undo. Used by the synth-Property paths (e.g., the Material shader-parameter texture slot before its migration).
Anti-patterns — don't roll your own
If you find yourself writing this:
// DON'T do this anymore.
ImGui::Button("Drop Texture Here##slot", ImVec2(-32.0f, 0.0f));
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* p = ImGui::AcceptDragDropPayload(DRAGDROP_ASSET))
{
AssetStub* stub = *(AssetStub**)p->Data;
if (stub && stub->mType == Texture::GetStaticType())
{
ref = LoadAsset(stub->mName);
}
}
ImGui::EndDragDropTarget();
}
ImGui::SameLine();
if (ImGui::SmallButton("X##clr")) ref = nullptr;
…stop. Use Polyphase::AssetRefPicker instead. You'll get the same drag-drop plus an X clear button that's actually consistent with every other asset slot in the editor, plus Inspect / Reveal / autocomplete / Material polymorphism / asset-color tint / undo wrapping when available — all the affordances users already know from the property inspector.
The same applies to material-instance texture parameters, paint settings, custom panel asset slots in addons, etc. — anywhere an AssetRef-shaped value needs to be picked, dropped, or cleared.
Where the implementation lives
| File | Role |
|---|---|
Engine/Source/Editor/EditorWidgets.h |
Public widget API: Checkbox, AssetRefPicker, flags, undo context. |
Engine/Source/Editor/EditorWidgets.cpp |
Implementations. |
Engine/Source/Editor/EditorWidgetsInternal.h |
Private bridge: declares PolyphaseEditorInternal::DrawAutocompleteDropdown and AssignAssetToProperty (defined in EditorImgui.cpp) so the widget can reuse them without duplicating ~300 lines of dropdown logic. Do not include from outside the Editor target. |
Engine/Source/Editor/EditorImgui.cpp::DrawAssetProperty |
Thin Property→widget adapter. The inspector's asset rows route through this. |