Created
July 30, 2025 02:19
-
-
Save linkdd/03389d8907c0cef7d07f551865b54d8f to your computer and use it in GitHub Desktop.
Revisions
-
linkdd created this gist
Jul 30, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,16 @@ # See - Clay: https://github.com/nicbarker/clay - Lexy: https://lexy.foonathan.net/ # What is this? I made a parser for a CSS dialect (with far less features) to style my C++ game UI (which is made with Clay). Why? Well, plenty of reasons why not, so I'll just say: - for the fun - because maintaining the UI style in C++ was a pain - for the FUN Should you do this? Absolutely not. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,138 @@ element#root { layout-sizing-width: grow(0, 0); layout-sizing-height: grow(0, 0); layout-direction: left-to-right; image: 'textures/backgrounds/main-menu.png'; background-color: rgba(0, 0, 0, 255); } element#gap { layout-sizing-width: 5%; layout-sizing-height: grow(0, 0); } element#menu { layout-sizing-width: 15%; layout-sizing-height: grow(0, 0); layout-direction: top-to-bottom; layout-padding: 16; layout-child-gap: 24; background-color: rgba(16, 16, 16, 196); border-width: outside(2); border-color: rgba(96, 96, 96, 255); } element#container { layout-sizing-width: grow(0, 0); layout-sizing-height: grow(0, 0); layout-padding: 64; } element#window { layout-sizing-width: 100%; layout-sizing-height: grow(0, 0); layout-direction: top-to-bottom; layout-padding: 16; layout-child-gap: 16; background-color: rgba(16, 16, 16, 196); border-width: outside(2); border-color: rgba(96, 96, 96, 255); } element#form { layout-sizing-width: grow(0, 0); layout-sizing-height: grow(0, 0); layout-direction: top-to-bottom; layout-child-alignment-x: center; layout-child-alignment-y: top; layout-padding: 8; layout-child-gap: 8; } element#form-field { layout-sizing-width: grow(0, 0); layout-sizing-height: fit(0, 0); layout-direction: left-to-right; layout-child-alignment-x: left; layout-child-alignment-y: center; layout-padding: 8; layout-child-gap: 8; } text#form-field-label { font-face: 'fonts/Unitblock.ttf'; font-size: 18; color: rgba(255, 193, 140, 255); } text#form-field-error { font-face: 'fonts/Unitblock.ttf'; font-size: 18; color: rgba(218, 109, 66, 255); } input#form-field-control { &.container { layout-sizing-width: grow(0, 0); layout-sizing-height: 36; layout-child-alignment-x: left; layout-child-alignment-y: center; layout-padding: 8; background-color: rgba(16, 16, 16, 255); border-width: outside(2); border-color: rgba(96, 96, 96, 255); &:hover { border-color: rgba(132, 36, 12, 255); } &:active { border-color: rgba(218, 109, 66, 255); } } &.content { font-face: 'fonts/Unitblock.ttf'; font-size: 18; color: rgba(204, 204, 204, 255); } } element#form-button-group { layout-sizing-width: grow(0, 0); layout-sizing-height: fit(0, 0); layout-direction: left-to-right; layout-child-alignment-x: center; layout-child-alignment-y: center; layout-padding: 8; layout-child-gap: 64; } button#primary { &.container { layout-sizing-width: grow(0, 0); layout-sizing-height: 48; layout-child-alignment-x: center; layout-child-alignment-y: center; background-color: rgba(86, 50, 50, 255); &:hover { background-color: rgba(132, 36, 12, 255); } &:active { background-color: rgba(218, 109, 66, 255); } } &.label { font-face: 'fonts/Unitblock.ttf'; font-size: 24; color: rgba(255, 193, 140, 255); } } element#separator { layout-sizing-width: grow(0, 0); layout-sizing-height: grow(0, 0); } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,20 @@ #include <lexy/action/parse.hpp> #include <lexy/input/string_input.hpp> #include <lexy_ext/report_error.hpp> #include <engine/ui/styles/parser.hpp> namespace engine::ui::styles::parser { stylesheet eval(manager& ui_manager, const std::string& source) { auto input = lexy::string_input(source); auto result = lexy::parse<document>(input, ui_manager, lexy_ext::report_error); if (result.has_value()) { return result.value(); } else { throw std::runtime_error{"Failed to parse stylesheet"}; } } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,1510 @@ #pragma once #include <cstdint> #include <sstream> #include <string> #include <filesystem> #include <utility> #include <functional> #include <vector> #include <lexy/dsl.hpp> #include <lexy/callback.hpp> #include <clay.h> #include <engine/ui/styles/types.hpp> #include <engine/ui/manager.hpp> namespace engine::ui::styles::parser { namespace dsl = lexy::dsl; namespace basic { // MARK: identifier struct identifier { static constexpr auto rule = dsl::identifier( dsl::ascii::alpha, dsl::ascii::alpha_digit_underscore / dsl::lit_c<'-'> ); static constexpr auto value = lexy::as_string<std::string>; }; // MARK: boolean struct boolean { struct true_ { static constexpr auto rule = LEXY_LIT("true"); static constexpr auto value = lexy::constant(true); }; struct false_ { static constexpr auto rule = LEXY_LIT("false"); static constexpr auto value = lexy::constant(false); }; static constexpr auto rule = dsl::p<true_> | dsl::p<false_>; static constexpr auto value = lexy::forward<bool>; }; // MARK: float struct float_ { static constexpr auto rule = dsl::sign + dsl::integer<int> + dsl::opt(dsl::lit_c<'.'> >> dsl::integer<int>) ; static constexpr auto value = lexy::callback<float>( [](lexy::minus_sign, int i, int d) -> float { auto result = 0.0f; auto oss = std::ostringstream{}; oss << "-" << i << "." << d; auto iss = std::istringstream{oss.str()}; iss >> result; return result; }, [](lexy::minus_sign, int i, lexy::nullopt) -> float { return -static_cast<float>(i); }, [](lexy::plus_sign, int i, int d) -> float { auto result = 0.0f; auto oss = std::ostringstream{}; oss << i << "." << d; auto iss = std::istringstream{oss.str()}; iss >> result; return result; }, [](lexy::plus_sign, int i, lexy::nullopt) -> float { return static_cast<float>(i); }, [](int i, int d) -> float { auto result = 0.0f; auto oss = std::ostringstream{}; oss << i << "." << d; auto iss = std::istringstream{oss.str()}; iss >> result; return result; }, [](int i, lexy::nullopt) -> float { return static_cast<float>(i); } ); }; // MARK: color struct color { static constexpr auto rule = LEXY_LIT("rgba") + dsl::parenthesized(dsl::times<4>(dsl::p<float_>, dsl::sep(dsl::comma))) ; static constexpr auto value = lexy::construct<Clay_Color>; }; // MARK: str struct str { static constexpr auto rule = dsl::single_quoted(dsl::ascii::print); static constexpr auto value = lexy::as_string<std::string>; }; } namespace property_set { template <typename T> struct as_property { struct _property_value { static constexpr auto rule = T::property_value_rule; static constexpr auto value = T::property_value_eval; }; static constexpr auto rule = T::property_name_rule >> dsl::lit_c<':'> >> dsl::p<_property_value> >> dsl::lit_c<';'> ; using property_value_type = std::pair<T, typename T::property_value_type>; static constexpr auto value = lexy::callback<property_value_type>( [](typename T::property_value_type value) { return std::make_pair(T{}, value); } ); }; // MARK: elt props struct element_properties { struct _layout_sizing_axis { using property_value_type = Clay_SizingAxis; struct fit_value { static constexpr auto rule = LEXY_LIT("fit") >> dsl::parenthesized(dsl::times<2>(dsl::p<basic::float_>, dsl::sep(dsl::comma))) ; static constexpr auto value = lexy::callback<property_value_type>( [](float min, float max) { return CLAY_SIZING_FIT(min, max); } ); }; struct grow_value { static constexpr auto rule = LEXY_LIT("grow") >> dsl::parenthesized(dsl::times<2>(dsl::p<basic::float_>, dsl::sep(dsl::comma))) ; static constexpr auto value = lexy::callback<property_value_type>( [](float min, float max) { return CLAY_SIZING_GROW(min, max); } ); }; struct percent_value { static constexpr auto rule = dsl::p<basic::float_> + LEXY_LIT("%") ; static constexpr auto value = lexy::callback<property_value_type>( [](float percent) { return CLAY_SIZING_PERCENT(percent / 100.0f); } ); }; struct fixed_value { static constexpr auto rule = dsl::p<basic::float_>; static constexpr auto value = lexy::callback<property_value_type>( [](float size) { return CLAY_SIZING_FIXED(size); } ); }; static constexpr auto property_value_rule = dsl::p<fit_value> | dsl::p<grow_value> | dsl::peek(dsl::p<percent_value>) >> dsl::p<percent_value> | dsl::peek(dsl::p<fixed_value>) >> dsl::p<fixed_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; struct layout_sizing_width : public _layout_sizing_axis { static constexpr auto property_name_rule = LEXY_LIT("layout-sizing-width"); }; using prop_layout_sizing_width = as_property<layout_sizing_width>; struct layout_sizing_height : public _layout_sizing_axis { static constexpr auto property_name_rule = LEXY_LIT("layout-sizing-height"); }; using prop_layout_sizing_height = as_property<layout_sizing_height>; struct layout_padding { using property_value_type = Clay_Padding; static constexpr auto property_name_rule = LEXY_LIT("layout-padding"); static constexpr auto property_value_rule = dsl::integer<uint16_t>; static constexpr auto property_value_eval = lexy::callback<property_value_type>([](uint16_t padding) { return CLAY_PADDING_ALL(padding); }); }; using prop_layout_padding = as_property<layout_padding>; struct layout_padding_left { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("layout-padding-left"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_layout_padding_left = as_property<layout_padding_left>; struct layout_padding_right { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("layout-padding-right"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_layout_padding_right = as_property<layout_padding_right>; struct layout_padding_top { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("layout-padding-top"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_layout_padding_top = as_property<layout_padding_top>; struct layout_padding_bottom { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("layout-padding-bottom"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_layout_padding_bottom = as_property<layout_padding_bottom>; struct layout_child_gap { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("layout-child-gap"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_layout_child_gap = as_property<layout_child_gap>; struct layout_child_alignment_x { using property_value_type = Clay_LayoutAlignmentX; struct left_value { static constexpr auto rule = LEXY_LIT("left"); static constexpr auto value = lexy::constant(CLAY_ALIGN_X_LEFT); }; struct center_value { static constexpr auto rule = LEXY_LIT("center"); static constexpr auto value = lexy::constant(CLAY_ALIGN_X_CENTER); }; struct right_value { static constexpr auto rule = LEXY_LIT("right"); static constexpr auto value = lexy::constant(CLAY_ALIGN_X_RIGHT); }; static constexpr auto property_name_rule = LEXY_LIT("layout-child-alignment-x"); static constexpr auto property_value_rule = dsl::p<left_value> | dsl::p<center_value> | dsl::p<right_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_layout_child_alignment_x = as_property<layout_child_alignment_x>; struct layout_child_alignment_y { using property_value_type = Clay_LayoutAlignmentY; struct top_value { static constexpr auto rule = LEXY_LIT("top"); static constexpr auto value = lexy::constant(CLAY_ALIGN_Y_TOP); }; struct center_value { static constexpr auto rule = LEXY_LIT("center"); static constexpr auto value = lexy::constant(CLAY_ALIGN_Y_CENTER); }; struct bottom_value { static constexpr auto rule = LEXY_LIT("bottom"); static constexpr auto value = lexy::constant(CLAY_ALIGN_Y_BOTTOM); }; static constexpr auto property_name_rule = LEXY_LIT("layout-child-alignment-y"); static constexpr auto property_value_rule = dsl::p<top_value> | dsl::p<center_value> | dsl::p<bottom_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_layout_child_alignment_y = as_property<layout_child_alignment_y>; struct layout_direction { using property_value_type = Clay_LayoutDirection; struct left_to_right_value { static constexpr auto rule = LEXY_LIT("left-to-right"); static constexpr auto value = lexy::constant(CLAY_LEFT_TO_RIGHT); }; struct top_to_bottom_value { static constexpr auto rule = LEXY_LIT("top-to-bottom"); static constexpr auto value = lexy::constant(CLAY_TOP_TO_BOTTOM); }; static constexpr auto property_name_rule = LEXY_LIT("layout-direction"); static constexpr auto property_value_rule = dsl::p<left_to_right_value> | dsl::p<top_to_bottom_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_layout_direction = as_property<layout_direction>; struct background_color { using property_value_type = Clay_Color; static constexpr auto property_name_rule = LEXY_LIT("background-color"); static constexpr auto property_value_rule = dsl::p<basic::color>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_background_color = as_property<background_color>; struct corner_radius { using property_value_type = Clay_CornerRadius; static constexpr auto property_name_rule = LEXY_LIT("corner-radius"); static constexpr auto property_value_rule = dsl::times<4>(dsl::p<basic::float_>); static constexpr auto property_value_eval = lexy::construct<property_value_type>; }; using prop_corner_radius = as_property<corner_radius>; struct corner_radius_top_left { using property_value_type = float; static constexpr auto property_name_rule = LEXY_LIT("corner-radius-top-left"); static constexpr auto property_value_rule = dsl::p<basic::float_>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_corner_radius_top_left = as_property<corner_radius_top_left>; struct corner_radius_top_right { using property_value_type = float; static constexpr auto property_name_rule = LEXY_LIT("corner-radius-top-right"); static constexpr auto property_value_rule = dsl::p<basic::float_>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_corner_radius_top_right = as_property<corner_radius_top_right>; struct corner_radius_bottom_left { using property_value_type = float; static constexpr auto property_name_rule = LEXY_LIT("corner-radius-bottom-left"); static constexpr auto property_value_rule = dsl::p<basic::float_>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_corner_radius_bottom_left = as_property<corner_radius_bottom_left>; struct corner_radius_bottom_right { using property_value_type = float; static constexpr auto property_name_rule = LEXY_LIT("corner-radius-bottom-right"); static constexpr auto property_value_rule = dsl::p<basic::float_>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_corner_radius_bottom_right = as_property<corner_radius_bottom_right>; struct aspect_ratio { using property_value_type = Clay_AspectRatioElementConfig; static constexpr auto property_name_rule = LEXY_LIT("aspect-ratio"); static constexpr auto property_value_rule = dsl::p<basic::float_>; static constexpr auto property_value_eval = lexy::construct<property_value_type>; }; using prop_aspect_ratio = as_property<aspect_ratio>; struct image { using property_value_type = std::filesystem::path; static constexpr auto property_name_rule = LEXY_LIT("image"); static constexpr auto property_value_rule = dsl::p<basic::str>; static constexpr auto property_value_eval = lexy::construct<property_value_type>; }; using prop_image = as_property<image>; struct floating_offset { using property_value_type = Clay_Vector2; static constexpr auto property_name_rule = LEXY_LIT("floating-offset"); static constexpr auto property_value_rule = dsl::times<2>(dsl::p<basic::float_>); static constexpr auto property_value_eval = lexy::construct<property_value_type>; }; using prop_floating_offset = as_property<floating_offset>; struct floating_expand { using property_value_type = Clay_Dimensions; static constexpr auto property_name_rule = LEXY_LIT("floating-expand"); static constexpr auto property_value_rule = dsl::times<2>(dsl::p<basic::float_>); static constexpr auto property_value_eval = lexy::construct<property_value_type>; }; using prop_floating_expand = as_property<floating_expand>; struct floating_zindex { using property_value_type = int16_t; static constexpr auto property_name_rule = LEXY_LIT("floating-zindex"); static constexpr auto property_value_rule = dsl::integer<int16_t>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_floating_zindex = as_property<floating_zindex>; struct _floating_attach_point_type { using property_value_type = Clay_FloatingAttachPointType; struct left_top_value { static constexpr auto rule = LEXY_LIT("left-top"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_LEFT_TOP); }; struct left_center_value { static constexpr auto rule = LEXY_LIT("left-center"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_LEFT_CENTER); }; struct left_bottom_value { static constexpr auto rule = LEXY_LIT("left-bottom"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_LEFT_BOTTOM); }; struct center_top_value { static constexpr auto rule = LEXY_LIT("center-top"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_CENTER_TOP); }; struct center_center_value { static constexpr auto rule = LEXY_LIT("center-center"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_CENTER_CENTER); }; struct center_bottom_value { static constexpr auto rule = LEXY_LIT("center-bottom"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_CENTER_BOTTOM); }; struct right_top_value { static constexpr auto rule = LEXY_LIT("right-top"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_RIGHT_TOP); }; struct right_center_value { static constexpr auto rule = LEXY_LIT("right-center"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_RIGHT_CENTER); }; struct right_bottom_value { static constexpr auto rule = LEXY_LIT("right-bottom"); static constexpr auto value = lexy::constant(CLAY_ATTACH_POINT_RIGHT_BOTTOM); }; static constexpr auto property_value_rule = dsl::p<left_top_value> | dsl::p<left_center_value> | dsl::p<left_bottom_value> | dsl::p<center_top_value> | dsl::p<center_center_value> | dsl::p<center_bottom_value> | dsl::p<right_top_value> | dsl::p<right_center_value> | dsl::p<right_bottom_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; struct floating_attach_point_element : public _floating_attach_point_type { static constexpr auto property_name_rule = LEXY_LIT("floating-attach-point-element"); }; using prop_floating_attach_point_element = as_property<floating_attach_point_element>; struct floating_attach_point_parent : public _floating_attach_point_type { static constexpr auto property_name_rule = LEXY_LIT("floating-attach-point-parent"); }; using prop_floating_attach_point_parent = as_property<floating_attach_point_parent>; struct floating_pointer_capture_mode { using property_value_type = Clay_PointerCaptureMode; struct capture_value { static constexpr auto rule = LEXY_LIT("capture"); static constexpr auto value = lexy::constant(CLAY_POINTER_CAPTURE_MODE_CAPTURE); }; struct passthrough_value { static constexpr auto rule = LEXY_LIT("passthrough"); static constexpr auto value = lexy::constant(CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH); }; static constexpr auto property_name_rule = LEXY_LIT("floating-pointer-capture-mode"); static constexpr auto property_value_rule = dsl::p<capture_value> | dsl::p<passthrough_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_floating_pointer_capture_mode = as_property<floating_pointer_capture_mode>; struct floating_attach_to { using property_value_type = Clay_FloatingAttachToElement; struct none_value { static constexpr auto rule = LEXY_LIT("none"); static constexpr auto value = lexy::constant(CLAY_ATTACH_TO_NONE); }; struct parent_value { static constexpr auto rule = LEXY_LIT("parent"); static constexpr auto value = lexy::constant(CLAY_ATTACH_TO_PARENT); }; struct element_value { static constexpr auto rule = LEXY_LIT("element"); static constexpr auto value = lexy::constant(CLAY_ATTACH_TO_ELEMENT_WITH_ID); }; struct root_value { static constexpr auto rule = LEXY_LIT("root"); static constexpr auto value = lexy::constant(CLAY_ATTACH_TO_ROOT); }; static constexpr auto property_name_rule = LEXY_LIT("floating-attach-to"); static constexpr auto property_value_rule = dsl::p<none_value> | dsl::p<parent_value> | dsl::p<element_value> | dsl::p<root_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_floating_attach_to = as_property<floating_attach_to>; struct floating_clip_to { using property_value_type = Clay_FloatingClipToElement; struct none_value { static constexpr auto rule = LEXY_LIT("none"); static constexpr auto value = lexy::constant(CLAY_CLIP_TO_NONE); }; struct parent_value { static constexpr auto rule = LEXY_LIT("parent"); static constexpr auto value = lexy::constant(CLAY_CLIP_TO_ATTACHED_PARENT); }; static constexpr auto property_name_rule = LEXY_LIT("floating-clip-to"); static constexpr auto property_value_rule = dsl::p<none_value> | dsl::p<parent_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_floating_clip_to = as_property<floating_clip_to>; struct clip_horizontal { using property_value_type = bool; static constexpr auto property_name_rule = LEXY_LIT("clip-horizontal"); static constexpr auto property_value_rule = dsl::p<basic::boolean>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_clip_horizontal = as_property<clip_horizontal>; struct clip_vertical { using property_value_type = bool; static constexpr auto property_name_rule = LEXY_LIT("clip-vertical"); static constexpr auto property_value_rule = dsl::p<basic::boolean>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_clip_vertical = as_property<clip_vertical>; struct clip_child_offset { using property_value_type = Clay_Vector2; static constexpr auto property_name_rule = LEXY_LIT("clip-child-offset"); static constexpr auto property_value_rule = dsl::times<2>(dsl::p<basic::float_>); static constexpr auto property_value_eval = lexy::construct<property_value_type>; }; using prop_clip_child_offset = as_property<clip_child_offset>; struct border_color { using property_value_type = Clay_Color; static constexpr auto property_name_rule = LEXY_LIT("border-color"); static constexpr auto property_value_rule = dsl::p<basic::color>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_border_color = as_property<border_color>; struct border_width { using property_value_type = Clay_BorderWidth; struct outside_value { static constexpr auto rule = LEXY_LIT("outside") + dsl::parenthesized(dsl::integer<uint16_t>) ; static constexpr auto value = lexy::callback<property_value_type>( [](uint16_t width) -> property_value_type { return CLAY_BORDER_OUTSIDE(width); } ); }; struct all_value { static constexpr auto rule = LEXY_LIT("all") + dsl::parenthesized(dsl::integer<uint16_t>) ; static constexpr auto value = lexy::callback<property_value_type>( [](uint16_t width) -> property_value_type { return CLAY_BORDER_ALL(width); } ); }; static constexpr auto property_name_rule = LEXY_LIT("border-width"); static constexpr auto property_value_rule = dsl::peek(dsl::p<outside_value>) >> dsl::p<outside_value> | dsl::peek(dsl::p<all_value>) >> dsl::p<all_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_border_width = as_property<border_width>; struct border_width_left { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("border-width-left"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_border_width_left = as_property<border_width_left>; struct border_width_right { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("border-width-right"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_border_width_right = as_property<border_width_right>; struct border_width_top { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("border-width-top"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_border_width_top = as_property<border_width_top>; struct border_width_bottom { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("border-width-bottom"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_border_width_bottom = as_property<border_width_bottom>; struct border_width_between_children { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("border-width-between-children"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_border_width_between_children = as_property<border_width_between_children>; static constexpr auto rule = dsl::partial_combination( dsl::p<prop_layout_sizing_width>, dsl::p<prop_layout_sizing_height>, dsl::p<prop_layout_padding>, dsl::p<prop_layout_padding_left>, dsl::p<prop_layout_padding_right>, dsl::p<prop_layout_padding_top>, dsl::p<prop_layout_padding_bottom>, dsl::p<prop_layout_child_gap>, dsl::p<prop_layout_child_alignment_x>, dsl::p<prop_layout_child_alignment_y>, dsl::p<prop_layout_direction>, dsl::p<prop_background_color>, dsl::p<prop_corner_radius>, dsl::p<prop_corner_radius_top_left>, dsl::p<prop_corner_radius_top_right>, dsl::p<prop_corner_radius_bottom_left>, dsl::p<prop_corner_radius_bottom_right>, dsl::p<prop_aspect_ratio>, dsl::p<prop_image>, dsl::p<prop_floating_offset>, dsl::p<prop_floating_expand>, dsl::p<prop_floating_zindex>, dsl::p<prop_floating_attach_point_element>, dsl::p<prop_floating_attach_point_parent>, dsl::p<prop_floating_pointer_capture_mode>, dsl::p<prop_floating_attach_to>, dsl::p<prop_floating_clip_to>, dsl::p<prop_clip_horizontal>, dsl::p<prop_clip_vertical>, dsl::p<prop_clip_child_offset>, dsl::p<prop_border_color>, dsl::p<prop_border_width>, dsl::p<prop_border_width_left>, dsl::p<prop_border_width_right>, dsl::p<prop_border_width_top>, dsl::p<prop_border_width_bottom>, dsl::p<prop_border_width_between_children> ); using property_setter = std::function<void(manager&, element_style&)>; using property_setters = std::vector<property_setter>; static constexpr auto value = lexy::fold_inplace<property_setters>( property_setters{}, [](property_setters& setters, prop_layout_sizing_width::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.sizing.width = value; }); }, [](property_setters& setters, prop_layout_sizing_height::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.sizing.height = value; }); }, [](property_setters& setters, prop_layout_padding::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.padding = value; }); }, [](property_setters& setters, prop_layout_padding_left::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.padding.left = value; }); }, [](property_setters& setters, prop_layout_padding_right::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.padding.right = value; }); }, [](property_setters& setters, prop_layout_padding_top::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.padding.top = value; }); }, [](property_setters& setters, prop_layout_padding_bottom::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.padding.bottom = value; }); }, [](property_setters& setters, prop_layout_child_gap::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.childGap = value; }); }, [](property_setters& setters, prop_layout_child_alignment_x::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.childAlignment.x = value; }); }, [](property_setters& setters, prop_layout_child_alignment_y::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.childAlignment.y = value; }); }, [](property_setters& setters, prop_layout_direction::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.layout.layoutDirection = value; }); }, [](property_setters& setters, prop_background_color::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.backgroundColor = value; }); }, [](property_setters& setters, prop_corner_radius::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.cornerRadius = value; }); }, [](property_setters& setters, prop_corner_radius_top_left::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.cornerRadius.topLeft = value; }); }, [](property_setters& setters, prop_corner_radius_top_right::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.cornerRadius.topRight = value; }); }, [](property_setters& setters, prop_corner_radius_bottom_left::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.cornerRadius.bottomLeft = value; }); }, [](property_setters& setters, prop_corner_radius_bottom_right::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.cornerRadius.bottomRight = value; }); }, [](property_setters& setters, prop_aspect_ratio::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.aspectRatio = value; }); }, [](property_setters& setters, prop_image::property_value_type property) { setters.push_back([property](manager& ui_manager, element_style& decl) { auto [_, value] = property; auto texture_id = ui_manager.add_texture_to_atlas(value); decl.image.imageData = reinterpret_cast<void*>(static_cast<intptr_t>(texture_id)); }); }, [](property_setters& setters, prop_floating_offset::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.floating.offset = value; }); }, [](property_setters& setters, prop_floating_expand::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.floating.expand = value; }); }, [](property_setters& setters, prop_floating_zindex::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.floating.zIndex = value; }); }, [](property_setters& setters, prop_floating_attach_point_element::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.floating.attachPoints.element = value; }); }, [](property_setters& setters, prop_floating_attach_point_parent::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.floating.attachPoints.parent = value; }); }, [](property_setters& setters, prop_floating_pointer_capture_mode::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.floating.pointerCaptureMode = value; }); }, [](property_setters& setters, prop_floating_attach_to::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.floating.attachTo = value; }); }, [](property_setters& setters, prop_floating_clip_to::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.floating.clipTo = value; }); }, [](property_setters& setters, prop_clip_horizontal::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.clip.horizontal = value; }); }, [](property_setters& setters, prop_clip_vertical::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.clip.vertical = value; }); }, [](property_setters& setters, prop_clip_child_offset::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.clip.childOffset = value; }); }, [](property_setters& setters, prop_border_color::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.border.color = value; }); }, [](property_setters& setters, prop_border_width::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.border.width = value; }); }, [](property_setters& setters, prop_border_width_left::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.border.width.left = value; }); }, [](property_setters& setters, prop_border_width_right::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.border.width.right = value; }); }, [](property_setters& setters, prop_border_width_top::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.border.width.top = value; }); }, [](property_setters& setters, prop_border_width_bottom::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.border.width.bottom = value; }); }, [](property_setters& setters, prop_border_width_between_children::property_value_type property) { setters.push_back([property](manager&, element_style& decl) { auto [_, value] = property; decl.border.width.betweenChildren = value; }); } ); }; // MARK: txt props struct text_properties { struct color { using property_value_type = Clay_Color; static constexpr auto property_name_rule = LEXY_LIT("color"); static constexpr auto property_value_rule = dsl::p<basic::color>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_color = as_property<color>; struct font_face { using property_value_type = std::filesystem::path; static constexpr auto property_name_rule = LEXY_LIT("font-face"); static constexpr auto property_value_rule = dsl::p<basic::str>; static constexpr auto property_value_eval = lexy::construct<property_value_type>; }; using prop_font_face = as_property<font_face>; struct font_size { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("font-size"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_font_size = as_property<font_size>; struct letter_spacing { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("letter-spacing"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_letter_spacing = as_property<letter_spacing>; struct line_height { using property_value_type = uint16_t; static constexpr auto property_name_rule = LEXY_LIT("line-height"); static constexpr auto property_value_rule = dsl::integer<property_value_type>; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_line_height = as_property<line_height>; struct wrap_mode { using property_value_type = Clay_TextElementConfigWrapMode; struct words_value { static constexpr auto rule = LEXY_LIT("words"); static constexpr auto value = lexy::constant(CLAY_TEXT_WRAP_WORDS); }; struct newlines_value { static constexpr auto rule = LEXY_LIT("newlines"); static constexpr auto value = lexy::constant(CLAY_TEXT_WRAP_NEWLINES); }; struct none_value { static constexpr auto rule = LEXY_LIT("none"); static constexpr auto value = lexy::constant(CLAY_TEXT_WRAP_NONE); }; static constexpr auto property_name_rule = LEXY_LIT("wrap-mode"); static constexpr auto property_value_rule = dsl::p<words_value> | dsl::p<newlines_value> | dsl::p<none_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_wrap_mode = as_property<wrap_mode>; struct alignment { using property_value_type = Clay_TextAlignment; struct left_value { static constexpr auto rule = LEXY_LIT("left"); static constexpr auto value = lexy::constant(CLAY_TEXT_ALIGN_LEFT); }; struct center_value { static constexpr auto rule = LEXY_LIT("center"); static constexpr auto value = lexy::constant(CLAY_TEXT_ALIGN_CENTER); }; struct right_value { static constexpr auto rule = LEXY_LIT("right"); static constexpr auto value = lexy::constant(CLAY_TEXT_ALIGN_RIGHT); }; static constexpr auto property_name_rule = LEXY_LIT("alignment"); static constexpr auto property_value_rule = dsl::p<left_value> | dsl::p<center_value> | dsl::p<right_value> ; static constexpr auto property_value_eval = lexy::forward<property_value_type>; }; using prop_alignment = as_property<alignment>; static constexpr auto rule = dsl::partial_combination( dsl::p<prop_color>, dsl::p<prop_font_face>, dsl::p<prop_font_size>, dsl::p<prop_letter_spacing>, dsl::p<prop_line_height>, dsl::p<prop_wrap_mode>, dsl::p<prop_alignment> ); using property_setter = std::function<void(manager&, text_style&)>; using property_setters = std::vector<property_setter>; static constexpr auto value = lexy::fold_inplace<property_setters>( property_setters{}, [](property_setters& setters, prop_color::property_value_type property) { setters.push_back([property](manager&, text_style& config) { auto [_, value] = property; config.textColor = value; }); }, [](property_setters& setters, prop_font_face::property_value_type property) { setters.push_back([property](manager& manager, text_style& config) { auto [_, value] = property; auto font_id = manager.add_font_to_atlas(value); config.fontId = font_id; }); }, [](property_setters& setters, prop_font_size::property_value_type property) { setters.push_back([property](manager&, text_style& config) { auto [_, value] = property; config.fontSize = value; }); }, [](property_setters& setters, prop_letter_spacing::property_value_type property) { setters.push_back([property](manager&, text_style& config) { auto [_, value] = property; config.letterSpacing = value; }); }, [](property_setters& setters, prop_line_height::property_value_type property) { setters.push_back([property](manager&, text_style& config) { auto [_, value] = property; config.lineHeight = value; }); }, [](property_setters& setters, prop_wrap_mode::property_value_type property) { setters.push_back([property](manager&, text_style& config) { auto [_, value] = property; config.wrapMode = value; }); }, [](property_setters& setters, prop_alignment::property_value_type property) { setters.push_back([property](manager&, text_style& config) { auto [_, value] = property; config.textAlignment = value; }); } ) >> lexy::forward<property_setters>; }; // MARK: elt props state struct container_properties_with_state { static constexpr auto rule = dsl::p<property_set::element_properties> + dsl::opt(dsl::lit_c<'&'> >> dsl::lit_c<':'> >> LEXY_LIT("hover") >> dsl::curly_bracketed(dsl::p<property_set::element_properties>)) + dsl::opt(dsl::lit_c<'&'> >> dsl::lit_c<':'> >> LEXY_LIT("active") >> dsl::curly_bracketed(dsl::p<property_set::element_properties>)) ; static constexpr auto value = lexy::callback_with_state<container_style_with_state>( []( manager& ui_manager, property_set::element_properties::property_setters normal_setters, lexy::nullopt, lexy::nullopt ) { auto style = container_style_with_state{}; for (auto& setter : normal_setters) { setter(ui_manager, style.normal); } style.hovered = style.normal; style.active = style.normal; return style; }, []( manager& ui_manager, property_set::element_properties::property_setters normal_setters, property_set::element_properties::property_setters hovered_setters, lexy::nullopt ) { auto style = container_style_with_state{}; for (auto& setter : normal_setters) { setter(ui_manager, style.normal); } style.hovered = style.normal; style.active = style.normal; for (auto& setter : hovered_setters) { setter(ui_manager, style.hovered); } return style; }, []( manager& ui_manager, property_set::element_properties::property_setters normal_setters, lexy::nullopt, property_set::element_properties::property_setters active_setters ) { auto style = container_style_with_state{}; for (auto& setter : normal_setters) { setter(ui_manager, style.normal); } style.hovered = style.normal; style.active = style.normal; for (auto& setter : active_setters) { setter(ui_manager, style.active); } return style; }, []( manager& ui_manager, property_set::element_properties::property_setters normal_setters, property_set::element_properties::property_setters hovered_setters, property_set::element_properties::property_setters active_setters ) { auto style = container_style_with_state{}; for (auto& setter : normal_setters) { setter(ui_manager, style.normal); } style.hovered = style.normal; style.active = style.normal; for (auto& setter : hovered_setters) { setter(ui_manager, style.hovered); } for (auto& setter : active_setters) { setter(ui_manager, style.active); } return style; } ); }; // MARK: txt props state struct text_properties_with_state { static constexpr auto rule = dsl::p<property_set::text_properties> + dsl::opt(dsl::lit_c<'&'> >> dsl::lit_c<':'> >> LEXY_LIT("hover") >> dsl::curly_bracketed(dsl::p<property_set::text_properties>)) + dsl::opt(dsl::lit_c<'&'> >> dsl::lit_c<':'> >> LEXY_LIT("active") >> dsl::curly_bracketed(dsl::p<property_set::text_properties>)) ; static constexpr auto value = lexy::callback_with_state<text_style_with_state>( []( manager& ui_manager, property_set::text_properties::property_setters normal_setters, std::optional<property_set::text_properties::property_setters> hovered_setters, std::optional<property_set::text_properties::property_setters> active_setters ) { auto style = text_style_with_state{}; for (auto& setter : normal_setters) { setter(ui_manager, style.normal); } style.hovered = style.normal; style.active = style.normal; if (hovered_setters.has_value()) { for (auto& setter : hovered_setters.value()) { setter(ui_manager, style.hovered); } } if (active_setters.has_value()) { for (auto& setter : active_setters.value()) { setter(ui_manager, style.active); } } return style; } ); }; } namespace block { // MARK: elt block struct element_block { using block_type = std::pair<std::string, element_style>; static constexpr auto rule = LEXY_LIT("element") >> dsl::hash_sign + dsl::p<basic::identifier> + dsl::curly_bracketed(dsl::p<property_set::element_properties>) ; static constexpr auto value = lexy::callback_with_state<block_type>( [](manager& ui_manager, std::string id, property_set::element_properties::property_setters setters) { auto style = element_style{}; for (auto& setter : setters) { setter(ui_manager, style); } return block_type{id, style}; } ); }; // MARK: txt block struct text_block { using block_type = std::pair<std::string, text_style>; static constexpr auto rule = LEXY_LIT("text") >> dsl::hash_sign + dsl::p<basic::identifier> + dsl::curly_bracketed(dsl::p<property_set::text_properties>) ; static constexpr auto value = lexy::callback_with_state<block_type>( [](manager& ui_manager, std::string id, property_set::text_properties::property_setters setters) { auto style = text_style{}; for (auto& setter : setters) { setter(ui_manager, style); } return block_type{id, style}; } ); }; // MARK: button block struct button_block { using block_type = std::pair<std::string, button_style>; struct container_subblock { static constexpr auto rule = dsl::lit_c<'&'> >> dsl::lit_c<'.'> >> LEXY_LIT("container") >> dsl::curly_bracketed(dsl::p<property_set::container_properties_with_state>) ; static constexpr auto value = lexy::forward<container_style_with_state>; }; struct label_subblock { static constexpr auto rule = dsl::lit_c<'&'> >> dsl::lit_c<'.'> >> LEXY_LIT("label") >> dsl::curly_bracketed(dsl::p<property_set::text_properties_with_state>) ; static constexpr auto value = lexy::forward<text_style_with_state>; }; static constexpr auto rule = LEXY_LIT("button") >> dsl::hash_sign + dsl::p<basic::identifier> + dsl::curly_bracketed(dsl::p<container_subblock> + dsl::p<label_subblock>) ; static constexpr auto value = lexy::callback<block_type>( []( std::string id, container_style_with_state container, text_style_with_state label ) { return block_type{id, button_style{container, label}}; } ); }; // MARK: input block struct input_block { using block_type = std::pair<std::string, input_style>; struct container_subblock { static constexpr auto rule = dsl::lit_c<'&'> >> dsl::lit_c<'.'> >> LEXY_LIT("container") >> dsl::curly_bracketed(dsl::p<property_set::container_properties_with_state>) ; static constexpr auto value = lexy::forward<container_style_with_state>; }; struct content_subblock { static constexpr auto rule = dsl::lit_c<'&'> >> dsl::lit_c<'.'> >> LEXY_LIT("content") >> dsl::curly_bracketed(dsl::p<property_set::text_properties_with_state>) ; static constexpr auto value = lexy::forward<text_style_with_state>; }; static constexpr auto rule = LEXY_LIT("input") >> dsl::hash_sign + dsl::p<basic::identifier> + dsl::curly_bracketed(dsl::p<container_subblock> + dsl::p<content_subblock>) ; static constexpr auto value = lexy::callback<block_type>( []( std::string id, container_style_with_state container, text_style_with_state content ) { return block_type{id, input_style{container, content}}; } ); }; } // MARK: document struct document { using block_type = std::variant< block::element_block::block_type, block::text_block::block_type, block::button_block::block_type, block::input_block::block_type >; static constexpr auto whitespace = dsl::ascii::space; static constexpr auto rule = dsl::list( dsl::p<block::element_block> | dsl::p<block::text_block> | dsl::p<block::button_block> | dsl::p<block::input_block> ); static constexpr auto value = lexy::as_list<std::vector<block_type>> >> lexy::callback<stylesheet>( [](const std::vector<block_type>& blocks) { auto sheet = stylesheet{}; for (auto& block : blocks) { if (std::holds_alternative<block::element_block::block_type>(block)) { auto [id, style] = std::get<block::element_block::block_type>(block); sheet.elements[id] = style; } else if (std::holds_alternative<block::text_block::block_type>(block)) { auto [id, style] = std::get<block::text_block::block_type>(block); sheet.texts[id] = style; } else if (std::holds_alternative<block::button_block::block_type>(block)) { auto [id, style] = std::get<block::button_block::block_type>(block); sheet.buttons[id] = style; } else if (std::holds_alternative<block::input_block::block_type>(block)) { auto [id, style] = std::get<block::input_block::block_type>(block); sheet.inputs[id] = style; } } return sheet; } ); }; stylesheet eval(manager& ui_manager, const std::string& source); } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,41 @@ #pragma once #include <string> #include <unordered_map> #include <clay.h> namespace engine::ui { using element_style = Clay_ElementDeclaration; using text_style = Clay_TextElementConfig; struct container_style_with_state { element_style normal; element_style hovered; element_style active; }; struct text_style_with_state { text_style normal; text_style hovered; text_style active; }; struct button_style { container_style_with_state container; text_style_with_state label; }; struct input_style { container_style_with_state container; text_style_with_state content; }; struct stylesheet { std::unordered_map<std::string, element_style> elements; std::unordered_map<std::string, text_style> texts; std::unordered_map<std::string, button_style> buttons; std::unordered_map<std::string, input_style> inputs; }; }