2016-02-21 17:44:23 +00:00
|
|
|
/*
|
|
|
|
* Mr. 4th Dimention - Allen Webster
|
|
|
|
*
|
|
|
|
* 20.02.2016
|
|
|
|
*
|
|
|
|
* GUI system for 4coder
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
// TOP
|
|
|
|
|
2016-02-27 07:44:17 +00:00
|
|
|
struct Query_Slot{
|
|
|
|
Query_Slot *next;
|
|
|
|
Query_Bar *query_bar;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Query_Set{
|
|
|
|
Query_Slot slots[8];
|
|
|
|
Query_Slot *free_slot;
|
|
|
|
Query_Slot *used_slot;
|
|
|
|
};
|
|
|
|
|
|
|
|
internal void
|
|
|
|
init_query_set(Query_Set *set){
|
|
|
|
Query_Slot *slot = set->slots;
|
|
|
|
int i;
|
|
|
|
set->free_slot = slot;
|
|
|
|
set->used_slot = 0;
|
|
|
|
for (i = 0; i+1 < ArrayCount(set->slots); ++i, ++slot){
|
|
|
|
slot->next = slot + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Query_Slot*
|
|
|
|
alloc_query_slot(Query_Set *set){
|
|
|
|
Query_Slot *slot = set->free_slot;
|
|
|
|
if (slot != 0){
|
|
|
|
set->free_slot = slot->next;
|
|
|
|
slot->next = set->used_slot;
|
|
|
|
set->used_slot = slot;
|
|
|
|
}
|
|
|
|
return(slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
free_query_slot(Query_Set *set, Query_Bar *match_bar){
|
|
|
|
Query_Slot *slot = 0, *prev = 0;
|
|
|
|
|
|
|
|
for (slot = set->used_slot; slot != 0; slot = slot->next){
|
|
|
|
if (slot->query_bar == match_bar) break;
|
|
|
|
prev = slot;
|
|
|
|
}
|
2016-04-02 19:35:33 +00:00
|
|
|
|
2016-02-27 07:44:17 +00:00
|
|
|
if (slot){
|
|
|
|
if (prev){
|
|
|
|
prev->next = slot->next;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
set->used_slot = slot->next;
|
|
|
|
}
|
|
|
|
slot->next = set->free_slot;
|
|
|
|
set->free_slot = slot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 21:25:56 +00:00
|
|
|
struct Super_Color{
|
|
|
|
Vec4 hsla;
|
|
|
|
Vec4 rgba;
|
|
|
|
u32 *out;
|
|
|
|
};
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
struct GUI_id{
|
|
|
|
u64 id[1];
|
|
|
|
};
|
|
|
|
|
2016-04-02 19:35:33 +00:00
|
|
|
struct GUI_Scroll_Vars{
|
|
|
|
f32 scroll_y;
|
|
|
|
f32 target_y;
|
|
|
|
f32 prev_target_y;
|
|
|
|
f32 min_y, max_y;
|
|
|
|
|
|
|
|
f32 scroll_x;
|
|
|
|
f32 target_x;
|
|
|
|
f32 prev_target_x;
|
|
|
|
|
|
|
|
i32_Rect region;
|
|
|
|
};
|
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
struct GUI_Target{
|
|
|
|
Partition push;
|
2016-03-31 04:05:47 +00:00
|
|
|
|
|
|
|
GUI_id active;
|
|
|
|
GUI_id hot;
|
|
|
|
GUI_id hover;
|
|
|
|
|
2016-04-02 19:35:33 +00:00
|
|
|
GUI_Scroll_Vars scroll_original;
|
|
|
|
GUI_Scroll_Vars scroll_updated;
|
|
|
|
f32 delta;
|
2016-03-31 17:13:40 +00:00
|
|
|
u32 scroll_id;
|
2016-03-01 21:25:56 +00:00
|
|
|
};
|
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
struct GUI_Header{
|
|
|
|
i32 type;
|
|
|
|
i32 size;
|
2016-03-01 21:25:56 +00:00
|
|
|
};
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
struct GUI_Interactive{
|
|
|
|
GUI_Header h;
|
|
|
|
GUI_id id;
|
|
|
|
};
|
|
|
|
|
2016-04-03 19:45:28 +00:00
|
|
|
struct GUI_Edit{
|
|
|
|
GUI_Header h;
|
|
|
|
void *out;
|
|
|
|
};
|
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
enum GUI_Command_Type{
|
|
|
|
guicom_null,
|
|
|
|
guicom_begin_overlap,
|
|
|
|
guicom_end_overlap,
|
|
|
|
guicom_begin_serial,
|
|
|
|
guicom_end_serial,
|
|
|
|
guicom_top_bar,
|
|
|
|
guicom_file,
|
2016-03-31 04:05:47 +00:00
|
|
|
guicom_text_field,
|
2016-04-03 19:45:28 +00:00
|
|
|
guicom_file_input,
|
2016-03-31 04:05:47 +00:00
|
|
|
guicom_file_option,
|
|
|
|
guicom_scrollable,
|
|
|
|
guicom_scrollable_top,
|
|
|
|
guicom_scrollable_slider,
|
|
|
|
guicom_scrollable_bottom,
|
2016-04-03 18:48:50 +00:00
|
|
|
guicom_scrollable_section_begin,
|
|
|
|
guicom_scrollable_section_end,
|
2016-03-01 21:25:56 +00:00
|
|
|
};
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
internal b32
|
|
|
|
gui_id_eq(GUI_id id1, GUI_id id2){
|
|
|
|
b32 result = (id1.id[0] == id2.id[0]);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal b32
|
|
|
|
gui_id_is_null(GUI_id id){
|
|
|
|
b32 result = (id.id[0] == 0);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal i32
|
|
|
|
gui_active_level(GUI_Target *target, GUI_id id){
|
|
|
|
i32 level = 0;
|
|
|
|
if (gui_id_eq(target->active, id)){
|
|
|
|
level = 4;
|
|
|
|
}
|
|
|
|
else if (gui_id_eq(target->hot, id)){
|
|
|
|
if (gui_id_eq(target->hover, id)){
|
|
|
|
level = 3;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
level = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (gui_id_eq(target->hover, id) && gui_id_is_null(target->hot)){
|
|
|
|
level = 1;
|
|
|
|
}
|
|
|
|
return(level);
|
|
|
|
}
|
|
|
|
|
2016-03-26 23:13:58 +00:00
|
|
|
internal void*
|
2016-03-31 04:05:47 +00:00
|
|
|
gui_push_item(GUI_Target *target, void *item, i32 size){
|
2016-03-26 08:06:41 +00:00
|
|
|
void *dest = partition_allocate(&target->push, size);
|
2016-03-31 04:05:47 +00:00
|
|
|
if (dest && item){
|
2016-03-26 08:06:41 +00:00
|
|
|
memcpy(dest, item, size);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
2016-03-26 23:13:58 +00:00
|
|
|
return(dest);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-26 23:13:58 +00:00
|
|
|
internal void*
|
|
|
|
gui_align(GUI_Target *target){
|
|
|
|
void *ptr;
|
|
|
|
partition_align(&target->push, 8);
|
|
|
|
ptr = partition_current(&target->push);
|
|
|
|
return(ptr);
|
|
|
|
}
|
|
|
|
|
2016-03-31 17:13:40 +00:00
|
|
|
internal void*
|
|
|
|
advance_to_alignment(void *ptr){
|
|
|
|
u64 p = (u64)ptr;
|
|
|
|
p = (p + 7) & (~7);
|
|
|
|
return (void*)p;
|
|
|
|
}
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
internal void*
|
|
|
|
gui_push_aligned_item(GUI_Target *target, GUI_Header *h, void *item, i32 size){
|
|
|
|
char *start, *end;
|
|
|
|
start = (char*)partition_allocate(&target->push, size);
|
|
|
|
if (start){
|
|
|
|
memcpy(start, item, size);
|
|
|
|
}
|
|
|
|
end = (char*)gui_align(target);
|
|
|
|
size = (i32)(end - start);
|
|
|
|
h->size += size;
|
|
|
|
return(start);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void*
|
|
|
|
gui_push_item(GUI_Target *target, GUI_Header *h, void *item, i32 size){
|
|
|
|
void *ptr;
|
|
|
|
ptr = (char*)partition_allocate(&target->push, size);
|
|
|
|
if (ptr){
|
|
|
|
memcpy(ptr, item, size);
|
|
|
|
}
|
|
|
|
h->size += size;
|
|
|
|
return(ptr);
|
|
|
|
}
|
|
|
|
|
2016-03-26 23:13:58 +00:00
|
|
|
internal GUI_Header*
|
2016-03-26 08:06:41 +00:00
|
|
|
gui_push_simple_command(GUI_Target *target, i32 type){
|
2016-03-26 23:13:58 +00:00
|
|
|
GUI_Header *result = 0;
|
2016-03-26 08:06:41 +00:00
|
|
|
GUI_Header item;
|
|
|
|
item.type = type;
|
|
|
|
item.size = sizeof(item);
|
2016-03-31 04:05:47 +00:00
|
|
|
result = (GUI_Header*)gui_push_item(target, &item, sizeof(item));
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2016-04-03 19:45:28 +00:00
|
|
|
internal GUI_Edit*
|
|
|
|
gui_push_string_edit_command(GUI_Target *target, i32 type, void *out){
|
|
|
|
GUI_Edit *result = 0;
|
|
|
|
GUI_Edit item;
|
|
|
|
item.h.type = type;
|
|
|
|
item.h.size = sizeof(item);
|
|
|
|
item.out = out;
|
|
|
|
result = (GUI_Edit*)gui_push_item(target, &item, sizeof(item));
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
internal GUI_Interactive*
|
|
|
|
gui_push_button_command(GUI_Target *target, i32 type, GUI_id id){
|
|
|
|
GUI_Interactive *result = 0;
|
|
|
|
GUI_Interactive item;
|
|
|
|
item.h.type = type;
|
|
|
|
item.h.size = sizeof(item);
|
|
|
|
item.id = id;
|
|
|
|
result = (GUI_Interactive*)gui_push_item(target, &item, sizeof(item));
|
2016-03-26 08:06:41 +00:00
|
|
|
return(result);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-26 23:13:58 +00:00
|
|
|
internal void
|
2016-03-31 17:13:40 +00:00
|
|
|
gui_push_string(GUI_Target *target, GUI_Header *h, String s, i32 extra){
|
|
|
|
u8 *start, *end, *str_start;
|
2016-03-26 23:13:58 +00:00
|
|
|
i32 size;
|
2016-03-31 17:13:40 +00:00
|
|
|
i32 *cap;
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
start = (u8*)gui_push_item(target, &s.size, sizeof(s.size));
|
2016-03-31 17:13:40 +00:00
|
|
|
cap = (i32*)gui_push_item(target, 0, sizeof(i32));
|
|
|
|
str_start = (u8*)gui_push_item(target, s.str, s.size);
|
|
|
|
if (extra) gui_push_item(target, 0, extra);
|
2016-03-31 04:05:47 +00:00
|
|
|
end = (u8*)gui_align(target);
|
|
|
|
size = (i32)(end - start);
|
2016-03-31 17:13:40 +00:00
|
|
|
*cap = (i32)(end - str_start);
|
2016-03-31 04:05:47 +00:00
|
|
|
h->size += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2016-03-31 17:13:40 +00:00
|
|
|
gui_push_string(GUI_Target *target, GUI_Header *h, String s){
|
|
|
|
gui_push_string(target, h, s, 0);
|
2016-03-26 23:13:58 +00:00
|
|
|
}
|
|
|
|
|
2016-03-01 21:25:56 +00:00
|
|
|
internal void
|
2016-03-26 08:06:41 +00:00
|
|
|
gui_begin_overlap(GUI_Target *target){
|
|
|
|
gui_push_simple_command(target, guicom_begin_overlap);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
internal void
|
|
|
|
gui_end_overlap(GUI_Target *target){
|
|
|
|
gui_push_simple_command(target, guicom_end_overlap);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2016-03-26 08:06:41 +00:00
|
|
|
gui_begin_serial_section(GUI_Target *target){
|
|
|
|
gui_push_simple_command(target, guicom_begin_serial);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2016-03-26 08:06:41 +00:00
|
|
|
gui_end_serial_section(GUI_Target *target){
|
|
|
|
gui_push_simple_command(target, guicom_end_serial);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
2016-04-03 18:48:50 +00:00
|
|
|
internal void
|
|
|
|
gui_begin_top_level(GUI_Target *target){
|
|
|
|
target->push.pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
gui_end_top_level(GUI_Target *target){
|
|
|
|
gui_push_simple_command(target, guicom_null);
|
|
|
|
}
|
|
|
|
|
2016-03-01 21:25:56 +00:00
|
|
|
internal void
|
2016-03-26 08:06:41 +00:00
|
|
|
gui_do_top_bar(GUI_Target *target){
|
|
|
|
gui_push_simple_command(target, guicom_top_bar);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2016-03-26 08:06:41 +00:00
|
|
|
gui_do_file(GUI_Target *target){
|
|
|
|
gui_push_simple_command(target, guicom_file);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-26 23:13:58 +00:00
|
|
|
internal void
|
2016-03-31 04:05:47 +00:00
|
|
|
gui_do_text_field(GUI_Target *target, String prompt, String text){
|
2016-03-26 23:13:58 +00:00
|
|
|
GUI_Header *h = gui_push_simple_command(target, guicom_text_field);
|
2016-03-31 04:05:47 +00:00
|
|
|
gui_push_string(target, h, prompt);
|
|
|
|
gui_push_string(target, h, text);
|
|
|
|
}
|
|
|
|
|
2016-04-03 19:45:28 +00:00
|
|
|
internal void
|
|
|
|
gui_do_file_input(GUI_Target *target, void *out){
|
|
|
|
gui_push_string_edit_command(target, guicom_file_input, out);
|
|
|
|
}
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
internal b32
|
|
|
|
gui_do_file_option(GUI_Target *target, GUI_id file_id, String filename, b32 is_folder, String message){
|
|
|
|
b32 result = 0;
|
|
|
|
|
|
|
|
GUI_Interactive *b = gui_push_button_command(target, guicom_file_option, file_id);
|
|
|
|
GUI_Header *h = (GUI_Header*)b;
|
|
|
|
gui_push_item(target, h, &is_folder, sizeof(is_folder));
|
|
|
|
gui_push_string(target, h, filename, 1);
|
|
|
|
gui_push_string(target, h, message);
|
|
|
|
|
|
|
|
if (gui_id_eq(file_id, target->active)){
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal GUI_id
|
|
|
|
gui_id_scrollbar(){
|
|
|
|
GUI_id id;
|
|
|
|
id.id[0] = max_u64;
|
|
|
|
return(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal GUI_id
|
|
|
|
gui_id_scrollbar_top(){
|
|
|
|
GUI_id id;
|
|
|
|
id.id[0] = max_u64 - 1;
|
|
|
|
return(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal GUI_id
|
|
|
|
gui_id_scrollbar_slider(){
|
|
|
|
GUI_id id;
|
|
|
|
id.id[0] = max_u64 - 2;
|
|
|
|
return(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal GUI_id
|
|
|
|
gui_id_scrollbar_bottom(){
|
|
|
|
GUI_id id;
|
|
|
|
id.id[0] = max_u64 - 3;
|
|
|
|
return(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal b32
|
2016-04-02 19:35:33 +00:00
|
|
|
gui_get_scroll_vars(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars *vars_out){
|
2016-03-31 04:05:47 +00:00
|
|
|
b32 result = 0;
|
2016-04-03 18:48:50 +00:00
|
|
|
if (target->scroll_id == scroll_id){
|
2016-04-02 19:35:33 +00:00
|
|
|
*vars_out = target->scroll_updated;
|
2016-04-03 18:48:50 +00:00
|
|
|
if (gui_id_eq(target->active, gui_id_scrollbar())){
|
|
|
|
result = 1;
|
|
|
|
}
|
2016-04-02 19:35:33 +00:00
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2016-04-03 18:48:50 +00:00
|
|
|
gui_begin_scrollable(GUI_Target *target, u32 scroll_id, GUI_Scroll_Vars scroll_vars, f32 delta){
|
2016-03-31 04:05:47 +00:00
|
|
|
GUI_Header *h;
|
|
|
|
|
2016-04-02 19:35:33 +00:00
|
|
|
target->delta = delta;
|
2016-03-31 04:05:47 +00:00
|
|
|
h = gui_push_simple_command(target, guicom_scrollable);
|
2016-04-02 19:35:33 +00:00
|
|
|
|
|
|
|
target->scroll_original = scroll_vars;
|
|
|
|
target->scroll_updated = scroll_vars;
|
2016-03-31 17:13:40 +00:00
|
|
|
target->scroll_id = scroll_id;
|
2016-03-31 04:05:47 +00:00
|
|
|
|
|
|
|
gui_push_simple_command(target, guicom_scrollable_top);
|
|
|
|
gui_push_simple_command(target, guicom_scrollable_slider);
|
|
|
|
gui_push_simple_command(target, guicom_scrollable_bottom);
|
2016-04-03 18:48:50 +00:00
|
|
|
gui_push_simple_command(target, guicom_scrollable_section_begin);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
gui_end_scrollable(GUI_Target *target){
|
|
|
|
gui_push_simple_command(target, guicom_scrollable_section_end);
|
2016-03-26 23:13:58 +00:00
|
|
|
}
|
|
|
|
|
2016-04-02 19:35:33 +00:00
|
|
|
internal void
|
|
|
|
gui_activate_scrolling(GUI_Target *target){
|
|
|
|
target->active = gui_id_scrollbar();
|
|
|
|
}
|
2016-03-01 21:25:56 +00:00
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
struct GUI_Section{
|
|
|
|
b32 overlapped;
|
2016-03-31 04:05:47 +00:00
|
|
|
i32 max_v, v;
|
2016-03-26 08:06:41 +00:00
|
|
|
};
|
2016-03-01 21:25:56 +00:00
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
struct GUI_Session{
|
|
|
|
i32_Rect full_rect;
|
|
|
|
i32_Rect clip_rect;
|
2016-03-31 04:05:47 +00:00
|
|
|
i32_Rect rect;
|
2016-04-03 18:48:50 +00:00
|
|
|
i32_Rect absolute_rect;
|
|
|
|
|
|
|
|
f32 suggested_min_y;
|
|
|
|
f32 suggested_max_y;
|
2016-03-01 21:25:56 +00:00
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
i32 line_height;
|
2016-03-31 04:05:47 +00:00
|
|
|
i32 scroll_bar_w;
|
|
|
|
b32 is_scrollable;
|
|
|
|
|
|
|
|
i32_Rect scroll_rect;
|
|
|
|
f32 scroll_top, scroll_bottom;
|
2016-03-01 21:25:56 +00:00
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
GUI_Section sections[64];
|
|
|
|
i32 t;
|
|
|
|
};
|
2016-03-01 21:25:56 +00:00
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
#define GUIScrollbarWidth 16
|
|
|
|
|
2016-03-01 21:25:56 +00:00
|
|
|
internal void
|
2016-03-26 08:06:41 +00:00
|
|
|
gui_session_init(GUI_Session *session, i32_Rect full_rect, i32 line_height){
|
|
|
|
GUI_Section *section;
|
2016-03-01 21:25:56 +00:00
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
*session = {0};
|
|
|
|
session->full_rect = full_rect;
|
|
|
|
session->line_height = line_height;
|
2016-03-31 04:05:47 +00:00
|
|
|
session->scroll_bar_w = GUIScrollbarWidth;
|
2016-03-01 21:25:56 +00:00
|
|
|
|
2016-03-26 08:06:41 +00:00
|
|
|
section = &session->sections[0];
|
|
|
|
section->v = full_rect.y0;
|
|
|
|
section->max_v = full_rect.y0;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
gui_section_end_item(GUI_Section *section, i32 v){
|
|
|
|
if (!section->overlapped){
|
|
|
|
section->v = v;
|
|
|
|
}
|
|
|
|
section->max_v = v;
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
inline i32_Rect
|
|
|
|
gui_layout_top_bottom(GUI_Session *session, i32 y0, i32 y1){
|
|
|
|
i32_Rect rect;
|
|
|
|
i32_Rect full_rect = session->full_rect;
|
|
|
|
rect.y0 = y0;
|
|
|
|
rect.y1 = y1;
|
|
|
|
rect.x0 = full_rect.x0;
|
|
|
|
rect.x1 = full_rect.x1;
|
|
|
|
if (session->is_scrollable){
|
|
|
|
rect.x1 -= session->scroll_bar_w;
|
|
|
|
}
|
|
|
|
return(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline i32_Rect
|
|
|
|
gui_layout_fixed_h(GUI_Session *session, i32 y, i32 h){
|
|
|
|
i32_Rect rect;
|
|
|
|
rect = gui_layout_top_bottom(session, y, y + h);
|
|
|
|
return(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
gui_scrollbar_top(i32_Rect bar, i32_Rect *top){
|
|
|
|
i32 w = (bar.x1 - bar.x0);
|
|
|
|
|
|
|
|
top->x0 = bar.x0;
|
|
|
|
top->x1 = bar.x1;
|
|
|
|
top->y0 = bar.y0;
|
|
|
|
top->y1 = top->y0 + w;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
gui_scrollbar_slider(i32_Rect bar, i32_Rect *slider, f32 s, f32 *min_out, f32 *max_out){
|
|
|
|
i32 w = (bar.x1 - bar.x0);
|
|
|
|
i32 min, max, pos;
|
|
|
|
|
|
|
|
slider->x0 = bar.x0;
|
|
|
|
slider->x1 = bar.x1;
|
|
|
|
|
|
|
|
min = bar.y0 + w + w/2;
|
|
|
|
max = bar.y1 - w - w/2;
|
|
|
|
|
|
|
|
pos = lerp(min, s, max);
|
|
|
|
|
|
|
|
slider->y0 = pos - w/2;
|
|
|
|
slider->y1 = slider->y0 + w;
|
|
|
|
|
|
|
|
*min_out = (f32)min;
|
|
|
|
*max_out = (f32)max;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
gui_scrollbar_bottom(i32_Rect bar, i32_Rect *bottom){
|
|
|
|
i32 w = (bar.x1 - bar.x0);
|
|
|
|
|
|
|
|
bottom->x0 = bar.x0;
|
|
|
|
bottom->x1 = bar.x1;
|
|
|
|
bottom->y1 = bar.y1;
|
|
|
|
bottom->y0 = bottom->y1 - w;
|
|
|
|
}
|
|
|
|
|
2016-03-01 21:25:56 +00:00
|
|
|
internal b32
|
2016-03-31 04:05:47 +00:00
|
|
|
gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h){
|
2016-03-26 08:06:41 +00:00
|
|
|
GUI_Section *section = 0;
|
|
|
|
GUI_Section *new_section = 0;
|
|
|
|
GUI_Section *prev_section = 0;
|
|
|
|
GUI_Section *end_section = 0;
|
|
|
|
b32 give_to_user = 0;
|
2016-04-03 18:48:50 +00:00
|
|
|
b32 always_give_to_user = 0;
|
2016-03-26 08:06:41 +00:00
|
|
|
i32_Rect rect = {0};
|
|
|
|
i32 y = 0;
|
|
|
|
i32 end_v = -1;
|
2016-04-02 19:35:33 +00:00
|
|
|
f32 lerp_space_scroll_v = 0;
|
|
|
|
i32 scroll_v = (i32)target->scroll_original.scroll_y;
|
2016-03-26 08:06:41 +00:00
|
|
|
|
|
|
|
Assert(session->t < ArrayCount(session->sections));
|
|
|
|
section = session->sections + session->t;
|
|
|
|
y = section->v;
|
|
|
|
|
2016-04-02 19:35:33 +00:00
|
|
|
if (!session->is_scrollable) scroll_v = 0;
|
2016-04-03 18:48:50 +00:00
|
|
|
|
|
|
|
switch (h->type){
|
|
|
|
case guicom_null: Assert(0); break;
|
|
|
|
|
|
|
|
case guicom_begin_overlap:
|
|
|
|
++session->t;
|
|
|
|
Assert(session->t < ArrayCount(session->sections));
|
|
|
|
new_section = &session->sections[session->t];
|
|
|
|
new_section->overlapped = 1;
|
|
|
|
new_section->v = y;
|
|
|
|
new_section->max_v = y;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_end_overlap:
|
|
|
|
Assert(session->t > 0);
|
|
|
|
Assert(section->overlapped);
|
|
|
|
prev_section = &session->sections[--session->t];
|
|
|
|
end_v = section->max_v;
|
|
|
|
end_section = prev_section;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_begin_serial:
|
|
|
|
++session->t;
|
|
|
|
Assert(session->t < ArrayCount(session->sections));
|
|
|
|
new_section = &session->sections[session->t];
|
|
|
|
new_section->overlapped = 0;
|
|
|
|
new_section->v = y;
|
|
|
|
new_section->max_v = y;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_end_serial:
|
|
|
|
Assert(session->t > 0);
|
|
|
|
Assert(!section->overlapped);
|
|
|
|
prev_section = &session->sections[--session->t];
|
|
|
|
end_v = section->max_v;
|
|
|
|
end_section = prev_section;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_top_bar:
|
|
|
|
give_to_user = 1;
|
|
|
|
rect = gui_layout_fixed_h(session, y, session->line_height + 2);
|
|
|
|
end_v = rect.y1;
|
|
|
|
end_section = section;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_file:
|
|
|
|
give_to_user = 1;
|
|
|
|
rect = gui_layout_top_bottom(session, y, session->full_rect.y1);
|
|
|
|
end_v = rect.y1;
|
|
|
|
end_section = section;
|
|
|
|
scroll_v = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_text_field:
|
|
|
|
give_to_user = 1;
|
|
|
|
rect = gui_layout_fixed_h(session, y, session->line_height + 2);
|
|
|
|
end_v = rect.y1;
|
|
|
|
end_section = section;
|
|
|
|
break;
|
2016-04-03 19:45:28 +00:00
|
|
|
|
|
|
|
case guicom_file_input:
|
|
|
|
always_give_to_user = 1;
|
|
|
|
break;
|
|
|
|
|
2016-04-03 18:48:50 +00:00
|
|
|
case guicom_file_option:
|
|
|
|
give_to_user = 1;
|
|
|
|
rect = gui_layout_fixed_h(session, y, session->line_height * 2);
|
|
|
|
end_v = rect.y1;
|
|
|
|
end_section = section;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_scrollable:
|
|
|
|
Assert(session->is_scrollable == 0);
|
|
|
|
Assert(!section->overlapped);
|
|
|
|
give_to_user = 1;
|
|
|
|
rect.x1 = session->full_rect.x1;
|
|
|
|
rect.x0 = rect.x1 - session->scroll_bar_w;
|
|
|
|
rect.y0 = y;
|
|
|
|
rect.y1 = session->full_rect.y1;
|
|
|
|
session->scroll_rect = rect;
|
|
|
|
session->is_scrollable = 1;
|
|
|
|
|
|
|
|
{
|
|
|
|
i32_Rect scrollable_rect;
|
|
|
|
scrollable_rect.x0 = session->full_rect.x0;
|
|
|
|
scrollable_rect.x1 = rect.x0;
|
|
|
|
scrollable_rect.y0 = rect.y0;
|
|
|
|
scrollable_rect.y1 = rect.y1;
|
|
|
|
|
|
|
|
target->scroll_updated.region = scrollable_rect;
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
2016-04-03 18:48:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_scrollable_top:
|
|
|
|
Assert(session->is_scrollable);
|
|
|
|
Assert(!section->overlapped);
|
|
|
|
give_to_user = 1;
|
|
|
|
gui_scrollbar_top(session->scroll_rect, &rect);
|
|
|
|
scroll_v = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_scrollable_slider:
|
|
|
|
Assert(session->is_scrollable);
|
|
|
|
Assert(!section->overlapped);
|
|
|
|
give_to_user = 1;
|
|
|
|
lerp_space_scroll_v = unlerp(
|
|
|
|
(f32)target->scroll_original.min_y, (f32)target->scroll_original.target_y, (f32)target->scroll_original.max_y);
|
|
|
|
gui_scrollbar_slider(session->scroll_rect, &rect, lerp_space_scroll_v, &session->scroll_top, &session->scroll_bottom);
|
|
|
|
scroll_v = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_scrollable_bottom:
|
|
|
|
Assert(session->is_scrollable);
|
|
|
|
Assert(!section->overlapped);
|
|
|
|
give_to_user = 1;
|
|
|
|
gui_scrollbar_bottom(session->scroll_rect, &rect);
|
|
|
|
scroll_v = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_scrollable_section_begin:
|
|
|
|
always_give_to_user = 1;
|
|
|
|
session->suggested_min_y = -(f32)(session->clip_rect.y0 - session->rect.y0);
|
|
|
|
session->suggested_max_y = (f32)(session->absolute_rect.y1 - session->full_rect.y1 * .5f);
|
|
|
|
rect = gui_layout_top_bottom(session, y, session->full_rect.y1);
|
|
|
|
end_v = rect.y1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case guicom_scrollable_section_end:
|
|
|
|
always_give_to_user = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
GUI_Section *section = session->sections;
|
|
|
|
i32 max_v = 0;
|
|
|
|
i32 i = 0;
|
|
|
|
|
|
|
|
for (i = 0; i <= session->t; ++i, ++section){
|
|
|
|
if (section->overlapped){
|
|
|
|
max_v = Max(max_v, section->max_v);
|
2016-03-31 04:05:47 +00:00
|
|
|
}
|
2016-04-03 18:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
session->absolute_rect = rect;
|
|
|
|
|
|
|
|
if (give_to_user){
|
2016-04-02 19:35:33 +00:00
|
|
|
rect.y0 -= scroll_v;
|
|
|
|
rect.y1 -= scroll_v;
|
2016-04-03 18:48:50 +00:00
|
|
|
|
2016-04-02 19:35:33 +00:00
|
|
|
if (rect.y1 > session->full_rect.y0){
|
|
|
|
session->rect = rect;
|
|
|
|
|
|
|
|
rect.y0 += scroll_v;
|
|
|
|
if (rect.y0 < max_v){
|
|
|
|
rect.y0 = max_v;
|
|
|
|
}
|
|
|
|
rect.y0 -= scroll_v;
|
|
|
|
session->clip_rect = rect;
|
2016-03-31 04:05:47 +00:00
|
|
|
}
|
2016-04-02 19:35:33 +00:00
|
|
|
else{
|
|
|
|
give_to_user = 0;
|
2016-04-03 18:48:50 +00:00
|
|
|
}
|
2016-03-31 04:05:47 +00:00
|
|
|
}
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
2016-03-26 08:06:41 +00:00
|
|
|
|
2016-04-03 18:48:50 +00:00
|
|
|
if (end_section){
|
|
|
|
gui_section_end_item(end_section, end_v);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y - scroll_v >= session->full_rect.y1){
|
|
|
|
give_to_user = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return(give_to_user || always_give_to_user);
|
2016-03-01 21:25:56 +00:00
|
|
|
}
|
2016-02-21 17:44:23 +00:00
|
|
|
|
2016-03-26 23:13:58 +00:00
|
|
|
#define NextHeader(h) ((GUI_Header*)((char*)(h) + (h)->size))
|
|
|
|
|
2016-03-31 04:05:47 +00:00
|
|
|
internal i32
|
|
|
|
gui_read_integer(void **ptr){
|
|
|
|
i32 result;
|
|
|
|
result = *(i32*)*ptr;
|
|
|
|
*ptr = ((char*)*ptr) + 4;
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal f32
|
|
|
|
gui_read_float(void **ptr){
|
|
|
|
f32 result;
|
|
|
|
result = *(f32*)*ptr;
|
|
|
|
*ptr = ((char*)*ptr) + 4;
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2016-03-26 23:13:58 +00:00
|
|
|
internal String
|
|
|
|
gui_read_string(void **ptr){
|
|
|
|
String result;
|
|
|
|
|
|
|
|
result.size = *(i32*)*ptr;
|
|
|
|
*ptr = ((i32*)*ptr) + 1;
|
2016-03-31 17:13:40 +00:00
|
|
|
result.memory_size = *(i32*)*ptr;
|
|
|
|
*ptr = ((i32*)*ptr) + 1;
|
2016-03-26 23:13:58 +00:00
|
|
|
|
2016-03-31 17:13:40 +00:00
|
|
|
result.str = (char*)*ptr;
|
|
|
|
*ptr = result.str + result.memory_size;
|
2016-03-26 23:13:58 +00:00
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
2016-02-21 17:44:23 +00:00
|
|
|
|
2016-04-03 19:45:28 +00:00
|
|
|
internal void*
|
|
|
|
gui_read_out(void **ptr){
|
|
|
|
void *result;
|
|
|
|
result = *(void**)*ptr;
|
|
|
|
*ptr = ((void**)ptr) + 1;
|
|
|
|
return(result);
|
|
|
|
}
|
2016-03-26 08:06:41 +00:00
|
|
|
|
2016-02-21 17:44:23 +00:00
|
|
|
// BOTTOM
|
|
|
|
|