LibGame v0.4.0
The LG Game Engine - Copyright (C) 2024-2026 ETMSoftware
Loading...
Searching...
No Matches
lg_wins.c File Reference

Functions

void lg_info_win (LG_Win_Style *style, const char *format,...)
 
void lg_info_win_no_block (zboolean with_frame, zboolean swap_fb, const char *text)
 
void lg_error_win (LG_Win_Style *style, zboolean log, const char *format,...)
 
int lg_question_win (LG_Win_Style *style, const char *format,...)
 
char * lg_entry_win (LG_Win_Style *style, int x, int y, const char *label)
 
int lg_win_open_centered (LG_Window *win, uint32_t v_shift)
 
LG_Window lg_win (const char *text, LG_Color_u text_color, LG_Color_u bg_color, zboolean with_frame, LG_Color_u border_color, TTF_Font *font, int index, LG_Color_u hightlight_text_color, LG_Color_u hightlight_bg_color)
 
LG_MenuWinParamslg_get_menu_wins_params ()
 
int lg_menu_win (const char *text, LG_Color_u text_c, LG_Color_u bg_c, LG_Color_u h_text_c, LG_Color_u h_bg_c, TTF_Font *font, int starting_index, int x, int y)
 
char * lg_action_func_to_str (LG_ActionFunc actions_funcs[])
 
char * lg_action_func_to_str2 (LG_ActionFunc2 actions_funcs[])
 
void lg_scrollable_win (LG_Win_Style *style, int display_n_lines, const char *text)
 
void lg_win_show_annoying_errors ()
 
void lg_win_no_annoying_errors ()
 
int lg_win_open (LG_Window *win, int x, int y, uint32_t v_shift)
 
void lg_win_free_tex (LG_Window *win)
 
zboolean is_lg_win (LG_Window *win)
 
Rec2Di lg_get_centered_win_rec (LG_Window *win)
 
int lg_win_get_w (LG_Window *win)
 
int lg_win_get_h (LG_Window *win)
 
int lg_text_get_n_lines (const char *text)
 
char * lg_text_format_for_win (const char *text, TTF_Font *font)
 
char * lg_wrap_lines (const char *text, TTF_Font *font, int max_width)
 

Variables

static LG_Color_u fully_transparent_c = (LG_Color_u){0, 0, 0, 0}
 
static zboolean no_annoying_errors = FALSE
 

Detailed Description

 === GUI windows implementation ===

 You may use these helper macros:

 - WITH_FRAME / NO_FRAME
 - BLOCK / NO_BLOCK
 - SWAP_FB / NO_SWAP

Function Documentation

◆ lg_info_win()

void lg_info_win ( LG_Win_Style style,
const char *  format,
  ... 
)

Create and open a styled centered INFO LG_Window

If only one line of text, line is surrounded by newlines, ie \nLINE\n\n

=== WARNING: Also swap framebuffer ===

=== WARNING2: This one uses WAIT_FOR_PRESS_OR_CLICK_OR_TOUCH === Also don't output "Press any key ..."

You should always clear or render to bg just before calling this func (with lg_clear_bg() or lg_read_and_render_screen_back() / lg_read_screen() / lg_render_screen_back())

Parameters
stylePointer to a LG_Win_Style instance
formatFormat
...Extra args

◆ lg_info_win_no_block()

void lg_info_win_no_block ( zboolean  with_frame,
zboolean  swap_fb,
const char *  text 
)

Create and open a non-blocking INFO LG_Window

Window at screen bottom, horiz. centered - free win->tex

=== WARNING: May swap framebuffer ===

Use default font 'dejavu_sans_bold_18' - should be a param

TODO: really need to make a stylised variadic version

(Params are self-explanatory)

Parameters
with_frame
swap_fb
textA NULL-terminated string with lines separated by newlines ('\n')

◆ lg_error_win()

void lg_error_win ( LG_Win_Style style,
zboolean  log,
const char *  format,
  ... 
)

Create and open a styled centered ERROR LG_Window

If only one line of text, line is surrounded by newlines, ie \nLINE\n\n

=== WARNING: Also swap framebuffer ===

You should always clear or render to bg just before calling this func (with lg_clear_bg() or lg_read_and_render_screen_back() / lg_read_screen() / lg_render_screen_back())

