brainstorming
Structured design dialogue that validates ideas before implementation begins.
editor-panel-creation
Step-by-step workflow for creating new editor panels including interface design, DI registration, EditorLayer integration, and menu bar setup. Focuses on panel architecture and lifecycle, not UI component APIs.
Full skill instructions
This skill provides comprehensive guidance for creating new ImGui-based editor panels, ensuring consistency with the engine's dependency injection architecture, UI styling standards, and editor integration patterns.
CRITICAL REQUIREMENT: All editor panels MUST use the UI infrastructure (Drawers, Elements, FieldEditors) instead of manual ImGui code. This ensures consistency, maintainability, and productivity across the entire editor.
The editor provides comprehensive UI infrastructure:
Invoke this skill when:
Follow these 6 steps to create a new panel. Use the Testing Checklist to verify completeness.
Location: Editor/Panels/
Pattern: All panels use interface-based design for testability and DI
Interface Template:
namespace Editor.Panels;
/// <summary>
/// Interface for the [PanelName] panel.
/// </summary>
public interface IMyNewPanel
{
/// <summary>
/// Renders the panel using ImGui.
/// </summary>
void OnImGuiRender();
/// <summary>
/// Gets or sets whether the panel is currently open.
/// </summary>
bool IsOpen { get; set; }
}
Naming Convention:
I[PanelName]Panel or I[PanelName][PanelName]Panel or [PanelName]ISceneHierarchyPanel, IConsolePanel, ITileMapPanelLocation: Editor/Panels/
Guidelines:
EditorUIConstants for sizing, spacing, colors (Drawers handle this automatically)Panel Template:
namespace Editor.Panels;
using Editor.UI;
using Editor.UI.Drawers;
using Editor.UI.Elements;
using Editor.UI.FieldEditors;
using ImGuiNET;
using Editor.Managers;
/// <summary>
/// Panel for managing and displaying [functionality].
/// </summary>
public class MyNewPanel(
ISceneManager sceneManager,
IProjectManager projectManager) : IMyNewPanel
{
// Panel state
private bool _isOpen = true;
private bool _showConfirmModal = false;
private string _filterText = string.Empty;
private int _selectedIndex = -1;
// Input buffers (use EditorUIConstants for sizes)
private readonly byte[] _nameBuffer = new byte[EditorUIConstants.MaxNameLength];
/// <inheritdoc/>
public bool IsOpen
{
get => _isOpen;
set => _isOpen = value;
}
/// <inheritdoc/>
public void OnImGuiRender()
{
if (!_isOpen)
return;
ImGuiWindowFlags flags = ImGuiWindowFlags.None;
if (ImGui.Begin("My Panel", ref _isOpen, flags))
{
DrawToolbar();
LayoutDrawer.DrawSeparator();
DrawContent();
}
ImGui.End();
// Render modals (must be outside Begin/End)
ModalDrawer.RenderConfirmationModal(
title: "Confirm Action",
showModal: ref _showConfirmModal,
message: "Are you sure?",
onOk: () => PerformAction());
}
private void DrawToolbar()
{
// Use ButtonDrawer for styled buttons
if (ButtonDrawer.DrawButton("Save", ButtonDrawer.ButtonType.Primary))
{
SaveData();
}
ImGui.SameLine();
if (ButtonDrawer.DrawButton("Clear", ButtonDrawer.ButtonType.Secondary))
{
_showConfirmModal = true;
}
}
private void DrawContent()
{
// Use LayoutDrawer for spacing
LayoutDrawer.DrawSpacing(EditorUIConstants.StandardPadding);
// Panel-specific content here
}
private void SaveData()
{
// Implementation
}
private void PerformAction()
{
// Implementation
}
}
Location: Editor/Program.cs
Registration Pattern:
private static void ConfigureServices(Container container)
{
// ... existing registrations
// Register new panel
container.Register<IMyNewPanel, MyNewPanel>(Reuse.Singleton);
}
Guidelines:
Location: Editor/EditorLayer.cs
Constructor Injection:
public class EditorLayer(
// ... existing parameters
ISceneHierarchyPanel sceneHierarchyPanel,
IPropertiesPanel propertiesPanel,
IConsolePanel consolePanel,
IMyNewPanel myNewPanel) : Layer
{
public override void OnImGuiRender()
{
// ... existing panel renders
sceneHierarchyPanel.OnImGuiRender();
propertiesPanel.OnImGuiRender();
consolePanel.OnImGuiRender();
myNewPanel.OnImGuiRender();
}
}
Location: Editor/EditorLayer.cs (in menu bar rendering)
Add Panel Toggle Menu:
private void DrawMenuBar()
{
if (ImGui.BeginMenu("Window"))
{
// Existing menu items
if (ImGui.MenuItem("Scene Hierarchy", "", _sceneHierarchyPanel.IsOpen))
_sceneHierarchyPanel.IsOpen = !_sceneHierarchyPanel.IsOpen;
if (ImGui.MenuItem("Properties", "", _propertiesPanel.IsOpen))
_propertiesPanel.IsOpen = !_propertiesPanel.IsOpen;
// New panel menu item
if (ImGui.MenuItem("My Panel", "", _myNewPanel.IsOpen))
_myNewPanel.IsOpen = !_myNewPanel.IsOpen;
ImGui.EndMenu();
}
}
Keyboard Shortcut (optional):
private void HandleShortcuts()
{
// Existing shortcuts
// Ctrl+Shift+M to toggle My Panel
if (ImGui.IsKeyDown(ImGuiKey.LeftCtrl) &&
ImGui.IsKeyDown(ImGuiKey.LeftShift) &&
ImGui.IsKeyPressed(ImGuiKey.M))
{
_myNewPanel.IsOpen = !_myNewPanel.IsOpen;
}
}
CRITICAL: All panels MUST use the UI infrastructure - never write manual ImGui code for patterns covered by Drawers, Elements, or FieldEditors!
Common UI Components:
ButtonDrawer.DrawButton() with button types (Primary, Secondary, Danger, Success)ModalDrawer.RenderConfirmationModal() for all confirmation dialogsTableDrawer.BeginTable() / TableDrawer.DrawRow() / TableDrawer.EndTable()LayoutDrawer.DrawSpacing() / LayoutDrawer.DrawSeparator()TextureDropTarget.Draw(), AudioDropTarget.Draw(), etc.Example: Minimal Panel with UI Infrastructure
using Editor.UI.Drawers;
using Editor.UI.Elements;
public class MyPanel : IMyPanel
{
private bool _showConfirmModal;
private float _speed = 1.0f;
private string _iconPath = "";
public void OnImGuiRender()
{
if (!_isOpen) return;
if (ImGui.Begin("My Panel", ref _isOpen))
{
// Use ButtonDrawer for styled buttons
if (ButtonDrawer.DrawButton("Save", ButtonDrawer.ButtonType.Primary))
{
Save();
}
LayoutDrawer.DrawSeparator();
// Use ImGui for properties
ImGui.DragFloat("Speed", ref _speed, 0.1f);
// Use drag-drop targets for assets
TextureDropTarget.Draw("Icon", _iconPath, (newPath) => _iconPath = newPath);
}
ImGui.End();
// Modals outside Begin/End
ModalDrawer.RenderConfirmationModal(
title: "Confirm",
showModal: ref _showConfirmModal,
message: "Are you sure?",
onOk: () => PerformAction());
}
}
Key Rules:
ImGui.Button() - use ButtonDrawer.DrawButton()ImGui.BeginPopupModal() - use ModalDrawer.RenderConfirmationModal()ImGui.DragFloat(), ImGui.InputText(), etc. for property editing (IFieldEditor is for script inspector only)TextureDropTarget.Draw(), etc.public void OnImGuiRender()
{
if (!_isOpen)
return;
ImGuiWindowFlags flags = ImGuiWindowFlags.None;
if (ImGui.Begin("My Panel", ref _isOpen, flags))
{
// Panel is dockable by default in ImGui
DrawContent();
}
ImGui.End();
}
private void DrawContent()
{
if (ImGui.BeginTabBar("##MyTabs"))
{
if (ImGui.BeginTabItem("Tab 1"))
{
DrawTab1Content();
ImGui.EndTabItem();
}
if (ImGui.BeginTabItem("Tab 2"))
{
DrawTab2Content();
ImGui.EndTabItem();
}
ImGui.EndTabBar();
}
}
private void DrawItem(string itemName)
{
ImGui.Selectable(itemName);
if (ImGui.BeginPopupContextItem($"##{itemName}Context"))
{
if (ImGui.MenuItem("Edit"))
EditItem(itemName);
if (ImGui.MenuItem("Delete"))
DeleteItem(itemName);
ImGui.EndPopup();
}
}
ALWAYS use ModalDrawer instead of manual ImGui popups.
using Editor.UI.Drawers;
private bool _showDeleteConfirmation = false;
private void DrawContent()
{
// Trigger modal with styled button
if (ButtonDrawer.DrawButton("Delete", ButtonDrawer.ButtonType.Danger))
_showDeleteConfirmation = true;
// Render modal using ModalDrawer
ModalDrawer.RenderConfirmationModal(
title: "Delete Confirmation",
showModal: ref _showDeleteConfirmation,
message: "Are you sure you want to delete?",
onOk: () => PerformDelete());
}
The editor has 17 panels in Editor/Panels/ and Editor/Features/. Reference these for implementation patterns:
See implementations in Editor/Panels/ for UI consistency patterns.
// Scene management
private readonly ISceneManager _sceneManager;
// Project management
private readonly IProjectManager _projectManager;
// Factories
private readonly ITextureFactory _textureFactory;
private readonly IShaderFactory _shaderFactory;
private readonly IAudioClipFactory _audioClipFactory;
// Systems
private readonly SystemManager _systemManager;
// Other panels (for cross-panel communication)
private readonly ISceneHierarchyPanel _sceneHierarchyPanel;
public class MyPanel(
ISceneManager sceneManager,
IProjectManager projectManager,
ITextureFactory textureFactory) : IMyPanel
{
// Dependencies are automatically available as private readonly fields
// No null validation needed - non-nullable reference types handle this
}
// ❌ WRONG - Do not create static singletons
public static class MyPanelManager
{
public static MyPanelManager Instance { get; } = new();
}
// ✅ CORRECT - Use DI container registration
container.Register<IMyPanel, MyPanel>(Reuse.Singleton);
EditorUIConstants used throughout (no magic numbers)Program.cs DI containerEditorLayerStructured design dialogue that validates ideas before implementation begins.
Comprehensive design intelligence for web and mobile UI/UX across 10 technology stacks.
Comprehensive implementation plans for multi-step tasks, breaking down specs into bite-sized, testable steps.
Introduction to the obra skills system with mandatory skill invocation rules and best practices.
Execute a written implementation plan with critical review and task checkpoints.
Delegate independent tasks to specialized agents working concurrently with isolated context.
Isolated git worktrees with smart directory selection and safety verification.
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
Plan searchable and shareable content that drives traffic, builds authority, and generates leads.
README-first repository scanner that extracts commands and classifies reproduction candidates without executing them.
Brainstorm and prioritize marketing strategies tailored to your SaaS stage, budget, and goals.
Plan and optimize your website's page hierarchy, navigation, URL structure, and internal linking.
The world's fastest calendar for remote work
Capture, organize, and utilize your knowledge effortlessly.
Instant Summaries of Audio & Video Interviews with AnySummary
Transform PDFs into engaging mind maps.
Chat with any PDF instantly
Create an optimal daily plan using your voice
A productivity platform to centralize organizational knowledge and workflows with contextual AI assistance.
AskYourPDF Pricing Plans: Tailored to Your Needs