Skip to content

Commit 6deae57

Browse files
andreakarashoclaude
andcommitted
Add ImGui-style BeginMenuBar/BeginMenu API with hover-to-switch behavior
BeginMenu now detects context: inside BeginMenuBar it renders a top-bar button with click-to-toggle and hover-to-switch (when a sibling menu is already open); inside a popup it renders a submenu with hover delay. Also strips ## ID suffixes from window/panel display titles and flags editor dialog windows (About, Build Settings, Preferences) as NoDocking. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 90698e6 commit 6deae57

2 files changed

Lines changed: 195 additions & 49 deletions

File tree

src/Clay.GameEditor/Program.cs

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -312,21 +312,9 @@ void RenderMenuBar()
312312
FontSize = 13
313313
};
314314

315-
if (ClayUI.Button("File##menu", menuBtnStyle)) ClayUI.OpenPopup("FileMenu");
316-
if (ClayUI.Button("Edit##menu", menuBtnStyle)) ClayUI.OpenPopup("EditMenu");
317-
if (ClayUI.Button("Assets##menu", menuBtnStyle)) ClayUI.OpenPopup("AssetsMenu");
318-
if (ClayUI.Button("GameObject##menu", menuBtnStyle)) ClayUI.OpenPopup("GameObjectMenu");
319-
if (ClayUI.Button("Component##menu", menuBtnStyle)) ClayUI.OpenPopup("ComponentMenu");
320-
if (ClayUI.Button("Window##menu", menuBtnStyle)) ClayUI.OpenPopup("WindowMenu");
321-
if (ClayUI.Button("Help##menu", menuBtnStyle)) ClayUI.OpenPopup("HelpMenu");
315+
ClayUI.BeginMenuBar(menuBtnStyle);
322316

323-
ClayUI.Spacer();
324-
325-
// Layout selector
326-
ClayUI.Label("Layout: Default", new LabelStyle { TextColor = colTextDim, FontSize = 12 });
327-
328-
// File menu
329-
if (ClayUI.BeginPopup("FileMenu"))
317+
if (ClayUI.BeginMenu("File"))
330318
{
331319
if (ClayUI.MenuItem("New Scene")) Console.WriteLine("File > New Scene");
332320
if (ClayUI.MenuItem("Open Scene...")) Console.WriteLine("File > Open Scene");
@@ -340,11 +328,10 @@ void RenderMenuBar()
340328
if (ClayUI.MenuItem("Build & Run")) Console.WriteLine("File > Build & Run");
341329
ClayUI.MenuSeparator();
342330
if (ClayUI.MenuItem("Exit")) Environment.Exit(0);
343-
ClayUI.EndPopup();
331+
ClayUI.EndMenu();
344332
}
345333

346-
// Edit menu
347-
if (ClayUI.BeginPopup("EditMenu"))
334+
if (ClayUI.BeginMenu("Edit"))
348335
{
349336
if (ClayUI.MenuItem("Undo")) Console.WriteLine("Edit > Undo");
350337
if (ClayUI.MenuItem("Redo")) Console.WriteLine("Edit > Redo");
@@ -358,11 +345,10 @@ void RenderMenuBar()
358345
if (ClayUI.MenuItem("Select All")) Console.WriteLine("Edit > Select All");
359346
ClayUI.MenuSeparator();
360347
if (ClayUI.MenuItem("Preferences...")) preferencesWindowOpen = true;
361-
ClayUI.EndPopup();
348+
ClayUI.EndMenu();
362349
}
363350

364-
// Assets menu
365-
if (ClayUI.BeginPopup("AssetsMenu"))
351+
if (ClayUI.BeginMenu("Assets"))
366352
{
367353
if (ClayUI.BeginMenu("Create"))
368354
{
@@ -377,11 +363,10 @@ void RenderMenuBar()
377363
ClayUI.MenuSeparator();
378364
if (ClayUI.MenuItem("Refresh")) Console.WriteLine("Assets > Refresh");
379365
if (ClayUI.MenuItem("Reimport All")) Console.WriteLine("Assets > Reimport All");
380-
ClayUI.EndPopup();
366+
ClayUI.EndMenu();
381367
}
382368

383-
// GameObject menu
384-
if (ClayUI.BeginPopup("GameObjectMenu"))
369+
if (ClayUI.BeginMenu("GameObject"))
385370
{
386371
if (ClayUI.MenuItem("Create Empty")) Console.WriteLine("GameObject > Create Empty");
387372
if (ClayUI.BeginMenu("3D Object"))
@@ -407,11 +392,10 @@ void RenderMenuBar()
407392
ClayUI.EndMenu();
408393
}
409394
if (ClayUI.MenuItem("Camera")) Console.WriteLine("GameObject > Camera");
410-
ClayUI.EndPopup();
395+
ClayUI.EndMenu();
411396
}
412397