Parameters
stylePointer to a LG_Win_Style instance
logIf set to TRUE, also output to STR_ERR
formatFormat
...Extra args

◆ lg_question_win()

int lg_question_win ( LG_Win_Style style,
const char *  format,
  ... 
)

Create and open a styled centered QUESTION LG_Window

On Android: left tap = NO / right tap = YES

Text is always surrounded by newlines, ie \nTEXT\n\n

=== WARNING: Also swap framebuffer ===

TODO: Which font size on Android ?

TODO2: This func use a dirty hack to support multiple (up to 4) ending newlines - should implement sth more robust

You should always clear or render to bg just before calling this func (with lg_clear_bg() or lg_read_and_render_screen_back() / lg_read_screen() / lg_render_screen_back())

Parameters
stylePointer to a LG_Win_Style instance
formatFormat
...Extra args
Returns
YES or NO, or -1 on error

◆ lg_entry_win()

char * lg_entry_win ( LG_Win_Style style,
int  x,
int  y,
const char *  label 
)

Create and open a styled ENTRY LG_Window

(-1, -1) for centered win, same colors as lg_question_win()

If not NULL (<esc> pressed), returned str must be freed

=== WARNING: Also swap framebuffer ===

You should always clear or render to bg just before calling this func (with lg_clear_bg() or lg_read_and_render_screen_back() / lg_read_screen() / lg_render_screen_back())

(Most params are self-explanatory)

Parameters
stylePointer to a LG_Win_Style instance
x
y
label
Returns
Entered text, NULL on error

◆ lg_win_open_centered()

int lg_win_open_centered ( LG_Window win,
uint32_t  v_shift 
)

Open a LG_Window at screen center

Parameters
winA LG_Window instance
v_shift<Not sure yet>
Returns
LG_OK if OK

◆ lg_win()

LG_Window lg_win ( const char *  text,
LG_Color_u  text_color,
LG_Color_u  bg_color,
zboolean  with_frame,
LG_Color_u  border_color,
TTF_Font *  font,
int  index,
LG_Color_u  hightlight_text_color,
LG_Color_u  hightlight_bg_color 
)

Create a new LG_Window

|------------win_rec-------------|
| |--------padding_rec---------| |
| | |-------layout_rec-------| | |
| | | layout_texture | | |
| | |------------------------| | |
| |----------------------------| |
|--------------------------------|
win_rec = visible_area

WARNING: For frameless wins, the background/border colors are still used, so you MUST set them (ie, DO use either a fully/partially transparent color or an opaque color)

For instance, use lg_color_u(0, 0, 0, 0) or UNUSED_LG_COLOR_U for a fully transparent bg

Max lines num inside window is LG_WIN_N_LINES_MAX, defined in lg_wins.h

H_PADDING, V_PADDING, and BORDER_WIDTH are also defined in lg_wins.h

Parameters
textA NULL-terminated string with lines separated by newlines ('\n')
text_colorText color as a LG_Color_u
with_frameCreate a window with a frame, ie add H_PADDING, V_PADDING, and BORDER_WIDTH to win dims
bg_colorBackgroung color as a LG_Color_u
border_colorBorder color as a LG_Color_u
fontPointer to a TTF_Font
indexIf in range [0, LG_WIN_N_LINES_MAX - 1], will (eventually) hightlight (index + 1)th line
hightlight_text_colorHighlighted line text color as a LG_Color_u
hightlight_bg_colorHighlighted line background color as a LG_Color_u
Returns
A new LG_Window, with id set to 0 -> OK / -1 -> invalid win (TODO: need to find sth better)

◆ lg_get_menu_wins_params()

LG_MenuWinParams * lg_get_menu_wins_params ( )

Get pointer to global params for all lg_menu_win() instances

Returns
A pointer to static global LG_MenuWinParams

◆ lg_menu_win()

int lg_menu_win ( const char *  text,
LG_Color_u  text_c,
LG_Color_u  bg_c,
LG_Color_u  h_text_c,
LG_Color_u  h_bg_c,
TTF_Font *  font,
int  starting_index,
int  x,
int  y 
)

Create and open a LG_Window with a menu (line highlighting enabled)

Take a string of lines separated by newlines ('\n')

