2025-07-06 20:43:53 +03:00
# pragma once
# include <include/core/SkCanvas.h>
# include <Eigen/Dense>
# include "GUIManagerID.hpp"
# include <clay.h>
2026-03-27 09:51:53 +03:00
# include "Elements/Element.hpp"
2025-10-15 16:33:24 +03:00
2025-07-06 20:43:53 +03:00
using namespace Eigen ;
namespace GUIStuff {
class GUIManager {
public :
struct ElementContainer {
std : : unique_ptr < Element > elem ;
2025-10-14 12:51:24 +03:00
bool isUsedThisFrame ;
2025-07-06 20:43:53 +03:00
} ;
GUIManager ( ) ;
2026-04-08 17:34:50 +03:00
void draw ( SkCanvas * c , bool skiaAA ) ;
2026-04-19 10:03:57 +03:00
void draw_force ( SkCanvas * canvas , bool skiaAA ) ;
2026-03-27 09:51:53 +03:00
void set_to_layout ( ) ;
void layout_if_necessary ( ) ;
2026-04-08 17:34:50 +03:00
void update ( ) ;
2026-03-27 09:51:53 +03:00
void update_window ( const Vector2f & windowPos , const Vector2f & windowSize , float guiScaleMultiplier ) ;
2025-07-06 20:43:53 +03:00
2026-03-31 13:17:58 +03:00
UpdateInputData io ;
2025-07-06 20:43:53 +03:00
2026-03-30 18:51:14 +03:00
void new_id ( const char * id , const std : : function < void ( ) > & f ) ;
void new_id ( int64_t id , const std : : function < void ( ) > & f ) ;
2025-07-06 20:43:53 +03:00
2026-04-01 18:00:22 +03:00
void set_z_index ( int16_t z , const std : : function < void ( ) > & f ) ;
2026-04-06 12:23:46 +03:00
void set_z_index_keep_clipping_region ( int16_t z , const std : : function < void ( ) > & f ) ;
2026-04-01 18:00:22 +03:00
int16_t get_z_index ( ) ;
2026-03-27 09:51:53 +03:00
void set_post_callback_func ( const std : : function < void ( ) > & f ) ;
2026-04-01 18:00:22 +03:00
void set_post_callback_func_high_priority ( const std : : function < void ( ) > & f ) ;
2026-03-31 17:33:09 +03:00
void run_post_callback_func ( ) ;
2025-07-06 20:43:53 +03:00
2026-04-08 17:34:50 +03:00
void invalidate_draw_element ( Element * element , const BorderData & extraPadding = { } ) ;
void invalidate_draw_in_area ( const SCollision : : AABB < float > & bb ) ;
2026-03-27 09:51:53 +03:00
template < typename ElementType , typename . . . Args > ElementType * element ( const char * id , const Args & . . . a ) {
push_id ( id ) ;
2026-04-02 22:05:37 +03:00
2026-03-27 09:51:53 +03:00
ElementType * elem = insert_element < ElementType > ( ) ;
2026-04-09 16:30:28 +03:00
Element * oldParent = parentElement ;
2026-04-02 21:57:26 +03:00
elem - > parent = parentElement ;
2026-04-02 22:05:37 +03:00
parentElement = elem ;
2026-04-01 21:49:44 +03:00
elem - > set_parent_clipping_region ( clippingRegion ) ;
2026-04-02 22:05:37 +03:00
Clay_ElementId clayId = strArena . elem_id_from_id_stack ( idStack ) ;
2026-03-31 17:33:09 +03:00
elem - > layout ( clayId , a . . . ) ;
2026-04-01 22:28:48 +03:00
elem - > set_bounding_box_from_elem_data ( Clay_GetElementData ( clayId ) ) ; // Setting bounding box after layout ensures that the element will have its bounding box set if it's set to be drawn.
2026-04-02 22:05:37 +03:00
2026-04-02 21:57:26 +03:00
parentElement = oldParent ;
2026-04-02 22:05:37 +03:00
2026-03-27 09:51:53 +03:00
pop_id ( ) ;
return elem ;
}
2025-07-06 20:43:53 +03:00
2026-04-01 21:49:44 +03:00
template < typename ElementType , typename . . . Args > ElementType * clipping_element ( const char * id , const Args & . . . a ) {
push_id ( id ) ;
ElementType * elem = insert_element < ElementType > ( ) ;
2026-04-09 16:30:28 +03:00
Element * oldParent = parentElement ;
2026-04-02 21:57:26 +03:00
elem - > parent = parentElement ;
2026-04-02 22:05:37 +03:00
parentElement = elem ;
2026-04-01 21:49:44 +03:00
elem - > set_parent_clipping_region ( clippingRegion ) ;
auto oldClippingRegion = clippingRegion ;
if ( elem - > get_bb ( ) . has_value ( ) ) {
if ( clippingRegion . has_value ( ) )
clippingRegion = clippingRegion . value ( ) . get_intersection_between_aabbs ( elem - > get_bb ( ) . value ( ) ) ;
else
clippingRegion = elem - > get_bb ( ) ;
}
2026-04-02 22:05:37 +03:00
Clay_ElementId clayId = strArena . elem_id_from_id_stack ( idStack ) ;
2026-04-01 21:49:44 +03:00
elem - > layout ( clayId , a . . . ) ;
2026-04-01 22:28:48 +03:00
elem - > set_bounding_box_from_elem_data ( Clay_GetElementData ( clayId ) ) ;
2026-04-02 22:05:37 +03:00
2026-04-01 21:49:44 +03:00
clippingRegion = oldClippingRegion ;
2026-04-02 22:05:37 +03:00
2026-04-02 21:57:26 +03:00
parentElement = oldParent ;
2026-04-01 21:49:44 +03:00
pop_id ( ) ;
return elem ;
}
2026-04-09 16:30:28 +03:00
void deselect_all ( ) ;
2026-03-27 09:51:53 +03:00
DefaultStringArena strArena ;
2025-12-20 16:38:51 +03:00
2026-04-11 16:36:24 +03:00
void input_paste_callback ( const CustomEvents : : PasteEvent & paste ) ;
2026-04-03 23:02:33 +03:00
void input_text_key_callback ( const InputManager : : KeyCallbackArgs & key ) ;
2026-04-04 17:52:43 +03:00
void input_text_callback ( const InputManager : : TextCallbackArgs & text ) ;
2026-03-31 17:33:09 +03:00
void input_key_callback ( const InputManager : : KeyCallbackArgs & key ) ;
void input_mouse_button_callback ( InputManager : : MouseButtonCallbackArgs button ) ;
void input_mouse_motion_callback ( InputManager : : MouseMotionCallbackArgs motion ) ;
void input_mouse_wheel_callback ( InputManager : : MouseWheelCallbackArgs wheel ) ;
bool cursor_obstructed ( ) const ;
2026-03-27 09:51:53 +03:00
private :
void layout ( ) ;
void layout_begin ( ) ;
void layout_end ( ) ;
void single_layout_run ( ) ;
2025-07-06 20:43:53 +03:00
2026-04-02 21:57:26 +03:00
void mouse_callback ( const Vector2f & mousePos , const std : : function < void ( ElementContainer * ) > & f ) ;
2026-03-31 17:33:09 +03:00
GUIManagerIDStack idStack ;
std : : vector < ElementContainer * > orderedElements ;
std : : unordered_map < GUIManagerIDStack , ElementContainer > elements ;
2025-07-06 20:43:53 +03:00
template < typename NewElement > NewElement * insert_element ( ) {
auto [ it , inserted ] = elements . emplace ( idStack , ElementContainer ( ) ) ;
2025-10-14 12:51:24 +03:00
auto & container = it - > second ;
2025-07-06 20:43:53 +03:00
if ( inserted )
2026-03-27 09:51:53 +03:00
container = { std : : make_unique < NewElement > ( * this ) } ;
container . elem - > zIndex = zIndex ;
2026-03-31 17:33:09 +03:00
orderedElements . emplace_back ( & container ) ;
2025-10-14 12:51:24 +03:00
container . isUsedThisFrame = true ;
2025-07-06 20:43:53 +03:00
return static_cast < NewElement * > ( it - > second . elem . get ( ) ) ;
}
static void clay_error_handler ( Clay_ErrorData errorData ) ;
static Clay_Dimensions clay_skia_measure_text ( Clay_StringSlice str , Clay_TextElementConfig * config , void * userData ) ;
2026-03-30 18:51:14 +03:00
void push_id ( int64_t id ) ;
void push_id ( const char * id ) ;
void pop_id ( ) ;
2026-04-01 18:00:22 +03:00
int16_t zIndex = 0 ;
2026-04-02 21:57:26 +03:00
Element * parentElement = nullptr ;
2026-04-01 21:49:44 +03:00
std : : optional < SCollision : : AABB < float > > clippingRegion ;
2026-03-27 09:51:53 +03:00
std : : function < void ( ) > postCallbackFunc ;
2026-04-01 18:00:22 +03:00
bool postCallbackFuncIsHighPriority ;
2025-07-06 20:43:53 +03:00
Clay_Context * clayInstance ;
Clay_Arena clayArena ;
2026-04-08 17:34:50 +03:00
2025-07-06 20:43:53 +03:00
Clay_RenderCommandArray renderCommands ;
2026-04-08 17:34:50 +03:00
std : : unordered_map < uint32_t , Clay_RenderCommand > oldRenderCommandMap ;
std : : optional < SCollision : : AABB < float > > invalidDrawBB ;
SCollision : : AABB < float > get_invalid_draw_bb ( SCollision : : AABB < float > bb , const BorderData & extraPadding = { } ) ;
SCollision : : AABB < float > get_invalid_draw_bb_from_command ( const Clay_RenderCommand * command ) ;
void update_invalidated_draw_area_from_layout ( ) ;
2026-04-08 20:42:10 +03:00
void calculate_new_clip_rect ( std : : vector < SCollision : : AABB < float > > & clipRectStack , std : : optional < SCollision : : AABB < float > > & clipRect , bool & clipNoDraw ) ;
void clip_rect_transform ( SkCanvas * canvas , std : : vector < SCollision : : AABB < float > > & clipRectStack , std : : optional < SCollision : : AABB < float > > & clipRect , bool & clipNoDraw ) ;
2026-03-27 09:51:53 +03:00
bool setToLayout ;
2026-04-08 17:34:50 +03:00
bool setToUpdateInvalidateDrawAreaFromLayout ;
2026-03-31 17:33:09 +03:00
bool cursorObstructed ;
2025-07-06 20:43:53 +03:00
} ;
}