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

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