Implemented the top layer
This commit is contained in:
1 parent
51174824b2
commit
4cdc17489e
1 file changed
+204
-57
@@ -96,6 +96,17 @@ static inline int point_in_rect(int x, int y, GUI_Rectangle rect)
|
||||
&& (x <= rect.x1)
|
||||
&& (y <= rect.y1);
|
||||
}
|
||||
static inline int point_in_rect_with_offset(
|
||||
int x, int y,
|
||||
GUI_Rectangle rect,
|
||||
int x_offset, int y_offset)
|
||||
{
|
||||
return
|
||||
(x >= (rect.x0+x_offset))
|
||||
&& (y >= (rect.y0+y_offset))
|
||||
&& (x <= (rect.x1+x_offset))
|
||||
&& (y <= (rect.y1+y_offset));
|
||||
}
|
||||
|
||||
|
||||
typedef enum {
|
||||
@@ -225,6 +236,10 @@ typedef struct {
|
||||
GUI_Draw_Command *first_draw_command;
|
||||
int num_draw_commands;
|
||||
Pixel_Buffer *pixel_buffer;
|
||||
bool should_draw;
|
||||
// TODO(Zelaven): Offsets like for the subtrees.
|
||||
int offset_x;
|
||||
int offset_y;
|
||||
} GUI_Layer;
|
||||
|
||||
|
||||
@@ -355,7 +370,14 @@ void fff(GUI_Context *context)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define GUIWITH_INNER2(token) defer ## token
|
||||
#define GUIWITH_INNER(token) GUIWITH_INNER2(token)
|
||||
#define GUIWITH(storage_variable, TYPE, value_to_use)\
|
||||
for(struct {TYPE temp; int i;} GUIWITH_INNER(__LINE__) = {.temp=(storage_variable), .i = ((storage_variable) = (value_to_use), 0)}; !GUIWITH_INNER(__LINE__).i; GUIWITH_INNER(__LINE__).i += 1, ((storage_variable) = GUIWITH_INNER(__LINE__).temp))
|
||||
|
||||
#define GUI_ON_LAYER(context, layer) \
|
||||
(layer)->should_draw = true;\
|
||||
GUIWITH(context->current_layer, GUI_Layer*, layer)
|
||||
|
||||
|
||||
// ---
|
||||
@@ -364,7 +386,7 @@ void fff(GUI_Context *context)
|
||||
// TODO(Zelaven): The mouse coordinates are in the context, so no need to pass
|
||||
// them as parameters.
|
||||
#undef ENABLE_DEBUG
|
||||
#define ENABLE_DEBUG 0
|
||||
#define ENABLE_DEBUG 1
|
||||
void gui_apply_input(
|
||||
GUI_Context *context,
|
||||
int mouse_x,
|
||||
@@ -380,12 +402,15 @@ void gui_apply_input(
|
||||
{
|
||||
GUI_Layer *top_layer = &context->top_layer;
|
||||
GUI_Subtree *root_subtree = (GUI_Subtree*)top_layer->subtree_rdic.root;
|
||||
if(root_subtree != NULL)
|
||||
if(top_layer->should_draw && root_subtree != NULL)
|
||||
{
|
||||
GUI_Node *top_layer_root =
|
||||
(GUI_Node*)root_subtree->rdic.root;
|
||||
if(top_layer_root != NULL)
|
||||
if(point_in_rect(mouse_x, mouse_y, top_layer_root->rect))
|
||||
if(point_in_rect_with_offset(
|
||||
mouse_x, mouse_y,
|
||||
top_layer_root->rect,
|
||||
top_layer->offset_x, top_layer->offset_y))
|
||||
{
|
||||
hit_layer = &context->top_layer;
|
||||
hit_root_subtree = root_subtree;
|
||||
@@ -579,6 +604,65 @@ GUI_Subtree_Reference gui_get_subtree(
|
||||
}
|
||||
|
||||
|
||||
GUI_Node_Reference gui_context_prepare_layer(
|
||||
GUI_Context *context,
|
||||
GUI_Layer *layer,
|
||||
GUI_Node_Reference last_root_reference,
|
||||
int width, int height,
|
||||
GUI_Layout_Direction layout_direction,
|
||||
GUI_Style *style)
|
||||
{
|
||||
layer->should_draw = false;
|
||||
GUI_Subtree_Reference root_subtree = layer->root_subtree;
|
||||
//root_subtree = gui_get_subtree(context, root_subtree);
|
||||
root_subtree.rdic_ref = rdic_context_start_frame(
|
||||
&layer->subtree_rdic, root_subtree.rdic_ref);
|
||||
if(root_subtree.node == NULL)
|
||||
{
|
||||
return (GUI_Node_Reference){0};
|
||||
}
|
||||
layer->root_subtree = root_subtree;
|
||||
root_subtree.node->rdic.freelist = context->node_freelist;
|
||||
|
||||
//static GUI_Subtree background_subtree = {0};
|
||||
//background_subtree.rdic.freelist = context->node_freelist;
|
||||
//context->background_layer.first_subtree = &background_subtree;
|
||||
//context->background_layer.last_subtree = &background_subtree;
|
||||
//context->current_subtree = &background_subtree;
|
||||
|
||||
GUI_Node_Reference new_root_reference = {
|
||||
.rdic_ref = rdic_context_start_frame(
|
||||
//&background_subtree.rdic, last_root_reference.rdic)
|
||||
&root_subtree.node->rdic, last_root_reference.rdic_ref)
|
||||
};
|
||||
if(new_root_reference.node == NULL)
|
||||
{
|
||||
return (GUI_Node_Reference){0};
|
||||
}
|
||||
//RDIC_Node_Reference new_root_reference = rdic_context_start_frame(
|
||||
// &background_subtree.rdic,
|
||||
// last_root_reference);
|
||||
|
||||
GUI_Node *root = (GUI_Node*)new_root_reference.node;
|
||||
root->dirty = false;
|
||||
if(!gui_node_references_equal(last_root_reference, new_root_reference)) {
|
||||
root->dirty = true;
|
||||
}
|
||||
if(layout_direction != root->layout_direction) {
|
||||
root->dirty = true;
|
||||
}
|
||||
|
||||
root->debug_string = GUI_STRING("root");
|
||||
root->layout_direction = layout_direction;
|
||||
root->semantic_size[GUI_AXIS2_X] = (GUI_Size)
|
||||
{.size_rule = GUI_SIZERULE_PIXELS, .value = width, .strictness = 100,};
|
||||
root->semantic_size[GUI_AXIS2_Y] = (GUI_Size)
|
||||
{.size_rule = GUI_SIZERULE_PIXELS, .value = height, .strictness = 100,};
|
||||
root->style = style;
|
||||
|
||||
return new_root_reference;
|
||||
}
|
||||
|
||||
#undef ENABLE_DEBUG
|
||||
#define ENABLE_DEBUG 0
|
||||
// TODO(Zelaven): Make this cause redrawing of root on parameter change.
|
||||
@@ -608,55 +692,14 @@ GUI_Node_Reference gui_context_start_frame(
|
||||
context->mouse_pressed, context->mouse_down);
|
||||
|
||||
context->current_layer = &context->background_layer;
|
||||
GUI_Node_Reference new_root_reference = gui_context_prepare_layer(
|
||||
context, context->current_layer, last_root_reference,
|
||||
width, height, layout_direction, style);
|
||||
|
||||
GUI_Subtree_Reference root_subtree = context->current_layer->root_subtree;
|
||||
//root_subtree = gui_get_subtree(context, root_subtree);
|
||||
root_subtree.rdic_ref = rdic_context_start_frame(
|
||||
&context->current_layer->subtree_rdic, root_subtree.rdic_ref);
|
||||
if(root_subtree.node == NULL)
|
||||
{
|
||||
return (GUI_Node_Reference){0};
|
||||
}
|
||||
context->current_layer->root_subtree = root_subtree;
|
||||
root_subtree.node->rdic.freelist = context->node_freelist;
|
||||
|
||||
//static GUI_Subtree background_subtree = {0};
|
||||
//background_subtree.rdic.freelist = context->node_freelist;
|
||||
//context->background_layer.first_subtree = &background_subtree;
|
||||
//context->background_layer.last_subtree = &background_subtree;
|
||||
//context->current_subtree = &background_subtree;
|
||||
|
||||
GUI_Node_Reference new_root_reference = {
|
||||
.rdic_ref = rdic_context_start_frame(
|
||||
//&background_subtree.rdic, last_root_reference.rdic)
|
||||
&root_subtree.node->rdic, last_root_reference.rdic_ref)
|
||||
};
|
||||
if(new_root_reference.node == NULL)
|
||||
{
|
||||
return (GUI_Node_Reference){0};
|
||||
}
|
||||
//RDIC_Node_Reference new_root_reference = rdic_context_start_frame(
|
||||
// &background_subtree.rdic,
|
||||
// last_root_reference);
|
||||
GUI_Node *root = (GUI_Node*)new_root_reference.node;
|
||||
root->dirty = false;
|
||||
if(!gui_node_references_equal(last_root_reference, new_root_reference)) {
|
||||
root->dirty = true;
|
||||
}
|
||||
if(layout_direction != root->layout_direction) {
|
||||
root->dirty = true;
|
||||
}
|
||||
context->current_layer->should_draw = true;
|
||||
|
||||
gui_apply_input(context, context->mouse_x, context->mouse_y);
|
||||
|
||||
root->debug_string = GUI_STRING("root");
|
||||
root->layout_direction = layout_direction;
|
||||
root->semantic_size[GUI_AXIS2_X] = (GUI_Size)
|
||||
{.size_rule = GUI_SIZERULE_PIXELS, .value = width, .strictness = 100,};
|
||||
root->semantic_size[GUI_AXIS2_Y] = (GUI_Size)
|
||||
{.size_rule = GUI_SIZERULE_PIXELS, .value = height, .strictness = 100,};
|
||||
root->style = style;
|
||||
|
||||
return new_root_reference;
|
||||
}
|
||||
void gui_context_finish_frame(
|
||||
@@ -1028,6 +1071,32 @@ bool gui_dumb_button(
|
||||
|
||||
#undef ENABLE_DEBUG
|
||||
#define ENABLE_DEBUG 0
|
||||
bool gui_mouseover_box(
|
||||
GUI_Context *context,
|
||||
GUI_Node_Reference *last_reference,
|
||||
GUI_String text,
|
||||
GUI_Style *style,
|
||||
GUI_Size size[static 2])
|
||||
{
|
||||
GUI_Node_Reference new_reference = gui_get_node(
|
||||
context, *last_reference, GUI_LAYOUT_NONE, style, size);
|
||||
GUI_Node *node = new_reference.node;
|
||||
node->debug_string = GUI_STRING("gui_mouseover_box");
|
||||
node->text_string = text;
|
||||
|
||||
bool new_ref_is_top = gui_node_references_equal(
|
||||
new_reference, context->top_node_under_cursor);
|
||||
DEBUG(" %p\n | %p\n | %p\n",
|
||||
context->top_node_under_cursor.node,
|
||||
last_reference->node, new_reference.node);
|
||||
bool hovered = new_ref_is_top;
|
||||
|
||||
*last_reference = new_reference;
|
||||
return hovered;
|
||||
}
|
||||
|
||||
#undef ENABLE_DEBUG
|
||||
#define ENABLE_DEBUG 1
|
||||
bool gui_slider(
|
||||
GUI_Context *context,
|
||||
GUI_Node_Reference *last_reference,
|
||||
@@ -1053,10 +1122,10 @@ bool gui_slider(
|
||||
new_reference, context->top_node_under_cursor);
|
||||
bool inner_ref_is_top = gui_node_references_equal(
|
||||
new_inner_reference, context->top_node_under_cursor);
|
||||
DEBUG("%p\n | %p %p\n | %p %p\n",
|
||||
/*DEBUG(" %p\n | %p %p\n | %p %p\n",
|
||||
context->top_node_under_cursor.node,
|
||||
last_reference->node, inner_box_reference->node,
|
||||
new_reference.node, new_inner_reference.node);
|
||||
new_reference.node, new_inner_reference.node);*/
|
||||
if(new_ref_is_top || inner_ref_is_top)
|
||||
{
|
||||
DEBUG("\n%s: reference is the top node under cursor.\n", __func__);
|
||||
@@ -1814,6 +1883,14 @@ void test_gui__subtree(
|
||||
full_gui_rectangle.y1-full_gui_rectangle.y0,
|
||||
GUI_LAYOUT_VERTICAL,
|
||||
&root_style);
|
||||
static GUI_Node_Reference top_root = {0};
|
||||
top_root = gui_context_prepare_layer(
|
||||
context, &context->top_layer, top_root,
|
||||
context->top_layer.pixel_buffer->width,
|
||||
context->top_layer.pixel_buffer->height,
|
||||
GUI_LAYOUT_HORIZONTAL, &outer_style);
|
||||
context->top_layer.offset_x = 50;
|
||||
context->top_layer.offset_y = 250;
|
||||
|
||||
|
||||
static GUI_Node_Reference top = {0};
|
||||
@@ -1841,7 +1918,7 @@ void test_gui__subtree(
|
||||
static GUI_Node_Reference dirty_button = {0};
|
||||
static GUI_Style button_style = {0x99,0x99,0x99, 0x00222222,2,0};
|
||||
static GUI_Size button_size[2] = {
|
||||
{GUI_SIZERULE_PIXELS, 200, 100},
|
||||
{GUI_SIZERULE_PIXELS, 170, 100},
|
||||
{GUI_SIZERULE_PIXELS, 40, 100}};
|
||||
if(gui_dumb_button(
|
||||
context, &dirty_button, GUI_STRING("Dirty middle"),
|
||||
@@ -1857,6 +1934,31 @@ void test_gui__subtree(
|
||||
set_pixels = true;
|
||||
printf("Setting pixels.\n");
|
||||
}
|
||||
static bool tooltip_toggle = false;
|
||||
static GUI_Node_Reference dirty_button3 = {0};
|
||||
if(gui_dumb_button(
|
||||
context, &dirty_button3, GUI_STRING("Hover for tooltip"),
|
||||
&button_style, button_size))
|
||||
{
|
||||
tooltip_toggle = !tooltip_toggle;
|
||||
}
|
||||
static GUI_Node_Reference dirty_button4 = {0};
|
||||
if(
|
||||
gui_mouseover_box(
|
||||
context, &dirty_button4, GUI_STRING("Hover for tooltip"),
|
||||
&button_style, button_size)
|
||||
|| tooltip_toggle)
|
||||
{
|
||||
GUI_ON_LAYER(context, &context->top_layer)
|
||||
{
|
||||
static GUI_Size full_size[2] = {
|
||||
{GUI_SIZERULE_PERCENTOFPARENT, 100, 100},
|
||||
{GUI_SIZERULE_PERCENTOFPARENT, 100, 100}};
|
||||
static GUI_Node_Reference top_layer_block = {0};
|
||||
top_layer_block = gui_dumb_block(
|
||||
context, top_layer_block, &element_style, full_size);
|
||||
}
|
||||
}
|
||||
} gui_pop_parent(context); // middle.
|
||||
|
||||
middle = gui_dumb_block(context, middle, &outer_style, middle_size);
|
||||
@@ -3611,6 +3713,30 @@ void gui_layout_and_draw(GUI_Context *context)
|
||||
}
|
||||
}
|
||||
|
||||
void gui_compose_layers(
|
||||
GUI_Context *context,
|
||||
Pixel_Buffer *target_buffer)
|
||||
{
|
||||
// TODO(Zelaven): Make the layers in the context iteratable.
|
||||
GUI_Layer *layers[] = {
|
||||
&context->background_layer,
|
||||
&context->top_layer,
|
||||
};
|
||||
for(
|
||||
size_t i = 0;
|
||||
i < ARRAYLENGTH(layers);
|
||||
i++)
|
||||
{
|
||||
GUI_Layer *layer = layers[i];
|
||||
if(layer->should_draw) {
|
||||
gui_draw_image_direct(
|
||||
target_buffer,
|
||||
layer->pixel_buffer,
|
||||
layer->offset_x,
|
||||
layer->offset_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include <unistd.h> // usleep.
|
||||
@@ -3678,12 +3804,27 @@ int main(void)
|
||||
RDIC_Freelist subtree_freelist = {&g_gui_subtree_freelist[0].rdic_node};
|
||||
context.subtree_freelist = &subtree_freelist;
|
||||
|
||||
Pixel_Buffer background_pixel_buffer = (Pixel_Buffer){
|
||||
.pixels = malloc(xwindow.pixel_buffer.width*xwindow.pixel_buffer.height*sizeof(GUI_Color)),
|
||||
.width = xwindow.pixel_buffer.width,
|
||||
.height = xwindow.pixel_buffer.height,
|
||||
};
|
||||
Pixel_Buffer top_pixel_buffer = (Pixel_Buffer){
|
||||
.pixels = malloc(300*200*sizeof(GUI_Color)),
|
||||
.width = 300,
|
||||
.height = 200,
|
||||
};
|
||||
assert(background_pixel_buffer.pixels);
|
||||
assert(top_pixel_buffer.pixels);
|
||||
|
||||
context.background_layer = (GUI_Layer){
|
||||
.subtree_rdic.freelist = &subtree_freelist,
|
||||
.pixel_buffer = &xwindow.pixel_buffer,
|
||||
//.pixel_buffer = &xwindow.pixel_buffer,
|
||||
.pixel_buffer = &background_pixel_buffer,
|
||||
};
|
||||
context.top_layer = (GUI_Layer){
|
||||
.subtree_rdic.freelist = &subtree_freelist,
|
||||
.pixel_buffer = &top_pixel_buffer,
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -3692,10 +3833,16 @@ int main(void)
|
||||
|
||||
fill_pixel_buffer(
|
||||
xwindow.pixel_buffer.pixels,
|
||||
xwindow.width,
|
||||
xwindow.height,
|
||||
0,
|
||||
0);
|
||||
xwindow.width, xwindow.height,
|
||||
0, 0);
|
||||
fill_pixel_buffer(
|
||||
background_pixel_buffer.pixels,
|
||||
background_pixel_buffer.width, background_pixel_buffer.height,
|
||||
0, 0);
|
||||
fill_pixel_buffer(
|
||||
top_pixel_buffer.pixels,
|
||||
top_pixel_buffer.width, top_pixel_buffer.height,
|
||||
0, 0);
|
||||
GUI_Rectangle screen_rectangle = {
|
||||
.x0 = 0, .y0 = 0,
|
||||
.x1 = xwindow.width, .y1 = xwindow.height,
|
||||
@@ -3798,7 +3945,7 @@ int main(void)
|
||||
//gui_layout_nodes(&context);
|
||||
#if 1
|
||||
gui_layout_and_draw(&context);
|
||||
SET_PIXEL(&xwindow.pixel_buffer, 239, 259, 0x00ff0000);
|
||||
gui_compose_layers(&context, &xwindow.pixel_buffer);
|
||||
#else
|
||||
for(
|
||||
GUI_Subtree *current = (GUI_Subtree*)context.background_layer.subtree_rdic.root;
|
||||
|
||||
Reference in new issue
Block a user