413-
// Component menu
414-
if (ClayUI.BeginPopup("ComponentMenu"))
398+
if (ClayUI.BeginMenu("Component"))
415399
{
416400
if (ClayUI.BeginMenu("Physics"))
417401
{
@@ -435,29 +419,34 @@ void RenderMenuBar()
435419
ClayUI.EndMenu();
436420
}
437421
if (ClayUI.MenuItem("New Script...")) Console.WriteLine("Component > New Script");
438-
ClayUI.EndPopup();
422+
ClayUI.EndMenu();
439423
}
440424

441-
// Window menu
442-
if (ClayUI.BeginPopup("WindowMenu"))
425+
if (ClayUI.BeginMenu("Window"))
443426
{
444427
if (ClayUI.MenuItem(showConsole ? "Console [*]" : "Console")) showConsole = !showConsole;
445428
if (ClayUI.MenuItem(showAssetBrowser ? "Asset Browser [*]" : "Asset Browser")) showAssetBrowser = !showAssetBrowser;
446429
ClayUI.MenuSeparator();
447430
if (ClayUI.MenuItem(debugWindowOpen ? "Debug Inspector [*]" : "Debug Inspector (F12)")) debugWindowOpen = !debugWindowOpen;
448-
ClayUI.EndPopup();
431+
ClayUI.EndMenu();
449432
}
450433

451-
// Help menu
452-
if (ClayUI.BeginPopup("HelpMenu"))
434+
if (ClayUI.BeginMenu("Help"))
453435
{
454436
if (ClayUI.MenuItem("Documentation")) Console.WriteLine("Help > Docs");
455437
if (ClayUI.MenuItem("API Reference")) Console.WriteLine("Help > API");
456438
ClayUI.MenuSeparator();
457439
if (ClayUI.MenuItem("About")) aboutWindowOpen = true;
458-
ClayUI.EndPopup();
440+
ClayUI.EndMenu();
459441
}
460442

443+
ClayUI.EndMenuBar();
444+
445+
ClayUI.Spacer();
446+
447+
// Layout selector
448+
ClayUI.Label("Layout: Default", new LabelStyle { TextColor = colTextDim, FontSize = 12 });
449+
461450
ClayUI.EndHorizontal();
462451
}
463452

@@ -1038,7 +1027,8 @@ void RenderFloatingWindows()
10381027
if (aboutWindowOpen)
10391028
{
10401029
if (ClayUI.BeginWindow("About##editor", ref aboutWindowOpen,
1041-
defaultPosition: new Vector2(400, 250), defaultSize: new Vector2(360, 200)))
1030+
defaultPosition: new Vector2(400, 250), defaultSize: new Vector2(360, 200),
1031+
flags: WindowFlags.NoDocking))
10421032
{
10431033
ClayUI.Heading("Raylib Game Engine Editor", new HeadingStyle { TextColor = colAccent, FontSize = 16 });
10441034
ClayUI.Space(8);
@@ -1058,7 +1048,8 @@ void RenderFloatingWindows()
10581048
if (buildWindowOpen)
10591049
{
10601050
if (ClayUI.BeginWindow("Build Settings##editor", ref buildWindowOpen,
1061-
defaultPosition: new Vector2(300, 150), defaultSize: new Vector2(420, 320)))
1051+
defaultPosition: new Vector2(300, 150), defaultSize: new Vector2(420, 320),
1052+
flags: WindowFlags.NoDocking))
10621053
{
10631054
ClayUI.Combo("Platform", ref buildPlatformIndex, buildPlatforms);
10641055
ClayUI.Space(8);
@@ -1088,7 +1079,8 @@ void RenderFloatingWindows()
10881079
if (preferencesWindowOpen)
10891080
{
10901081
if (ClayUI.BeginWindow("Preferences##editor", ref preferencesWindowOpen,
1091-
defaultPosition: new Vector2(350, 180), defaultSize: new Vector2(380, 280)))
1082+
defaultPosition: new Vector2(350, 180), defaultSize: new Vector2(380, 280),
1083+
flags: WindowFlags.NoDocking))
10921084
{
10931085
ClayUI.Heading("Editor", new HeadingStyle { TextColor = colTextBright, FontSize = 14 });
10941086
ClayUI.Space(4);

0 commit comments

Comments
 (0)