Each line must be short enough as to not trigger wrapping which would break functionnality, as the number of lines is 'guessed' from the number of newlines in the string

Return the index (in range [0, n_lines - 1]) of the selected line (ENTER / left-click) or one of these negative values:

  • MENUWIN_KEY_ESC (-1) for ESC - no line was selected
  • MENUWIN_KEY_LEFT (-2) for LEFT ARROW
  • MENUWIN_KEY_RIGHT (-3) for RIGHT ARROW
  • MENUWIN_KEY_SPACE (-4) for SPACE

Set: x = -1, y = -1 for a centered window

You can use lg_get_menu_wins_params() to get and set other params

Usage example from LibGame scene_editor/main_menu.c:

// === CHECK THIS CODE IS UP TO DATE ===
static int about()
{
char *tmp = l_str_new3(
" === %s v%s === \n\n %s \n"
" %s is part of %s \n\n"
" %s version: %s \n"
" %s \n\n"
" Build, load, edit, save %s scenes \n"
" Import scene graphs, meshes, terrains, lights, shaders, ...",
APP_NAME, APP_V_NUM, APP_COPYRIGHT_STR,
APP_NAME, LIBGAME_NAME,
LIBGAME_NAME, LIBGAME_V_NUM,
LIBGAME_COPYRIGHT_STR,
LIBGAME_NAME
);
info_win(tmp);
free3(tmp);
return MENUWIN_CLOSE;
}
// This is now called for every frame - REAL IMMEDIATE MODE
int pick_action(Level *lev2, int *n_menu, int x, int y)
{
env = lg_get_game_env();
exit_status = MENUWIN_CONTINUE;
lev = lev2;
static int i = 0, n_menu_bak = 0;
int j;
LG_ActionFunc2 files_actions_funcs[] = {
{"New scene <F6>", &new_scene2},
{"Load scene <F7>", &load_scene},
{"load scene from TXT file", &load_scene_from_txt_file0},
{"Save scene <F8>", &save_scene},
{"---", &do_nothing},
{"Quit <esc>", &quit},
{NULL, NULL}};
LG_ActionFunc2 nodes_actions_funcs[] = {
{"Import mesh (OBJ/FBX/BMESH) <F9>", &new_node_from_mesh0},
{"Export selected node mesh (BMESH)", &not_implemented_yet},
{"Copy selected node <F10>", &copy_selected_node_at_center},
{"Delete selected node <F11>", &delete_selected_node2},
{NULL, NULL}};
LG_ActionFunc2 cam_actions_funcs[] = {
{"Next predef cam position <F3>", &next_predef_cam_pos},
{"Orbit cam <F4>", &orbit_cam2},
{"Slow motion mode <F2>", &slow_motion},
{"Toggle zoom in effect #1 <F12>", &zoom_in_effect1},
{"Toggle zoom in effect #2 (same so far)", &zoom_in_effect2},
{"Reset cam <enter>", &reset_cam2},
{NULL, NULL}};
LG_ActionFunc2 view_actions_funcs[] = {
{"Grid type", &do_nothing},
{" GL lines", &gl_lines_grid},
{" Mesh lines", &meshlines_grid},
{" Geom shaders", &geom_shaders_grid},
{" Grid -> half_size +", &inc_grid_half_size},
{" Grid -> half_size -", &dec_grid_half_size},
{" Grid -> scaling +", &inc_grid_scaling},
{" Grid -> scaling -", &dec_grid_scaling},
{" None", &no_grid},
{"---", &do_nothing},
{"Show arrows", &show_arrows},
{NULL, NULL}};
LG_ActionFunc2 light_actions_funcs[] = {
{"Toggle light type", &toggle_light_type},
{"Change light dir X", &change_light_dir_x},
{"Change light dir Y", &change_light_dir_y},
{"Luminosity +", &inc_luminosity},
{"Luminosity -", &dec_luminosity},
{NULL, NULL}};
LG_ActionFunc2 info_actions_funcs[] = {
{"Help win <F1>", &toggle_help_win},
{"nodes_ntos[] info <F5>", &output_nodes_ntos},
{"Scene graph", &output_scenegraph},
{"Selected node mesh info", &selected_mesh_info},
{"Debug info", &debug_info},
{"---", &do_nothing},
{"About", &about},
{NULL, NULL}};
LG_ActionFunc2 *actions_funcs_array[] = {
files_actions_funcs,
nodes_actions_funcs,
cam_actions_funcs,
view_actions_funcs,
light_actions_funcs,
info_actions_funcs
};
int size = (int)(sizeof(actions_funcs_array) / sizeof(LG_ActionFunc2 *));
if (!IN_RANGE_i_(*n_menu, 0, size - 1)) {
INFO_ERR("*n_menu must be in range [0, %d]\n", size - 1)
*n_menu = 0;
}
char *str_array[size];
for (j = 0; j < size; j++) {
if ((str_array[j] = lg_action_func_to_str2(&actions_funcs_array[j][0])) == NULL) {
INFO_ERR("Out of memory\n")
lg_quit(-1, TRUE);
}
}
mwp->with_frame = TRUE;
mwp->loop = TRUE;
mwp->orig_bg = lg_take_screenshot();
str_array[*n_menu],
lg_color_u(MENUWIN_TEXT_C),
lg_color_u(MENUWIN_BG_C),
lg_get_lg_color_u_from_str(MENUWIN_H_TEXT_C),
lg_get_lg_color_u_from_str(MENUWIN_H_BG_C),
lg_font_get_ttf(MENUWIN_FONT),
(i > 0 && *n_menu == n_menu_bak) ? i : 0,
x + *n_menu * TZWIN_MENUS_LEFT_H_SHIFT,
y
);
n_menu_bak = *n_menu;
if (i >= 0) {
exit_status = actions_funcs_array[*n_menu][i].func();
} else if (i == MENUWIN_KEY_ESC) { // MENUWIN_KEY_ESC if none is selected (ESC)
exit_status = MENUWIN_CLOSE;
} else if (i == MENUWIN_KEY_SPACE) { // None is selected (SPACE)
exit_status = MENUWIN_SPACE_PRESSED;
} else if (i == MENUWIN_KEY_LEFT) { // LEFT
(*n_menu)--;
if (*n_menu < 0) {
*n_menu = size - 1;
}
} else if (i == MENUWIN_KEY_RIGHT) { // RIGHT
(*n_menu)++;
if (*n_menu > size - 1) {
*n_menu = 0;
}
}
for (j = 0; j < size; j++) {
free3(str_array[j]);
}
if (mwp->orig_bg != NULL) {
lg_texture_remove(mwp->orig_bg);
}
return exit_status;
}
LG_Texture * lg_take_screenshot()
Definition lg_background.c:264
LG_Env * lg_get_game_env()
Definition lg_env_instance.c:19
TTF_Font * lg_font_get_ttf(const char *name)
Definition lg_fonts.c:156
char * l_str_new3(const char *format,...)
Definition lg_goodies.c:71
LG_Color_u lg_get_lg_color_u_from_str(const char *str)
Definition lg_gr_func.c:694
void lg_flush_keyb_events()
Definition lg_keyboard.c:257
void lg_flush_mouse_events()
Definition lg_mouse.c:105
void lg_texture_remove(LG_Texture *node)
Definition lg_textures.c:809
LG_Color_u lg_color_u(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Definition lg_vertex.c:208
LG_MenuWinParams * lg_get_menu_wins_params()
Definition lg_wins.c:944
int lg_menu_win(const char *text, LG_Color_u text_c, LG_Color_u bg_c, LG_Color_u h_text_c, LG_Color_u h_bg_c, TTF_Font *font, int starting_index, int x, int y)
Definition lg_wins.c:1162
char * lg_action_func_to_str2(LG_ActionFunc2 actions_funcs[])
Definition lg_wins.c:1335
void lg_quit(int exit_code, zboolean call_exit)
Definition libgame.c:1039
Definition lg_wins.h:90
Definition lg_wins.h:77

=== WARNING: May also swap framebuffer ===

Parameters
textA NULL-terminated string with lines separated by newlines ('\n')
text_cText color
bg_cBackground color
h_text_cHightlight text color
h_bg_cHightlight bg color
fontA TTF_Font
starting_index(self-explanatory enough)
xHorizontally centered if -1
yVertically centered if -1
Returns
Index (in range [0, n_lines - 1]) of the selected line (ENTER / left-click) or one of these negative values:
  • MENUWIN_KEY_ESC (-1) for ESC - no line was selected
  • MENUWIN_KEY_LEFT (-2) for LEFT ARROW
  • MENUWIN_KEY_RIGHT (-3) for RIGHT ARROW
  • MENUWIN_KEY_SPACE (-4) for SPACE
  • MENUWIN_ERROR (-5) on error

◆ lg_action_func_to_str()

char * lg_action_func_to_str ( LG_ActionFunc  actions_funcs[])

Get a string with all actions separated by newlines ('\n') from the address of a NULL-terminated array of LG_ActionFunc

typedef struct {
const char *str;
void (*func)();
Definition lg_wins.h:85
Parameters
Addressof a NULL-terminated array of LG_ActionFunc
Returns
A string - must be freed when done

◆ lg_action_func_to_str2()

char * lg_action_func_to_str2 ( LG_ActionFunc2  actions_funcs[])

Get a string with all actions separated by newlines ('\n') from the address of a NULL-terminated array of LG_ActionFunc2

typedef struct {
const char *str;
int (*func)();
Parameters
Addressof a NULL-terminated array of LG_ActionFunc2
Returns
A string - must be freed when done

◆ lg_scrollable_win()

void lg_scrollable_win ( LG_Win_Style style,
int  display_n_lines,
const char *  text 
)

Create and open a LG_Window with vertically scrollable content

Suitable for an emulated terminal

Parameters
stylePointer to a LG_Win_Style instance
display_n_linesNum of lines to display, ie height in lines of the emulated terminal
textA NULL-terminated string with lines separated by newlines ('\n')

◆ lg_win_show_annoying_errors()

void lg_win_show_annoying_errors ( )

Enable output of annoying, not-critical errors (default)

◆ lg_win_no_annoying_errors()

void lg_win_no_annoying_errors ( )

Disable output of annoying, not-critical errors

◆ lg_win_open()

int lg_win_open ( LG_Window win,
int  x,
int  y,
uint32_t  v_shift 
)

Open a LG_Window instance

Set: x = -1, y = -1 for a centered window

Parameters
win
xHorizontally centered if -1
yVertically centered if -1
v_shift<Not sure yet>
Returns
LG_OK if OK

◆ lg_win_free_tex()

void lg_win_free_tex ( LG_Window win)

Free resources (texture atlas actually) of a LG_Window instance

Parameters
win

◆ is_lg_win()

zboolean is_lg_win ( LG_Window win)

Check win is valid

Parameters
win

◆ lg_get_centered_win_rec()

Rec2Di lg_get_centered_win_rec ( LG_Window win)

Return win rectangle of centered win

Parameters
winA pointer to a LG_Windox
Returns
The win rectangle if OK, lg_rec2d_i(0, 0, 0, 0) on error

◆ lg_win_get_w()

int lg_win_get_w ( LG_Window win)

Get win width

Parameters
win
Returns
win->tex_rec.w or -1 on error

◆ lg_win_get_h()

int lg_win_get_h ( LG_Window win)

Get win height

Parameters
win
Returns
win->tex_rec.h or -1 on error

◆ lg_text_get_n_lines()

int lg_text_get_n_lines ( const char *  text)

Get num of lines of a text by scanning newlines ('\n')

Num of lines = 1 + num of newlines

  • " " -> 1 line
  • "\n " -> 2 lines
  • "hello1\nhello2\nhello3\n" -> 4 lines
Parameters
textA NULL-terminated string
Returns
Num of lines or -1 on error

◆ lg_text_format_for_win()

char * lg_text_format_for_win ( const char *  text,
TTF_Font *  font 
)

Format text for display in LG_Window

Returned string must be freed when done

Parameters
textA NULL-terminated string
fontPointer to a TTF_Font
Returns
Formatted text if OK, NULL on error

◆ lg_wrap_lines()

char * lg_wrap_lines ( const char *  text,
TTF_Font *  font,
int  max_width 
)

Line and word wrapping: Insert newline(s) if one string (ie between 2 newlines) is too long (ie > max_width)

Returned string must be freed when done

TODO: keep improving the algo

Parameters
stylePointer to a LG_Win_Style instance
fontPointer to a TTF_Font
max_widthIn pixels
Returns
New string if OK, NULL on error