Skip to content

Instantly share code, notes, and snippets.

@JettMonstersGoBoom
Last active August 2, 2024 00:58
Show Gist options
  • Save JettMonstersGoBoom/4ea50df7ba3bfef1d5d8f027fcc4f747 to your computer and use it in GitHub Desktop.
Save JettMonstersGoBoom/4ea50df7ba3bfef1d5d8f027fcc4f747 to your computer and use it in GitHub Desktop.
menu bar hack for raygui.
// note W is width of button, not bar
// note H is height of button AND bar
typedef struct
{
const char *string;
int uID;
void *data;
} MenuBarEntry;
#ifdef RAYGUI_MENUBAR_IMPLEMENTATION
// Button control, returns true when clicked
static int FocusedGuiRect(Rectangle bounds)
{
int result = 0;
GuiState state = GuiGetState();
if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
{
Vector2 mousePoint = GetMousePosition();
// Check button state
if (CheckCollisionPointRec(mousePoint, bounds))
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
state = STATE_PRESSED;
else
state = STATE_FOCUSED;
}
}
return (state);
}
int GuiShowMenu(MenuBarEntry **menu,int w,int h)
{
int Align = GuiGetStyle(BUTTON,TEXT_ALIGNMENT);
GuiStatusBar((Rectangle){0,0,GetScreenWidth(),h},"");
GuiSetStyle(BUTTON, TEXT_ALIGNMENT,TEXT_ALIGN_LEFT);
int ret = 0;
bool isClosed = false;
bool isFocused = false;
int isOpen = -1;
// find out who's open
for (int m=0;menu[m]!=NULL;m++)
{
MenuBarEntry *item = menu[m];
if (item->uID!=0)
isOpen = m;
}
// for all menus
for (int m=0;menu[m]!=NULL;m++)
{
Rectangle rect=(Rectangle){m*w,0,w,h};
MenuBarEntry *item = menu[m];
// first item in menu is the top level button string
// tell the system we're focused on something
if (FocusedGuiRect(rect)) isFocused=true;
// put the Menu title button up
if (GuiButton(rect,TextFormat(" %s",item->string)))
{
// if we hit the button, we toggle the menu on/off
item->uID=!item->uID;
// set is closed if the top menu is switched off.
if (item->uID==0) isClosed=true;
}
// if it's open
if (item->uID!=0)
{
// check if it's the one we had last time
if ((m!=isOpen) && (isOpen!=-1))
menu[isOpen]->uID=0;
// add the other entries
for (int q=1;item[q].string!=NULL;q++)
{
// step down 1 slot
rect.y+=rect.height;
// set if we're focused
if (FocusedGuiRect(rect))
isFocused=true;
// handle button press
if (GuiButton(rect,item[q].string))
{
item->uID=false;
isClosed=true;
ret = item[q].uID;
}
}
}
}
// if we're not focused and left click, close the menu
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && (isFocused==false))
isClosed = true;
// turn everything off
if (isClosed==true)
{
for (int m=0;menu[m]!=NULL;m++)
{
menu[m]->uID=false;
}
}
// restore alignment
GuiSetStyle(BUTTON, TEXT_ALIGNMENT,Align);
return ret;
}
#else
// note W is width of button, not bar
// note H is height of button AND bar
int GuiShowMenu(MenuBarEntry **menu,int w,int h);
#endif
#include <stdio.h>
#include "raylib.h"
#include "rlgl.h"
#include "raymath.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#define RAYGUI_MENUBAR_IMPLEMENTATION
#include "raygui_menubar.h"
enum
{
MENU_OPEN = 0x1000,
MENU_SAVE,
MENU_OPEN_PROJECT,
MENU_SAVE_PROJECT,
MENU_UNDO,
MENU_REDO,
MENU_CUT,
MENU_COPY,
MENU_PASTE,
MENU_EXIT
};
// first item is the menu header, and it's uID should be 0 ( closed )
MenuBarEntry file_menu[] =
{
{"File",0},
{"#05# Open",MENU_OPEN},
{"#06# Save",MENU_SAVE},
{"#01# Open Project",MENU_OPEN_PROJECT},
{"#02# Save Project",MENU_SAVE_PROJECT},
{"#113# Exit",MENU_EXIT},
{NULL},
};
MenuBarEntry edit_menu[] =
{
{"Edit",0},
{"#56#Undo",MENU_UNDO},
{"#57#Redo",MENU_REDO},
{"#17#Cut",MENU_CUT},
{"#16#Copy",MENU_COPY},
{"#18#Paste",MENU_PASTE},
{NULL},
};
MenuBarEntry demo_menu[] =
{
{"Demo",0},
{"#56#Stuff",MENU_UNDO},
{"#57#Things",MENU_REDO},
{NULL},
};
MenuBarEntry *MainMenu[]=
{
file_menu,
edit_menu,
demo_menu,
NULL
};
bool exitWindow = false;
void HandleMenuBar();
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 1280;
int screenHeight = 720;
InitWindow(screenWidth, screenHeight, "raylib menu template");
SetWindowState(FLAG_WINDOW_RESIZABLE);
SetTargetFPS(60);
exitWindow = false;
// load font
const int textSize = 24;
GuiSetStyle(DEFAULT, TEXT_SIZE, textSize);
// Main game loop
while (!exitWindow) // Detect window close button or ESC key
{
ClearBackground(BLACK);
exitWindow = WindowShouldClose();
BeginDrawing();
HandleMenuBar();
EndDrawing();
}
// UnloadFont(fontTtf);
CloseWindow(); // Close window and OpenGL context
return 0;
}
void HandleMenuBar()
{
int bwidth = (GuiGetStyle(DEFAULT, TEXT_SIZE) * 8) + 4;
int bheight = GuiGetStyle(DEFAULT, TEXT_SIZE) + 4;
int ret = GuiShowMenu(MainMenu,bwidth,bheight);
if (ret!=0)
{
switch(ret)
{
case MENU_EXIT:
{
exitWindow=true;
break;
}
case MENU_OPEN:
{
printf("Open File");
break;
}
}
}
}
const char *Menu[]=
{
"File:#05# Open:#06# Save:#01# Open PRJ:#02# Save PRJ:#113#Exit",
"Edit:#56#Undo:#57#Redo:#17#Cut:#16#Copy:#18#Paste",
"Demo:#56#Stuff:#57#Things",
NULL
};
static int FocusedGuiRect(Rectangle bounds)
{
int result = 0;
GuiState state = GuiGetState();
if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
{
Vector2 mousePoint = GetMousePosition();
// Check button state
if (CheckCollisionPointRec(mousePoint, bounds))
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
state = STATE_PRESSED;
else
state = STATE_FOCUSED;
}
}
return (state);
}
// returns 16 bit number
// 11111111-------- menu index
// --------11111111 submenu index
// 0x0103 menu 1, subutem 3
unsigned short GuiShowMenuAscii(char **menu,int w,int h)
{
static int GuiShowMenuAsciiOpen = -1;
bool isFocused = false;
unsigned short ret = 0;
// full bar across
GuiStatusBar((Rectangle){0,0,GetScreenWidth(),h},"");
for (int m=0;menu[m]!=NULL;m++)
{
Rectangle rect=(Rectangle){m*w,0,w,h};
char *ent = strdup(menu[m]);
char *tok = strtok(ent,":");
if (FocusedGuiRect(rect)) isFocused=true;
if (GuiButton(rect,TextFormat(" %s",tok))) GuiShowMenuAsciiOpen = m;
int subItem=0;
if (GuiShowMenuAsciiOpen==m)
{
while(tok!=NULL)
{
rect.y+=h;
tok = strtok(NULL,":");
subItem++;
if (tok!=NULL)
{
if (FocusedGuiRect(rect)) isFocused=true;
if (GuiButton(rect,tok))
{
ret = (m<<8) | subItem;
}
}
}
}
free(ent);
}
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && (isFocused==false))
GuiShowMenuAsciiOpen = -1;
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment