lxgui
gui_anchor.cpp
1 #include "lxgui/gui_anchor.hpp"
2 
3 #include "lxgui/gui_frame.hpp"
4 #include "lxgui/gui_frame_renderer.hpp"
5 #include "lxgui/gui_manager.hpp"
6 #include "lxgui/gui_out.hpp"
7 #include "lxgui/gui_region.hpp"
8 #include "lxgui/gui_registry.hpp"
9 #include "lxgui/utils_string.hpp"
10 
11 #include <sstream>
12 
13 namespace lxgui::gui {
14 
15 anchor::anchor(region& object, const anchor_data& data) : anchor_data(data) {
16  if (!object.is_virtual()) {
17  if (parent_name == "$default")
18  parent_name = object.get_parent() ? "$parent" : "";
19 
20  update_parent_(object);
21  }
22 }
23 
24 void anchor::update_parent_(region& object) {
25  parent_ = nullptr;
26 
27  if (parent_name.empty())
28  return;
29 
30  utils::observer_ptr<frame> obj_parent = object.get_parent();
31 
32  std::string parent_full_name = parent_name;
33  if (obj_parent) {
34  utils::replace(parent_full_name, "$parent", obj_parent->get_name());
35  } else if (parent_full_name.find("$parent") != parent_full_name.npos) {
36  gui::out << gui::error << "gui::" << object.get_region_type() << ": "
37  << "region \"" << object.get_name() << "\" tries to anchor to \""
38  << parent_full_name << "\", but '$parent' does not exist." << std::endl;
39  return;
40  }
41 
42  utils::observer_ptr<region> new_parent =
43  object.get_registry().get_region_by_name(parent_full_name);
44 
45  if (!new_parent) {
46  gui::out << gui::error << "gui::" << object.get_region_type() << ": "
47  << "region \"" << object.get_name() << "\" tries to anchor to \""
48  << parent_full_name << "\" but this region does not (yet?) exist." << std::endl;
49  return;
50  }
51 
52  parent_ = new_parent;
53 }
54 
55 vector2f anchor::get_point(const region& object) const {
56  vector2f parent_pos;
57  vector2f parent_size;
58  if (const region* raw_parent = parent_.get()) {
59  parent_pos = raw_parent->get_borders().top_left();
60  parent_size = raw_parent->get_apparent_dimensions();
61  } else {
62  parent_size = object.get_effective_frame_renderer()->get_target_dimensions();
63  }
64 
65  vector2f offset_abs;
66  if (type == anchor_type::abs)
67  offset_abs = offset;
68  else
69  offset_abs = offset * parent_size;
70 
71  offset_abs = object.round_to_pixel(offset_abs, utils::rounding_method::nearest_not_zero);
72 
73  vector2f parent_offset;
74  switch (parent_point) {
75  case point::top_left:
76  parent_offset.x = 0.0f;
77  parent_offset.y = 0.0f;
78  break;
79  case point::left:
80  parent_offset.x = 0.0f;
81  parent_offset.y = parent_size.y / 2.0f;
82  break;
83  case point::bottom_left:
84  parent_offset.x = 0.0f;
85  parent_offset.y = parent_size.y;
86  break;
87  case point::top:
88  parent_offset.x = parent_size.x / 2.0f;
89  parent_offset.y = 0.0f;
90  break;
91  case point::center: parent_offset = parent_size / 2.0f; break;
92  case point::bottom:
93  parent_offset.x = parent_size.x / 2.0f;
94  parent_offset.y = parent_size.y;
95  break;
96  case point::top_right:
97  parent_offset.x = parent_size.x;
98  parent_offset.y = 0.0f;
99  break;
100  case point::right:
101  parent_offset.x = parent_size.x;
102  parent_offset.y = parent_size.y / 2.0f;
103  break;
104  case point::bottom_right:
105  parent_offset.x = parent_size.x;
106  parent_offset.y = parent_size.y;
107  break;
108  }
109 
110  return offset_abs + parent_offset + parent_pos;
111 }
112 
113 std::string anchor::serialize(const std::string& tab) const {
114  std::stringstream str;
115 
116  str << tab << " | # Point : " << utils::to_string(object_point) << "\n";
117  if (parent_)
118  str << tab << " | # Parent : " << parent_->get_name();
119  else
120  str << tab << " | # Parent : none";
121  if (!parent_name.empty())
122  str << " (raw name: " << parent_name << ")\n";
123  else
124  str << "\n";
125  str << tab << " | # Rel. point: " << utils::to_string(parent_point) << "\n";
126  if (type == anchor_type::abs) {
127  str << tab << " | # Offset X : " << offset.x << "\n";
128  str << tab << " | # Offset Y : " << offset.y << "\n";
129  } else {
130  str << tab << " | # Offset X : " << offset.x << " (rel)\n";
131  str << tab << " | # Offset Y : " << offset.y << " (rel)\n";
132  }
133 
134  return str.str();
135 }
136 
137 } // namespace lxgui::gui
anchor_type type
Definition: gui_anchor.hpp:93
vector2f get_point(const region &object) const
Returns this anchor's absolute coordinates (in pixels).
Definition: gui_anchor.cpp:55
anchor(region &object, const anchor_data &data)
Constructor.
Definition: gui_anchor.cpp:15
std::string serialize(const std::string &tab) const
Prints all relevant information about this anchor in a string.
Definition: gui_anchor.cpp:113
The base class of all elements in the GUI.
Definition: gui_region.hpp:161
std::ostream out
const std::string error
Definition: gui_out.cpp:7
@ nearest_not_zero
Equivalent to round() but only returns 0 if input is exactly 0.
Raw data of an anchor (value type)
Definition: gui_anchor.hpp:32