💿🐜 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.

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