lxgui
gui_region_parser.cpp
1 #include "lxgui/gui_anchor.hpp"
2 #include "lxgui/gui_color.hpp"
3 #include "lxgui/gui_layout_node.hpp"
4 #include "lxgui/gui_out.hpp"
5 #include "lxgui/gui_region.hpp"
6 #include "lxgui/utils_std.hpp"
7 
8 namespace lxgui::gui {
9 
11  if (const auto attr = node.try_get_attribute_value<std::string>("c")) {
12  const std::string& s = attr.value();
13  if (!s.empty() && s[0] == '#')
14  return color(s);
15  }
16 
17  return color(
18  node.get_attribute_value_or<float>("r", 0.0f),
19  node.get_attribute_value_or<float>("g", 0.0f),
20  node.get_attribute_value_or<float>("b", 0.0f),
21  node.get_attribute_value_or<float>("a", 1.0f));
22 }
23 
25  return {node.try_get_attribute_value<float>("x"), node.try_get_attribute_value<float>("y")};
26 }
27 
29  return {
30  node.get_attribute_value_or<float>("x", fallback),
31  node.get_attribute_value_or<float>("y", fallback)};
32 }
33 
34 std::pair<anchor_type, vector2<std::optional<float>>>
36  const layout_node* abs_dim_node = node.try_get_child("AbsDimension");
37  const layout_node* rel_dim_node = node.try_get_child("RelDimension");
38 
39  if (abs_dim_node && rel_dim_node) {
40  gui::out << gui::warning << node.get_location() << ": " << node.get_name()
41  << " node can only contain one of AbsDimension or RelDimension, but not both. "
42  "RelDimension ignored."
43  << std::endl;
44  }
45 
46  if (!abs_dim_node && !rel_dim_node) {
47  gui::out << gui::warning << node.get_location() << ": " << node.get_name()
48  << " node must contain one of AbsDimension or RelDimension." << std::endl;
49  return {};
50  }
51 
53  const layout_node* chosen_node = nullptr;
54  if (abs_dim_node) {
55  type = anchor_type::abs;
56  chosen_node = abs_dim_node;
57  } else {
58  type = anchor_type::rel;
59  chosen_node = rel_dim_node;
60  }
61 
62  return std::make_pair(type, parse_offset_node_(*chosen_node));
63 }
64 
66  if (const layout_node* size_block = node.try_get_child("Size")) {
67  auto dimensions = parse_dimension_node_(*size_block);
68  bool has_x = dimensions.second.x.has_value();
69  bool has_y = dimensions.second.y.has_value();
70  if (dimensions.first == anchor_type::abs) {
71  if (has_x && has_y) {
72  set_dimensions(vector2f(dimensions.second.x.value(), dimensions.second.y.value()));
73  } else if (has_x)
74  set_width(dimensions.second.x.value());
75  else if (has_y)
76  set_height(dimensions.second.y.value());
77  } else {
78  if (has_x && has_y) {
80  vector2f(dimensions.second.x.value(), dimensions.second.y.value()));
81  } else if (has_x)
82  set_relative_width(dimensions.second.x.value());
83  else if (has_y)
84  set_relative_height(dimensions.second.y.value());
85  }
86  }
87 }
88 
90  if (const layout_node* anchors_node = node.try_get_child("Anchors")) {
91  std::vector<point> found_points;
92  for (const auto& anchor_node : anchors_node->get_children()) {
93  if (anchor_node.get_name() != "Anchor" && anchor_node.get_name() != "") {
94  gui::out << gui::warning << anchor_node.get_location() << ": "
95  << "unexpected node '" << anchor_node.get_name() << "'; ignored."
96  << std::endl;
97  continue;
98  }
99 
100  point pt = anchor_node.get_attribute_value_or<point>("point", point::top_left);
101  std::string parent = anchor_node.get_attribute_value_or<std::string>(
102  "relativeTo", parent_ || is_virtual() ? "$parent" : "");
103  point relative_point = anchor_node.get_attribute_value_or<point>("relativePoint", pt);
104 
105  if (utils::find(found_points, pt) != found_points.end()) {
106  gui::out << gui::warning << anchor_node.get_location() << ": "
107  << "anchor point \"" << utils::to_string(pt)
108  << "\" has already been defined for \"" << name_ << "\". anchor skipped."
109  << std::endl;
110  continue;
111  }
112 
113  anchor_data a(pt, parent, relative_point);
114 
115  if (const layout_node* offset_node = anchor_node.try_get_child("Offset")) {
116  auto dimensions = parse_dimension_node_(*offset_node);
117  a.type = dimensions.first;
118  a.offset = vector2f(
119  dimensions.second.x.value_or(0.0f), dimensions.second.y.value_or(0.0f));
120  }
121 
122  set_anchor(a);
123  }
124  }
125 }
126 
128  parse_attributes_(node);
129  parse_size_node_(node);
130  parse_anchor_node_(node);
131 }
132 
134  if (node.get_attribute_value_or<bool>("setAllAnchors", false))
135  set_all_anchors("$parent");
136 }
137 
138 } // namespace lxgui::gui
Holds a single color (float RGBA, 128 bits)
Definition: gui_color.hpp:12
std::string_view get_name() const noexcept
Returns this node's name.
std::string_view get_location() const noexcept
Returns this node's location in the file as {file}:{line}.
An node in a layout file.
std::optional< std::string_view > try_get_attribute_value(std::string_view name) const noexcept
Returns the value of the attribute with the provided name, nullopt if not found.
const layout_node * try_get_child(std::string_view name) const noexcept
Returns the first child with a given name, or null if none.
T get_attribute_value_or(std::string_view name, T fallback) const noexcept
Returns the value of the attribute with the provided name, or a default if not found or parsing faile...
virtual void set_width(float abs_width)
Changes this region's absolute width (in pixels).
Definition: gui_region.cpp:227
void set_all_anchors(const utils::observer_ptr< region > &obj)
Adjusts this regions anchors to fit the provided region.
Definition: gui_region.cpp:437
void set_anchor(const anchor_data &a)
Adds/replaces an anchor.
Definition: gui_region.cpp:473
color parse_color_node_(const layout_node &node)
virtual void parse_layout(const layout_node &node)
Parses data from a layout_node.
bool is_virtual() const
Checks if this region is virtual.
Definition: gui_region.cpp:553
virtual void parse_size_node_(const layout_node &node)
std::pair< anchor_type, vector2< std::optional< float > > > parse_dimension_node_(const layout_node &node)
utils::observer_ptr< frame > parent_
Definition: gui_region.hpp:807
virtual void set_height(float abs_height)
Changes this region's absolute height (in pixels).
Definition: gui_region.cpp:239
void set_relative_height(float rel_height)
Changes this region's height (relative to its parent).
Definition: gui_region.cpp:265
virtual void parse_attributes_(const layout_node &node)
vector2< std::optional< float > > parse_offset_node_(const layout_node &node)
std::string name_
Definition: gui_region.hpp:804
virtual void set_dimensions(const vector2f &dimensions)
Changes this region's absolute dimensions (in pixels).
Definition: gui_region.cpp:215
void set_relative_width(float rel_width)
Changes this region's width (relative to its parent).
Definition: gui_region.cpp:258
void set_relative_dimensions(const vector2f &dimensions)
Changes this region's dimensions (relative to its parent).
Definition: gui_region.cpp:251
vector2< float > parse_offset_node_or_(const layout_node &node, float fallback)
virtual void parse_anchor_node_(const layout_node &node)
vector2< float > vector2f
Holds 2D coordinates (as floats)
std::ostream out
const std::string warning
Definition: gui_out.cpp:6
auto find(C &v, const T &s)
Definition: utils_std.hpp:14
Raw data of an anchor (value type)
Definition: gui_anchor.hpp:32
Holds 2D coordinates.
Definition: gui_vector2.hpp:14