💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

444 lines
9.7 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. /*
  2. * Copyright (C) 2017 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef UI_HPP
  20. #define UI_HPP
  21. #include "../input.hpp"
  22. #include "../materials.hpp"
  23. #include <vector>
  24. #include <functional>
  25. #include <emergent/emergent.hpp>
  26. using namespace Emergent;
  27. namespace Anchor
  28. {
  29. static const Vector2& TOP_LEFT = Vector2(0.0f, 0.0f);
  30. static const Vector2& TOP_RIGHT = Vector2(1.0f, 0.0f);
  31. static const Vector2& BOTTOM_LEFT = Vector2(0.0f, 1.0f);
  32. static const Vector2& BOTTOM_RIGHT = Vector2(1.0f, 1.0f);
  33. static const Vector2& CENTER = Vector2(0.5f, 0.5f);
  34. }
  35. class UIElement: public MouseMotionObserver, public MouseButtonObserver
  36. {
  37. public:
  38. enum class Type
  39. {
  40. CONTAINER,
  41. LABEL,
  42. IMAGE
  43. };
  44. UIElement();
  45. virtual ~UIElement();
  46. /// Sets the anchor vector. Possible values are 0, 0.5, and 1, corresponding to the left, center, and right, respectively, and the top, center, and bottom.
  47. void setAnchor(const Vector2& anchor);
  48. /// Sets the layer offset, relative to its parent layer + 1
  49. void setLayerOffset(int offset);
  50. /// Sets the local origin of the element
  51. void setOrigin(const Vector2& origin);
  52. /// Sets the translation of the element, relative to its position in its parent element
  53. void setTranslation(const Vector2& translation);
  54. /// Sets the rotation of the element
  55. void setRotation(float angle);
  56. /// Sets the dimensions of the element
  57. void setDimensions(const Vector2& dimensions);
  58. /// Sets the tint color of the element
  59. void setTintColor(const Vector4& color);
  60. /// Sets the visibility of the element
  61. void setVisible(bool visible);
  62. /// Enables or disables callbacks
  63. void setActive(bool active);
  64. /// Returns the type of this element
  65. virtual UIElement::Type getElementType() const = 0;
  66. /// Returns the material of this element
  67. const UIMaterial* getMaterial() const;
  68. /// @copydoc UIElement::getMaterial() const
  69. UIMaterial* getMaterial();
  70. /// Returns the parent of this element
  71. const UIElement* getParent() const;
  72. /// @copydoc UIElement::getParent() const
  73. UIElement* getParent();
  74. /// Returns the number of child elements
  75. std::size_t getChildCount() const;
  76. /// Returns the child element at the specified index
  77. const UIElement* getChild(std::size_t index) const;
  78. /// @copydoc UIElement::getChild() const
  79. UIElement* getChild(std::size_t index);
  80. /// Returns the anchor vector
  81. const Vector2& getAnchor() const;
  82. /// Returns the layer offset
  83. int getLayerOffset() const;
  84. /// Returns the layer of this element
  85. int getLayer() const;
  86. /// Returns the origin of this element
  87. const Vector2& getOrigin() const;
  88. /// Returns the translation of this element, relative to its parent
  89. const Vector2& getTranslation() const;
  90. /// Returns the rotation of this element
  91. float getRotation() const;
  92. /// Returns the dimensions of this element
  93. const Vector2& getDimensions() const;
  94. /// Returns the world-space position of this element. Only accurate after update() is called
  95. const Vector2& getPosition() const;
  96. /// Returns the world-space bounds of this element.
  97. const Rect& getBounds() const;
  98. /// Returns the tint color of this element
  99. const Vector4& getTintColor() const;
  100. /// Returns the final color of this element, relative to its ancestor's tint colors
  101. const Vector4& getColor() const;
  102. /// Returns the visibility of this element
  103. bool isVisible() const;
  104. /// Returns `true` if the element is active (callbacks enabled)
  105. bool isActive() const;
  106. /// Calculates the world-space position and bounds of this element and its children
  107. virtual void update();
  108. /// Adds a child to this element
  109. void addChild(UIElement* element);
  110. /// Removes a child from this element
  111. void removeChild(UIElement* element);
  112. void setMouseOverCallback(std::function<void()> callback);
  113. void setMouseOutCallback(std::function<void()> callback);
  114. void setMouseMovedCallback(std::function<void(int, int)> callback);
  115. void setMousePressedCallback(std::function<void(int, int, int)> callback);
  116. void setMouseReleasedCallback(std::function<void(int, int, int)> callback);
  117. void mouseMoved(int x, int y);
  118. void mouseButtonPressed(int button, int x, int y);
  119. void mouseButtonReleased(int button, int x, int y);
  120. protected:
  121. UIMaterial material;
  122. private:
  123. UIElement* parent;
  124. std::vector<UIElement*> children;
  125. Vector2 anchor;
  126. int layerOffset;
  127. int layer;
  128. Vector2 origin;
  129. Vector2 translation;
  130. float rotation;
  131. Vector2 dimensions;
  132. Vector2 position;
  133. Rect bounds;
  134. Vector4 tintColor;
  135. Vector4 color;
  136. bool visible;
  137. bool active;
  138. bool mouseOver;
  139. std::function<void()> mouseOverCallback;
  140. std::function<void()> mouseOutCallback;
  141. std::function<void(int, int)> mouseMovedCallback;
  142. std::function<void(int, int, int)> mousePressedCallback;
  143. std::function<void(int, int, int)> mouseReleasedCallback;
  144. };
  145. inline void UIElement::setAnchor(const Vector2& anchor)
  146. {
  147. this->anchor = anchor;
  148. }
  149. inline void UIElement::setLayerOffset(int offset)
  150. {
  151. this->layerOffset = offset;
  152. }
  153. inline void UIElement::setOrigin(const Vector2& origin)
  154. {
  155. this->origin = origin;
  156. }
  157. inline void UIElement::setTranslation(const Vector2& translation)
  158. {
  159. this->translation = translation;
  160. }
  161. inline void UIElement::setRotation(float angle)
  162. {
  163. this->rotation = angle;
  164. }
  165. inline void UIElement::setDimensions(const Vector2& dimensions)
  166. {
  167. this->dimensions = dimensions;
  168. }
  169. inline void UIElement::setTintColor(const Vector4& color)
  170. {
  171. this->tintColor = color;
  172. }
  173. inline void UIElement::setVisible(bool visible)
  174. {
  175. this->visible = visible;
  176. }
  177. inline void UIElement::setActive(bool active)
  178. {
  179. this->active = active;
  180. }
  181. inline const UIElement* UIElement::getParent() const
  182. {
  183. return parent;
  184. }
  185. inline const UIMaterial* UIElement::getMaterial() const
  186. {
  187. return &material;
  188. }
  189. inline UIMaterial* UIElement::getMaterial()
  190. {
  191. return &material;
  192. }
  193. inline UIElement* UIElement::getParent()
  194. {
  195. return parent;
  196. }
  197. inline std::size_t UIElement::getChildCount() const
  198. {
  199. return children.size();
  200. }
  201. inline const UIElement* UIElement::getChild(std::size_t index) const
  202. {
  203. return children[index];
  204. }
  205. inline UIElement* UIElement::getChild(std::size_t index)
  206. {
  207. return children[index];
  208. }
  209. inline const Vector2& UIElement::getAnchor() const
  210. {
  211. return anchor;
  212. }
  213. inline int UIElement::getLayerOffset() const
  214. {
  215. return layerOffset;
  216. }
  217. inline int UIElement::getLayer() const
  218. {
  219. return layer;
  220. }
  221. inline const Vector2& UIElement::getOrigin() const
  222. {
  223. return origin;
  224. }
  225. inline const Vector2& UIElement::getTranslation() const
  226. {
  227. return translation;
  228. }
  229. inline float UIElement::getRotation() const
  230. {
  231. return rotation;
  232. }
  233. inline const Vector2& UIElement::getDimensions() const
  234. {
  235. return dimensions;
  236. }
  237. inline const Vector2& UIElement::getPosition() const
  238. {
  239. return position;
  240. }
  241. inline const Rect& UIElement::getBounds() const
  242. {
  243. return bounds;
  244. }
  245. inline const Vector4& UIElement::getTintColor() const
  246. {
  247. return tintColor;
  248. }
  249. inline const Vector4& UIElement::getColor() const
  250. {
  251. return color;
  252. }
  253. inline bool UIElement::isVisible() const
  254. {
  255. return visible;
  256. }
  257. inline bool UIElement::isActive() const
  258. {
  259. return active;
  260. }
  261. class UIContainer: public UIElement
  262. {
  263. public:
  264. virtual UIElement::Type getElementType() const;
  265. };
  266. inline UIElement::Type UIContainer::getElementType() const
  267. {
  268. return UIElement::Type::CONTAINER;
  269. }
  270. class UILabel: public UIElement
  271. {
  272. public:
  273. UILabel();
  274. virtual ~UILabel();
  275. virtual UIElement::Type getElementType() const;
  276. void setFont(Font* font);
  277. void setText(const std::string& text);
  278. const Font* getFont() const;
  279. Font* getFont();
  280. const std::string& getText() const;
  281. private:
  282. void calculateDimensions();
  283. Font* font;
  284. std::string text;
  285. };
  286. inline UIElement::Type UILabel::getElementType() const
  287. {
  288. return UIElement::Type::LABEL;
  289. }
  290. inline const Font* UILabel::getFont() const
  291. {
  292. return font;
  293. }
  294. inline Font* UILabel::getFont()
  295. {
  296. return font;
  297. }
  298. inline const std::string& UILabel::getText() const
  299. {
  300. return text;
  301. }
  302. class UIImage: public UIElement
  303. {
  304. public:
  305. UIImage();
  306. virtual ~UIImage();
  307. virtual UIElement::Type getElementType() const;
  308. virtual const Texture* getTexture() const;
  309. void setTexture(Texture* texture);
  310. void setTextureBounds(const Rect& bounds);
  311. const Rect& getTextureBounds() const;
  312. private:
  313. Rect textureBounds;
  314. };
  315. inline UIElement::Type UIImage::getElementType() const
  316. {
  317. return UIElement::Type::IMAGE;
  318. }
  319. inline const Texture* UIImage::getTexture() const
  320. {
  321. return material.texture;
  322. }
  323. inline void UIImage::setTexture(Texture* texture)
  324. {
  325. material.texture = texture;
  326. }
  327. inline void UIImage::setTextureBounds(const Rect& bounds)
  328. {
  329. this->textureBounds = bounds;
  330. }
  331. inline const Rect& UIImage::getTextureBounds() const
  332. {
  333. return textureBounds;
  334. }
  335. // Creates a scene from a root UI element (follows visitor pattern?)
  336. class UIBatcher
  337. {
  338. public:
  339. void batch(BillboardBatch* result, const UIElement* ui);
  340. private:
  341. void queueElements(std::list<const UIElement*>* elements, const UIElement* element) const;
  342. BillboardBatch::Range* getRange(BillboardBatch* result, const UIElement* element) const;
  343. void batchElement(BillboardBatch* result, const UIElement* element);
  344. void batchLabel(BillboardBatch* result, const UILabel* label);
  345. void batchImage(BillboardBatch* result, const UIImage* image);
  346. };
  347. #endif // UI_HPP