2023-09-26 19:40:16 +02:00
# ifndef _PIUMA_GUI_H_
# define _PIUMA_GUI_H_
# include "../lib/types.h"
# include "../lib/math.h"
# include "../lib/geometry.h"
# include "../render/2d.h"
# include "../lib/text.h"
# include "../lib/event.h"
2024-09-27 19:46:39 +02:00
# include "../lib/array.h"
2023-09-26 19:40:16 +02:00
typedef u32 Gui_Id ;
struct Gui_Input
{
v2 pointer_position ;
v2 absolute_pointer_position ;
bool mouse_pressed ;
bool mouse_pressed_this_frame ;
bool mouse_released_this_frame ;
s64 text_cursor_move ;
char text [ 32 ] ;
2024-09-27 19:46:39 +02:00
s32 scroll_move ;
2023-09-26 19:40:16 +02:00
v2 absolute_pointer_position_last_frame ;
} ;
enum Gui_Text_Align
{
GUI_ALIGN_CENTER ,
GUI_ALIGN_LEFT ,
GUI_ALIGN_RIGHT
} ;
struct Gui_Style
{
f32 font_size ;
f32 animation_base_time ;
v4 text_color ;
Gui_Text_Align text_align ;
v4 button_color ;
v4 button_color_hovered ;
v4 button_color_pressed ;
v4 button_text_color ;
v4 button_text_color_hovered ;
v4 button_text_color_pressed ;
f32 button_radius ;
v4 slider_fill_color ;
v4 window_background_color ;
v4 window_border_color ;
v4 window_background_color_inactive ;
v4 window_border_color_inactive ;
f32 window_corner_radius ;
v4 window_titlebar_color ;
v4 window_titlebar_color_inactive ;
2024-09-27 19:46:39 +02:00
f32 scrollbar_size ;
f32 scrollbar_corner_radius ;
f32 scrollbar_inner_bar_size ;
f32 scrollbar_inner_bar_corner_radius ;
v4 scrollbar_color ;
v4 scrollbar_inner_bar_color ;
2023-09-26 19:40:16 +02:00
} ;
struct Gui_Window
{
Gui_Id id ;
Rect r ;
r_framebuffer framebuffer ;
bool still_open ;
} ;
enum Gui_Widget_Status_Flags : u8
{
GUI_WIDGET_STATUS_NONE ,
GUI_WIDGET_STATUS_PREVENT_HOT
} ;
struct Gui_Context
{
u32 width ;
u32 height ;
f64 last_frame_time ;
f64 current_frame_time ;
Gui_Id active ; // Are we interacting with the widget (pressed for buttons, ready to receive text for text inputs)
Gui_Id hot ; // Hovered the previous frame
Gui_Id possibly_hot ; // Might become hot this frame
f64 active_start_time ;
f64 hot_start_time ;
u8 active_status ;
// Text input state
u64 text_cursor_position ;
u64 text_length ;
// Windows
2024-09-27 19:46:39 +02:00
Array < Gui_Window > windows ;
2023-09-26 19:40:16 +02:00
Gui_Window * current_window ;
r_framebuffer * old_framebuffer ;
2024-09-27 19:46:39 +02:00
// Clipping
Array < Rect > clipping ;
2023-09-26 19:40:16 +02:00
// ID
2024-09-27 19:46:39 +02:00
Array < Gui_Id > id_stack ;
2023-09-26 19:40:16 +02:00
Gui_Input input ;
Gui_Style style ;
} ;
struct Gui_State
{
Gui_Context default_context ;
Gui_Context * selected_context ;
} ;
extern Gui_State global_gui_state ;
bool gui_init ( ) ;
void gui_deinit ( ) ;
void gui_context_init ( Gui_Context * ctx ) ;
//@Correctness: gui_context_deinit
void gui_context_select ( Gui_Context * ctx ) ; // Set implicit Gui_Context
void gui_frame_begin ( Gui_Context * ctx , f64 curr_time ) ;
void gui_frame_begin ( f64 curr_time ) ;
void gui_frame_end ( Gui_Context * ctx ) ;
void gui_frame_end ( ) ;
void gui_handle_event ( Gui_Context * ctx , Event * e ) ;
void gui_handle_event ( Event * e ) ;
// ### Widgets ###
// Text
void gui_text ( Gui_Context * ctx , Rect r , const char * text ) ;
void gui_text ( Rect r , const char * text ) ;
void gui_text_aligned ( Gui_Context * ctx , Rect r , const char * text , Gui_Text_Align alignment ) ;
void gui_text_aligned ( Rect r , const char * text , Gui_Text_Align alignment ) ;
v2 gui_text_compute_size ( Gui_Context * ctx , const char * text ) ;
v2 gui_text_compute_size ( const char * text ) ;
// Button
bool gui_button ( Gui_Context * ctx , Rect r , const char * text ) ;
bool gui_button ( Rect r , const char * text ) ;
2024-09-27 19:46:39 +02:00
// @Feature: Buttons with widgets inside
2023-09-26 19:40:16 +02:00
// Slider
2024-09-27 19:46:39 +02:00
bool gui_slider_range ( Gui_Context * ctx , Rect r , f32 min , f32 max , f32 * value ) ;
bool gui_slider_range ( Rect r , f32 min , f32 max , f32 * value ) ;
2023-09-26 19:40:16 +02:00
2023-09-30 18:28:35 +02:00
2024-09-27 19:46:39 +02:00
bool gui_slider_text ( Gui_Context * ctx , Rect r , f32 * ratio , const char * text ) ; // ratio must be between 0 and 1.
bool gui_slider_text ( Rect r , f32 * ratio , const char * text ) ;
// @Feature: Checkbox
// @Feature: Option buttons
// @Feature: Combo box
// @Feature: Tooltips
2023-09-26 19:40:16 +02:00
// Images
bool gui_image ( Gui_Context * ctx , Rect r , r_texture * texture ) ;
bool gui_image ( Rect r , r_texture * texture ) ;
bool gui_image ( Gui_Context * ctx , Rect r , const u8 * bmp , u32 width , u32 height , u32 channels , u32 flags = 0 ) ;
bool gui_image ( Rect r , const u8 * bmp , u32 width , u32 height , u32 channels , u32 flags = 0 ) ;
// Text input
bool gui_text_input ( Gui_Context * ctx , Rect r , char * text , u64 max_size ) ;
bool gui_text_input ( Rect r , char * text , u64 max_size ) ;
2023-09-30 02:39:12 +02:00
// Panels
void gui_panel ( Gui_Context * ctx , Rect r ) ;
void gui_panel ( Rect r ) ;
2023-09-26 19:40:16 +02:00
// Windows
2024-09-27 19:46:39 +02:00
struct Gui_Titlebar_State
{
v2 move ;
v2 anchor_point ;
bool close ;
} ;
struct Gui_Window_Titlebar_State
{
Rect inner_r ;
Gui_Titlebar_State titlebar ;
} ;
2023-09-26 19:40:16 +02:00
bool gui_window_start ( Gui_Context * ctx , Rect r , Gui_Id id ) ; // You have to provide some kind of unique id to identify windows
bool gui_window_start ( Rect r , Gui_Id id ) ;
2024-09-27 19:46:39 +02:00
bool gui_window_with_titlebar_start ( Gui_Context * ctx , Rect r , const char * title , Gui_Window_Titlebar_State * state ) ;
bool gui_window_with_titlebar_start ( Rect r , const char * title , Gui_Window_Titlebar_State * state ) ;
2023-09-26 19:40:16 +02:00
void gui_window_end ( Gui_Context * ctx ) ;
void gui_window_end ( ) ;
2024-09-27 19:46:39 +02:00
// Standalone titlebar for your custom windows
bool gui_window_titlebar ( Gui_Context * ctx , Rect r , const char * title , Gui_Titlebar_State * state ) ;
bool gui_window_titlebar ( Rect r , const char * title , Gui_Titlebar_State * state ) ;
// @Feature: Panel
// If you want to change which zone is displayed, change position in displayed_r. size will always be computed from r after removing the scrollbar size
bool gui_scrollable_area_start ( Gui_Context * ctx , Rect r , v2 area_size , Rect * displayed_r ) ;
bool gui_scrollable_area_start ( Rect r , v2 area_size , Rect * displayed_r ) ;
void gui_scrollable_area_end ( Gui_Context * ctx ) ;
void gui_scrollable_area_end ( ) ;
2023-09-26 19:40:16 +02:00
Gui_Window * gui_window_by_id ( Gui_Context * ctx , Rect r , Gui_Id id ) ; // Rect r might be needed for creation
void gui_window_update_rect ( Gui_Context * ctx , Gui_Window * window , Rect r ) ;
// Helpers
bool gui_is_hovered ( Gui_Context * ctx , Gui_Id widget_id , Rect r ) ;
bool gui_button_behaviuor ( Gui_Context * ctx , Gui_Id widget_id , Rect r ) ;
bool gui_text_input_behaviuor ( Gui_Context * ctx , Gui_Id widget_id , Rect r ) ;
bool gui_window_behaviour ( Gui_Context * ctx , Gui_Id widget_id , Rect r ) ;
Gui_Id gui_id_from_pointer ( Gui_Context * ctx , const void * ptr ) ;
void gui_id_stack_push ( Gui_Context * ctx , Gui_Id id ) ;
void gui_id_stack_pop ( Gui_Context * ctx ) ;
2024-09-27 19:46:39 +02:00
// Clipping
void gui_clip_start ( Gui_Context * ctx , Rect r ) ;
void gui_clip_end ( Gui_Context * ctx ) ;
bool gui_is_clipped ( Gui_Context * ctx , Rect r ) ; // Returns true only if completely clipped
2023-09-26 19:40:16 +02:00
# endif