UIScreen.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // ----------------------------------------------------------------
  2. // From Game Programming in C++ by Sanjay Madhav
  3. // Copyright (C) 2017 Sanjay Madhav. All rights reserved.
  4. //
  5. // Released under the BSD License
  6. // See LICENSE in root directory for full details.
  7. // ----------------------------------------------------------------
  8. #include "UIScreen.h"
  9. #include "Texture.h"
  10. #include "Shader.h"
  11. #include "Game.h"
  12. #include "Renderer.h"
  13. #include "Font.h"
  14. UIScreen::UIScreen(Game* game)
  15. :mGame(game)
  16. ,mTitle(nullptr)
  17. ,mBackground(nullptr)
  18. ,mTitlePos(0.0f, 300.0f)
  19. ,mNextButtonPos(0.0f, 200.0f)
  20. ,mBGPos(0.0f, 250.0f)
  21. ,mState(EActive)
  22. {
  23. // Add to UI Stack
  24. mGame->PushUI(this);
  25. mFont = mGame->GetFont("Assets/Carlito-Regular.ttf");
  26. mButtonOn = mGame->GetRenderer()->GetTexture("Assets/ButtonYellow.png");
  27. mButtonOff = mGame->GetRenderer()->GetTexture("Assets/ButtonBlue.png");
  28. }
  29. UIScreen::~UIScreen()
  30. {
  31. if (mTitle)
  32. {
  33. mTitle->Unload();
  34. delete mTitle;
  35. }
  36. for (auto b : mButtons)
  37. {
  38. delete b;
  39. }
  40. mButtons.clear();
  41. }
  42. void UIScreen::Update(float deltaTime)
  43. {
  44. }
  45. void UIScreen::Draw(Shader* shader)
  46. {
  47. // Draw background (if exists)
  48. if (mBackground)
  49. {
  50. DrawTexture(shader, mBackground, mBGPos);
  51. }
  52. // Draw title (if exists)
  53. if (mTitle)
  54. {
  55. DrawTexture(shader, mTitle, mTitlePos);
  56. }
  57. // Draw buttons
  58. for (auto b : mButtons)
  59. {
  60. // Draw background of button
  61. Texture* tex = b->GetHighlighted() ? mButtonOn : mButtonOff;
  62. DrawTexture(shader, tex, b->GetPosition());
  63. // Draw text of button
  64. DrawTexture(shader, b->GetNameTex(), b->GetPosition());
  65. }
  66. // Override in subclasses to draw any textures
  67. }
  68. void UIScreen::ProcessInput(const uint8_t* keys)
  69. {
  70. // Do we have buttons?
  71. if (!mButtons.empty())
  72. {
  73. // Get position of mouse
  74. int x, y;
  75. SDL_GetMouseState(&x, &y);
  76. // Convert to (0,0) center coordinates
  77. Vector2 mousePos(static_cast<float>(x), static_cast<float>(y));
  78. mousePos.x -= mGame->GetRenderer()->GetScreenWidth() * 0.5f;
  79. mousePos.y = mGame->GetRenderer()->GetScreenHeight() * 0.5f - mousePos.y;
  80. // Highlight any buttons
  81. for (auto b : mButtons)
  82. {
  83. if (b->ContainsPoint(mousePos))
  84. {
  85. b->SetHighlighted(true);
  86. }
  87. else
  88. {
  89. b->SetHighlighted(false);
  90. }
  91. }
  92. }
  93. }
  94. void UIScreen::HandleKeyPress(int key)
  95. {
  96. switch (key)
  97. {
  98. case SDL_BUTTON_LEFT:
  99. if (!mButtons.empty())
  100. {
  101. for (auto b : mButtons)
  102. {
  103. if (b->GetHighlighted())
  104. {
  105. b->OnClick();
  106. break;
  107. }
  108. }
  109. }
  110. break;
  111. default:
  112. break;
  113. }
  114. }
  115. void UIScreen::Close()
  116. {
  117. mState = EClosing;
  118. }
  119. void UIScreen::SetTitle(const std::string& text,
  120. const Vector3& color,
  121. int pointSize)
  122. {
  123. // Clear out previous title texture if it exists
  124. if (mTitle)
  125. {
  126. mTitle->Unload();
  127. delete mTitle;
  128. mTitle = nullptr;
  129. }
  130. mTitle = mFont->RenderText(text, color, pointSize);
  131. }
  132. void UIScreen::AddButton(const std::string& name, std::function<void()> onClick)
  133. {
  134. Vector2 dims(static_cast<float>(mButtonOn->GetWidth()),
  135. static_cast<float>(mButtonOn->GetHeight()));
  136. Button* b = new Button(name, mFont, onClick, mNextButtonPos, dims);
  137. mButtons.emplace_back(b);
  138. // Update position of next button
  139. // Move down by height of button plus padding
  140. mNextButtonPos.y -= mButtonOff->GetHeight() + 20.0f;
  141. }
  142. void UIScreen::DrawTexture(class Shader* shader, class Texture* texture,
  143. const Vector2& offset, float scale)
  144. {
  145. // Scale the quad by the width/height of texture
  146. Matrix4 scaleMat = Matrix4::CreateScale(
  147. static_cast<float>(texture->GetWidth()) * scale,
  148. static_cast<float>(texture->GetHeight()) * scale,
  149. 1.0f);
  150. // Translate to position on screen
  151. Matrix4 transMat = Matrix4::CreateTranslation(
  152. Vector3(offset.x, offset.y, 0.0f));
  153. // Set world transform
  154. Matrix4 world = scaleMat * transMat;
  155. shader->SetMatrixUniform("uWorldTransform", world);
  156. // Set current texture
  157. texture->SetActive();
  158. // Draw quad
  159. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
  160. }
  161. void UIScreen::SetRelativeMouseMode(bool relative)
  162. {
  163. if (relative)
  164. {
  165. SDL_SetRelativeMouseMode(SDL_TRUE);
  166. // Make an initial call to get relative to clear out
  167. SDL_GetRelativeMouseState(nullptr, nullptr);
  168. }
  169. else
  170. {
  171. SDL_SetRelativeMouseMode(SDL_FALSE);
  172. }
  173. }
  174. Button::Button(const std::string& name, Font* font,
  175. std::function<void()> onClick,
  176. const Vector2& pos, const Vector2& dims)
  177. :mOnClick(onClick)
  178. ,mNameTex(nullptr)
  179. ,mFont(font)
  180. ,mPosition(pos)
  181. ,mDimensions(dims)
  182. ,mHighlighted(false)
  183. {
  184. SetName(name);
  185. }
  186. Button::~Button()
  187. {
  188. if (mNameTex)
  189. {
  190. mNameTex->Unload();
  191. delete mNameTex;
  192. }
  193. }
  194. void Button::SetName(const std::string& name)
  195. {
  196. mName = name;
  197. if (mNameTex)
  198. {
  199. mNameTex->Unload();
  200. delete mNameTex;
  201. mNameTex = nullptr;
  202. }
  203. mNameTex = mFont->RenderText(mName);
  204. }
  205. bool Button::ContainsPoint(const Vector2& pt) const
  206. {
  207. bool no = pt.x < (mPosition.x - mDimensions.x / 2.0f) ||
  208. pt.x > (mPosition.x + mDimensions.x / 2.0f) ||
  209. pt.y < (mPosition.y - mDimensions.y / 2.0f) ||
  210. pt.y > (mPosition.y + mDimensions.y / 2.0f);
  211. return !no;
  212. }
  213. void Button::OnClick()
  214. {
  215. // Call attached handler, if it exists
  216. if (mOnClick)
  217. {
  218. mOnClick();
  219. }
  220. }