cOMS/ui/attribute/UIAttribute.h
Dennis Eichhorn eb9a135ca7
Some checks failed
CodeQL / Analyze (${{ matrix.language }}) (autobuild, c-cpp) (push) Has been cancelled
Microsoft C++ Code Analysis / Analyze (push) Has been cancelled
fixing bugs and adding some test scripts
2025-04-27 20:10:58 +00:00

293 lines
12 KiB
C++
Executable File

#ifndef COMS_UI_ATTRIBUTE_H
#define COMS_UI_ATTRIBUTE_H
#include "../../stdlib/Types.h"
#include "../../utils/StringUtils.h"
#include "../../math/Evaluator.h"
#include "../../compiler/CompilerUtils.h"
#include "UIAttributeType.h"
#include "UIAttributeDimension.h"
#include "UIAttributeFont.h"
enum UIAttributeDataType : byte {
UI_ATTRIBUTE_DATA_TYPE_INT,
UI_ATTRIBUTE_DATA_TYPE_F32,
UI_ATTRIBUTE_DATA_TYPE_STR,
UI_ATTRIBUTE_DATA_TYPE_V4_F32,
};
struct UIAttribute {
// Attributes use ids (=type name) instead of strings
UIAttributeType attribute_id;
UIAttributeDataType datatype;
union {
// @performance The string makes this struct really large when it is not needed in 95% of the cases
char value_str[32];
int32 value_int;
uint32 value_uint;
f32 value_float;
v4_f32 value_v4_f32;
};
};
struct UIAttributeGroup {
// @question Why is this a uint32 instead of uint16, I think it doesn't matter due to the alignment?!
uint32 attribute_count;
// We don't use a pointer since this would prevent us from copying around the main data owner
// The UIAttribute values come directly after UIAttributeGroup (e.g. group + 1 in memory)
//UIAttribute* attributes;
};
UIAttribute* ui_attribute_from_group(const UIAttributeGroup* group, UIAttributeType type)
{
if (!group->attribute_count) {
return NULL;
}
UIAttribute* attributes = (UIAttribute *) (group + 1);
// The following code is an optimized binary search
// @performance Consider to use EytzingerSearch for even better performance
int32 length = group->attribute_count;
while (length > 1) {
int32 half = length / 2;
length -= half;
attributes += (attributes[half - 1].attribute_id < type) * half;
}
return attributes->attribute_id == type ? attributes : NULL;
}
constexpr
int32 ui_attribute_type_to_id(const char* attribute_name)
{
if (str_compare(attribute_name, "x") == 0) {
return UI_ATTRIBUTE_TYPE_POSITION_X;
} else if (str_compare(attribute_name, "y") == 0) {
return UI_ATTRIBUTE_TYPE_POSITION_Y;
} else if (str_compare(attribute_name, "width") == 0) {
return UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH;
} else if (str_compare(attribute_name, "height") == 0) {
return UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT;
} else if (str_compare(attribute_name, "width_min") == 0) {
return UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH_MIN;
} else if (str_compare(attribute_name, "height_min") == 0) {
return UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT_MIN;
} else if (str_compare(attribute_name, "width_max") == 0) {
return UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH_MAX;
} else if (str_compare(attribute_name, "height_max") == 0) {
return UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT_MAX;
} else if (str_compare(attribute_name, "overflow") == 0) {
return UI_ATTRIBUTE_TYPE_DIMENSION_OVERFLOW;
} else if (str_compare(attribute_name, "font_name") == 0) {
return UI_ATTRIBUTE_TYPE_FONT_NAME;
} else if (str_compare(attribute_name, "font_color") == 0) {
return UI_ATTRIBUTE_TYPE_FONT_COLOR;
} else if (str_compare(attribute_name, "font_size") == 0) {
return UI_ATTRIBUTE_TYPE_FONT_SIZE;
} else if (str_compare(attribute_name, "font_weight") == 0) {
return UI_ATTRIBUTE_TYPE_FONT_WEIGHT;
} else if (str_compare(attribute_name, "font_line_height") == 0) {
return UI_ATTRIBUTE_TYPE_FONT_LINE_HEIGHT;
} else if (str_compare(attribute_name, "align_h") == 0) {
return UI_ATTRIBUTE_TYPE_ALIGN_H;
} else if (str_compare(attribute_name, "align_v") == 0) {
return UI_ATTRIBUTE_TYPE_ALIGN_V;
} else if (str_compare(attribute_name, "zindex") == 0) {
return UI_ATTRIBUTE_TYPE_ZINDEX;
} else if (str_compare(attribute_name, "style1") == 0) {
return UI_ATTRIBUTE_TYPE_STYLE1;
} else if (str_compare(attribute_name, "style2") == 0) {
return UI_ATTRIBUTE_TYPE_STYLE2;
} else if (str_compare(attribute_name, "style3") == 0) {
return UI_ATTRIBUTE_TYPE_STYLE3;
} else if (str_compare(attribute_name, "style4") == 0) {
return UI_ATTRIBUTE_TYPE_STYLE4;
} else if (str_compare(attribute_name, "style5") == 0) {
return UI_ATTRIBUTE_TYPE_STYLE5;
} else if (str_compare(attribute_name, "style6") == 0) {
return UI_ATTRIBUTE_TYPE_STYLE6;
} else if (str_compare(attribute_name, "style7") == 0) {
return UI_ATTRIBUTE_TYPE_STYLE7;
} else if (str_compare(attribute_name, "style8") == 0) {
return UI_ATTRIBUTE_TYPE_STYLE8;
} else if (str_compare(attribute_name, "foreground_color") == 0) {
return UI_ATTRIBUTE_TYPE_FOREGROUND_COLOR;
} else if (str_compare(attribute_name, "foreground_img") == 0) {
return UI_ATTRIBUTE_TYPE_FOREGROUND_IMG;
} else if (str_compare(attribute_name, "foreground_img_opacity") == 0) {
return UI_ATTRIBUTE_TYPE_FOREGROUND_IMG_OPACITY;
} else if (str_compare(attribute_name, "foreground_img_position_v") == 0) {
return UI_ATTRIBUTE_TYPE_FOREGROUND_IMG_POSITION_V;
} else if (str_compare(attribute_name, "foreground_img_position_h") == 0) {
return UI_ATTRIBUTE_TYPE_FOREGROUND_IMG_POSITION_H;
} else if (str_compare(attribute_name, "foreground_img_style") == 0) {
return UI_ATTRIBUTE_TYPE_FOREGROUND_IMG_STYLE;
} else if (str_compare(attribute_name, "background_color") == 0) {
return UI_ATTRIBUTE_TYPE_BACKGROUND_COLOR;
} else if (str_compare(attribute_name, "background_img") == 0) {
return UI_ATTRIBUTE_TYPE_BACKGROUND_IMG;
} else if (str_compare(attribute_name, "background_img_opacity") == 0) {
return UI_ATTRIBUTE_TYPE_BACKGROUND_IMG_OPACITY;
} else if (str_compare(attribute_name, "background_img_position_v") == 0) {
return UI_ATTRIBUTE_TYPE_BACKGROUND_IMG_POSITION_V;
} else if (str_compare(attribute_name, "background_img_position_h") == 0) {
return UI_ATTRIBUTE_TYPE_BACKGROUND_IMG_POSITION_H;
} else if (str_compare(attribute_name, "background_img_style") == 0) {
return UI_ATTRIBUTE_TYPE_BACKGROUND_IMG_STYLE;
} else if (str_compare(attribute_name, "border_color") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_COLOR;
} else if (str_compare(attribute_name, "border_width") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_WIDTH;
} else if (str_compare(attribute_name, "border_top_color") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_TOP_COLOR;
} else if (str_compare(attribute_name, "border_top_width") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_TOP_WIDTH;
} else if (str_compare(attribute_name, "border_right_color") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_RIGHT_COLOR;
} else if (str_compare(attribute_name, "border_right_width") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_RIGHT_WIDTH;
} else if (str_compare(attribute_name, "border_bottom_color") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_BOTTOM_COLOR;
} else if (str_compare(attribute_name, "border_bottom_width") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_BOTTOM_WIDTH;
} else if (str_compare(attribute_name, "border_left_color") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_LEFT_COLOR;
} else if (str_compare(attribute_name, "border_left_width") == 0) {
return UI_ATTRIBUTE_TYPE_BORDER_LEFT_WIDTH;
} else if (str_compare(attribute_name, "padding") == 0) {
return UI_ATTRIBUTE_TYPE_PADDING;
} else if (str_compare(attribute_name, "padding_top") == 0) {
return UI_ATTRIBUTE_TYPE_PADDING_TOP;
} else if (str_compare(attribute_name, "padding_right") == 0) {
return UI_ATTRIBUTE_TYPE_PADDING_RIGHT;
} else if (str_compare(attribute_name, "padding_bottom") == 0) {
return UI_ATTRIBUTE_TYPE_PADDING_BOTTOM;
} else if (str_compare(attribute_name, "padding_left") == 0) {
return UI_ATTRIBUTE_TYPE_PADDING_LEFT;
} else if (str_compare(attribute_name, "scroll_style") == 0) {
return UI_ATTRIBUTE_TYPE_SCROLL_STYLE;
} else if (str_compare(attribute_name, "scroll_x") == 0) {
return UI_ATTRIBUTE_TYPE_SCROLL_X;
} else if (str_compare(attribute_name, "scroll_y") == 0) {
return UI_ATTRIBUTE_TYPE_SCROLL_Y;
} else if (str_compare(attribute_name, "shadow_inner_color") == 0) {
return UI_ATTRIBUTE_TYPE_SHADOW_INNER_COLOR;
} else if (str_compare(attribute_name, "shadow_inner_angle") == 0) {
return UI_ATTRIBUTE_TYPE_SHADOW_INNER_ANGLE;
} else if (str_compare(attribute_name, "shadow_inner_distance") == 0) {
return UI_ATTRIBUTE_TYPE_SHADOW_INNER_DISTANCE;
} else if (str_compare(attribute_name, "shadow_outer_color") == 0) {
return UI_ATTRIBUTE_TYPE_SHADOW_OUTER_COLOR;
} else if (str_compare(attribute_name, "shadow_outer_angle") == 0) {
return UI_ATTRIBUTE_TYPE_SHADOW_OUTER_ANGLE;
} else if (str_compare(attribute_name, "shadow_outer_distance") == 0) {
return UI_ATTRIBUTE_TYPE_SHADOW_OUTER_DISTANCE;
} else if (str_compare(attribute_name, "transition_animation") == 0) {
return UI_ATTRIBUTE_TYPE_TRANSITION_ANIMATION;
} else if (str_compare(attribute_name, "transition_duration") == 0) {
return UI_ATTRIBUTE_TYPE_TRANSITION_DURATION;
} else if (str_compare(attribute_name, "text_limit") == 0) {
return UI_ATTRIBUTE_TYPE_TEXT_LIMIT;
} else if (str_compare(attribute_name, "cache_size") == 0) {
return UI_ATTRIBUTE_TYPE_CACHE_SIZE;
} else if (str_compare(attribute_name, "anim") == 0) {
return UI_ATTRIBUTE_TYPE_ANIMATION;
} else if (str_compare(attribute_name, "vertex_count") == 0) {
return UI_ATTRIBUTE_TYPE_VERTEX_COUNT;
}
ASSERT_SIMPLE(false);
return -1;
}
inline
void ui_attribute_parse_value(UIAttribute* attr, const char* attribute_name, const char* pos)
{
attr->attribute_id = (UIAttributeType) ui_attribute_type_to_id(attribute_name);
char value[64];
str_copy_until(value, pos, "\r\n");
if (str_is_integer(value)) {
attr->value_int = (int32) str_to_int(value);
attr->datatype = UI_ATTRIBUTE_DATA_TYPE_INT;
} else if (str_is_float(value)) {
attr->value_float = str_to_float(value, NULL);
attr->datatype = UI_ATTRIBUTE_DATA_TYPE_F32;
} else if (str_is_hex_color(value)) {
++pos; // Skip '#'
hexstr_to_rgba(&attr->value_v4_f32, pos);
attr->datatype = UI_ATTRIBUTE_DATA_TYPE_V4_F32;
} else {
str_copy_until(attr->value_str, value, "\r\n");
attr->datatype = UI_ATTRIBUTE_DATA_TYPE_STR;
}
}
inline
void ui_theme_assign_f32(f32* a, const UIAttribute* attr)
{
if (attr->datatype == UI_ATTRIBUTE_DATA_TYPE_INT) {
*a = (f32) attr->value_int;
} else if (attr->datatype == UI_ATTRIBUTE_DATA_TYPE_F32) {
*a = (f32) attr->value_float;
} else if (attr->datatype == UI_ATTRIBUTE_DATA_TYPE_STR) {
ASSERT_SIMPLE(str_length(attr->value_str) > 0);
char value[32];
memcpy(value, attr->value_str, ARRAY_COUNT(attr->value_str));
*a = (f32) evaluator_evaluate(value);
}
}
inline
void ui_theme_assign_dimension(UIAttributeDimension* dimension, const UIAttribute* attr)
{
switch (attr->attribute_id) {
case UI_ATTRIBUTE_TYPE_POSITION_X: {
ui_theme_assign_f32(&dimension->dimension.x, attr);
} break;
case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH: {
ui_theme_assign_f32(&dimension->dimension.width, attr);
} break;
case UI_ATTRIBUTE_TYPE_POSITION_Y: {
ui_theme_assign_f32(&dimension->dimension.y, attr);
} break;
case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: {
ui_theme_assign_f32(&dimension->dimension.height, attr);
} break;
default: {
UNREACHABLE();
}
}
}
inline
void ui_theme_assign_font(UIAttributeFont* font, const UIAttribute* attr)
{
switch (attr->attribute_id) {
case UI_ATTRIBUTE_TYPE_FONT_NAME: {
UNREACHABLE();
} break;
case UI_ATTRIBUTE_TYPE_FONT_COLOR: {
font->color = attr->value_uint;
} break;
case UI_ATTRIBUTE_TYPE_FONT_SIZE: {
font->size = attr->value_float;
} break;
case UI_ATTRIBUTE_TYPE_FONT_WEIGHT: {
font->weight = attr->value_float;
} break;
case UI_ATTRIBUTE_TYPE_FONT_LINE_HEIGHT: {
font->line_height = attr->value_float;
} break;
default: {
UNREACHABLE();
}
}
}
#endif