#ifndef TOS_UI_LAYOUT_H #define TOS_UI_LAYOUT_H #include "../stdlib/Types.h" #include "../stdlib/HashMap.h" #include "UIElement.h" #include "../asset/Asset.h" // Modified for every scene struct UILayout { // This array has the size of the game window and represents in color codes where interactible ui elements are // Size is based on screen size (we don't need full screen size since we assume an interactible element is at least 4 pixels width and height) // width = 25% of screen size // height = 25% of screen size uint16 width; uint16 height; // Contains all UI elements also dynamic ones (e.g. movable windows) uint32* ui_chroma_codes; // Contains constant UI elements that usually don't change (e.g. HUD) uint32* ui_chroma_codes_static; // Used to directly find element by name // The values are the UIElements HashMap hash_map; int32 vertex_size; Asset* ui_asset; // @question Should we maybe also hold the font atlas asset here AND the color palette? // Defines the length of the static vertex array int32 vertex_size_static; }; inline uint32 layout_element_from_location(UILayout* layout, uint16 x, uint16 y) { return layout->ui_chroma_codes[layout->width * y / 4 + x / 4]; } // This function should only get called if the location of a UI Element changes // @performance How to handle moving elements (= dragging a window). We don't want to update this while dragging! void layout_chroma_codes_update(UILayout* layout) { // Reset all memcpy(layout->ui_chroma_codes, layout->ui_chroma_codes_static, layout->width * layout->height * sizeof(uint32)); // @question Are the dimension values below even absolute? They may be in relation to the parent?! for (int32 i = 0; i < layout->hash_map.buf.count; ++i) { if (!layout->hash_map.table[i]) { continue; } HashEntry* entry = (HashEntry *) layout->hash_map.table[i]; UIElement* element = (UIElement *) entry->value; if (element->is_dynamic) { continue; } int32 y_start = element->dimension.y1 / 4; int32 y_end = element->dimension.y2 / 4; int32 x_start = element->dimension.x1 / 4; int32 x_end = element->dimension.x2 / 4; for (int32 y = y_start; y < y_end; ++y) { int32 y_offset = layout->width * y; for (int32 x = x_start; x < x_end; ++x) { layout->ui_chroma_codes[y_offset + x] = (uint32) element->id; } } // Now handle all next elements while (entry->next) { entry = entry->next; element = (UIElement *) entry->value; y_start = element->dimension.y1 / 4; y_end = element->dimension.y2 / 4; x_start = element->dimension.x1 / 4; x_end = element->dimension.x2 / 4; for (int32 y = y_start; y < y_end; ++y) { int32 y_offset = layout->width * y; for (int32 x = x_start; x < x_end; ++x) { layout->ui_chroma_codes[y_offset + x] = (uint32) element->id; } } } } } void layout_chroma_codes_update_static(UILayout* layout) { // Reset all memset(layout->ui_chroma_codes_static, 0, layout->width * layout->height * sizeof(uint32)); // @question Are the dimension values below even absolute? They may be in relation to the parent?! for (int32 i = 0; i < layout->hash_map.buf.count; ++i) { if (!layout->hash_map.table[i]) { continue; } HashEntry* entry = (HashEntry *) layout->hash_map.table[i]; UIElement* element = (UIElement *) entry->value; if (!element->is_dynamic) { continue; } int32 y_start = element->dimension.y1 / 4; int32 y_end = element->dimension.y2 / 4; int32 x_start = element->dimension.x1 / 4; int32 x_end = element->dimension.x2 / 4; for (int32 y = y_start; y < y_end; ++y) { int32 y_offset = layout->width * y; for (int32 x = x_start; x < x_end; ++x) { layout->ui_chroma_codes_static[y_offset + x] = (uint32) element->id; } } // Now handle all next elements while (entry->next) { entry = entry->next; element = (UIElement *) entry->value; y_start = element->dimension.y1 / 4; y_end = element->dimension.y2 / 4; x_start = element->dimension.x1 / 4; x_end = element->dimension.x2 / 4; for (int32 y = y_start; y < y_end; ++y) { int32 y_offset = layout->width * y; for (int32 x = x_start; x < x_end; ++x) { layout->ui_chroma_codes_static[y_offset + x] = (uint32) element->id; } } } } } #endif