Control.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. #include "Base.h"
  2. #include "Control.h"
  3. namespace gameplay
  4. {
  5. Control::Control()
  6. : _id(""), _state(Control::NORMAL), _position(Vector2::zero()), _size(Vector2::zero()), _bounds(Rectangle::empty()), _clip(Rectangle::empty()),
  7. _autoWidth(true), _autoHeight(true), _dirty(true), _consumeTouchEvents(true)
  8. {
  9. }
  10. Control::Control(const Control& copy)
  11. {
  12. }
  13. Control::~Control()
  14. {
  15. }
  16. void Control::init(Theme::Style* style, Properties* properties)
  17. {
  18. _style = style;
  19. properties->getVector2("position", &_position);
  20. properties->getVector2("size", &_size);
  21. _state = Control::getStateFromString(properties->getString("state"));
  22. const char* id = properties->getId();
  23. if (id)
  24. {
  25. _id = id;
  26. }
  27. }
  28. const char* Control::getID() const
  29. {
  30. return _id.c_str();
  31. }
  32. void Control::setPosition(float x, float y)
  33. {
  34. _position.set(x, y);
  35. }
  36. const Vector2& Control::getPosition() const
  37. {
  38. return _position;
  39. }
  40. void Control::setSize(float width, float height)
  41. {
  42. _size.set(width, height);
  43. }
  44. const Vector2& Control::getSize() const
  45. {
  46. return _size;
  47. }
  48. const Rectangle& Control::getBounds() const
  49. {
  50. return _bounds;
  51. }
  52. const Rectangle& Control::getClip() const
  53. {
  54. return _clip;
  55. }
  56. void Control::setAutoSize(bool width, bool height)
  57. {
  58. _autoWidth = width;
  59. _autoHeight = height;
  60. }
  61. void Control::setStyle(Theme::Style* style)
  62. {
  63. _style = style;
  64. }
  65. Theme::Style* Control::getStyle() const
  66. {
  67. return _style;
  68. }
  69. void Control::setState(State state)
  70. {
  71. _state = state;
  72. }
  73. Control::State Control::getState()
  74. {
  75. return _state;
  76. }
  77. void Control::disable()
  78. {
  79. _state = DISABLED;
  80. }
  81. void Control::enable()
  82. {
  83. _state = NORMAL;
  84. }
  85. bool Control::isEnabled()
  86. {
  87. return _state != DISABLED;
  88. }
  89. Theme::Style::OverlayType Control::getOverlayType() const
  90. {
  91. switch (_state)
  92. {
  93. case Control::NORMAL:
  94. return Theme::Style::OVERLAY_NORMAL;
  95. case Control::FOCUS:
  96. return Theme::Style::OVERLAY_FOCUS;
  97. case Control::ACTIVE:
  98. return Theme::Style::OVERLAY_ACTIVE;
  99. case Control::DISABLED:
  100. return Theme::Style::OVERLAY_DISABLED;
  101. default:
  102. return Theme::Style::OVERLAY_NORMAL;
  103. }
  104. }
  105. void Control::setConsumeTouchEvents(bool consume)
  106. {
  107. _consumeTouchEvents = consume;
  108. }
  109. bool Control::getConsumeTouchEvents()
  110. {
  111. return _consumeTouchEvents;
  112. }
  113. bool Control::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  114. {
  115. // Empty stub to be implemented by Button and its descendents.
  116. return _consumeTouchEvents;
  117. }
  118. void Control::keyEvent(Keyboard::KeyEvent evt, int key)
  119. {
  120. }
  121. void Control::update(const Rectangle& clip)
  122. {
  123. // Calculate the bounds.
  124. float x = clip.x + _position.x;
  125. float y = clip.y + _position.y;
  126. float width = _size.x;
  127. float height = _size.y;
  128. float clipX2 = clip.x + clip.width;
  129. float x2 = x + width;
  130. if (x2 > clipX2)
  131. {
  132. width = clipX2 - x;
  133. }
  134. float clipY2 = clip.y + clip.height;
  135. float y2 = y + height;
  136. if (y2 > clipY2)
  137. {
  138. height = clipY2 - y;
  139. }
  140. _bounds.set(_position.x, _position.y, width, height);
  141. // Calculate the clipping viewport.
  142. Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
  143. Theme::Border border;
  144. Theme::ContainerRegion* containerRegion = overlay->getContainerRegion();
  145. if (containerRegion)
  146. {
  147. border = overlay->getContainerRegion()->getBorder();
  148. }
  149. Theme::Padding padding = _style->getPadding();
  150. x += border.left + padding.left;
  151. y += border.top + padding.top;
  152. width = _size.x - border.left - padding.left - border.right - padding.right;
  153. height = _size.y - border.top - padding.top - border.bottom - padding.bottom;
  154. clipX2 = clip.x + clip.width;
  155. x2 = x + width;
  156. if (x2 > clipX2)
  157. {
  158. width = clipX2 - x;
  159. }
  160. clipY2 = clip.y + clip.height;
  161. y2 = y + height;
  162. if (y2 > clipY2)
  163. {
  164. height = clipY2 - y;
  165. }
  166. _clip.set(x, y, width, height);
  167. }
  168. void Control::drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip)
  169. {
  170. Vector2 pos(clip.x + _position.x, clip.y + _position.y);
  171. // Get the border and background images for this control's current state.
  172. Theme::ContainerRegion* containerRegion = _style->getOverlay(getOverlayType())->getContainerRegion();
  173. if (containerRegion)
  174. {
  175. // Get the UVs.
  176. Theme::UVs topLeft, top, topRight, left, center, right, bottomLeft, bottom, bottomRight;
  177. topLeft = containerRegion->getUVs(Theme::ContainerRegion::TOP_LEFT);
  178. top = containerRegion->getUVs(Theme::ContainerRegion::TOP);
  179. topRight = containerRegion->getUVs(Theme::ContainerRegion::TOP_RIGHT);
  180. left = containerRegion->getUVs(Theme::ContainerRegion::LEFT);
  181. center = containerRegion->getUVs(Theme::ContainerRegion::CENTER);
  182. right = containerRegion->getUVs(Theme::ContainerRegion::RIGHT);
  183. bottomLeft = containerRegion->getUVs(Theme::ContainerRegion::BOTTOM_LEFT);
  184. bottom = containerRegion->getUVs(Theme::ContainerRegion::BOTTOM);
  185. bottomRight = containerRegion->getUVs(Theme::ContainerRegion::BOTTOM_RIGHT);
  186. // Calculate screen-space positions.
  187. Theme::Border border = containerRegion->getBorder();
  188. Theme::Padding padding = _style->getPadding();
  189. Vector4 borderColor = containerRegion->getColor();
  190. float midWidth = _size.x - border.left - border.right;
  191. float midHeight = _size.y - border.top - border.bottom;
  192. float midX = pos.x + border.left;
  193. float midY = pos.y + border.top;
  194. float rightX = pos.x + _size.x - border.right;
  195. float bottomY = pos.y + _size.y - border.bottom;
  196. // Draw themed border sprites.
  197. if (!border.left && !border.right && !border.top && !border.bottom)
  198. {
  199. // No border, just draw the image.
  200. spriteBatch->draw(pos.x, pos.y, _size.x, _size.y, center.u1, center.v1, center.u2, center.v2, borderColor, clip);
  201. }
  202. else
  203. {
  204. if (border.left && border.top)
  205. spriteBatch->draw(pos.x, pos.y, border.left, border.top, topLeft.u1, topLeft.v1, topLeft.u2, topLeft.v2, borderColor, clip);
  206. if (border.top)
  207. spriteBatch->draw(pos.x + border.left, pos.y, midWidth, border.top, top.u1, top.v1, top.u2, top.v2, borderColor, clip);
  208. if (border.right && border.top)
  209. spriteBatch->draw(rightX, pos.y, border.right, border.top, topRight.u1, topRight.v1, topRight.u2, topRight.v2, borderColor, clip);
  210. if (border.left)
  211. spriteBatch->draw(pos.x, midY, border.left, midHeight, left.u1, left.v1, left.u2, left.v2, borderColor, clip);
  212. if (border.left && border.right && border.top && border.bottom)
  213. spriteBatch->draw(pos.x + border.left, pos.y + border.top, _size.x - border.left - border.right, _size.y - border.top - border.bottom,
  214. center.u1, center.v1, center.u2, center.v2, borderColor, clip);
  215. if (border.right)
  216. spriteBatch->draw(rightX, midY, border.right, midHeight, right.u1, right.v1, right.u2, right.v2, borderColor, clip);
  217. if (border.bottom && border.left)
  218. spriteBatch->draw(pos.x, bottomY, border.left, border.bottom, bottomLeft.u1, bottomLeft.v1, bottomLeft.u2, bottomLeft.v2, borderColor, clip);
  219. if (border.bottom)
  220. spriteBatch->draw(midX, bottomY, midWidth, border.bottom, bottom.u1, bottom.v1, bottom.u2, bottom.v2, borderColor, clip);
  221. if (border.bottom && border.right)
  222. spriteBatch->draw(rightX, bottomY, border.right, border.bottom, bottomRight.u1, bottomRight.v1, bottomRight.u2, bottomRight.v2, borderColor, clip);
  223. }
  224. }
  225. }
  226. void Control::drawSprites(SpriteBatch* spriteBatch, const Rectangle& position)
  227. {
  228. }
  229. void Control::drawText(const Rectangle& position)
  230. {
  231. }
  232. bool Control::isDirty()
  233. {
  234. return _dirty;
  235. }
  236. bool Control::isContainer()
  237. {
  238. return false;
  239. }
  240. Control::State Control::getStateFromString(const char* state)
  241. {
  242. if (!state)
  243. {
  244. return NORMAL;
  245. }
  246. if (strcmp(state, "NORMAL") == 0)
  247. {
  248. return NORMAL;
  249. }
  250. else if (strcmp(state, "ACTIVE") == 0)
  251. {
  252. return ACTIVE;
  253. }
  254. else if (strcmp(state, "FOCUS") == 0)
  255. {
  256. return FOCUS;
  257. }
  258. else if (strcmp(state, "DISABLED") == 0)
  259. {
  260. return DISABLED;
  261. }
  262. return NORMAL;
  263. }
  264. }