UIScreen.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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, bool flipY)
  144. {
  145. // Scale the quad by the width/height of texture
  146. // and flip the y if we need to
  147. float yScale = static_cast<float>(texture->GetHeight()) * scale;
  148. if (flipY) { yScale *= -1.0f; }
  149. Matrix4 scaleMat = Matrix4::CreateScale(
  150. static_cast<float>(texture->GetWidth()) * scale,
  151. yScale,
  152. 1.0f);
  153. // Translate to position on screen
  154. Matrix4 transMat = Matrix4::CreateTranslation(
  155. Vector3(offset.x, offset.y, 0.0f));
  156. // Set world transform
  157. Matrix4 world = scaleMat * transMat;
  158. shader->SetMatrixUniform("uWorldTransform", world);
  159. // Set current texture
  160. texture->SetActive();
  161. // Draw quad
  162. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
  163. }
  164. void UIScreen::SetRelativeMouseMode(bool relative)
  165. {
  166. if (relative)
  167. {
  168. SDL_SetRelativeMouseMode(SDL_TRUE);
  169. // Make an initial call to get relative to clear out
  170. SDL_GetRelativeMouseState(nullptr, nullptr);
  171. }
  172. else
  173. {
  174. SDL_SetRelativeMouseMode(SDL_FALSE);
  175. }
  176. }
  177. Button::Button(const std::string& name, Font* font,
  178. std::function<void()> onClick,
  179. const Vector2& pos, const Vector2& dims)
  180. :mOnClick(onClick)
  181. ,mNameTex(nullptr)
  182. ,mFont(font)
  183. ,mPosition(pos)
  184. ,mDimensions(dims)
  185. ,mHighlighted(false)
  186. {
  187. SetName(name);
  188. }
  189. Button::~Button()
  190. {
  191. if (mNameTex)
  192. {
  193. mNameTex->Unload();
  194. delete mNameTex;
  195. }
  196. }
  197. void Button::SetName(const std::string& name)
  198. {
  199. mName = name;
  200. if (mNameTex)
  201. {
  202. mNameTex->Unload();
  203. delete mNameTex;
  204. mNameTex = nullptr;
  205. }
  206. mNameTex = mFont->RenderText(mName);
  207. }
  208. bool Button::ContainsPoint(const Vector2& pt) const
  209. {
  210. bool no = pt.x < (mPosition.x - mDimensions.x / 2.0f) ||
  211. pt.x > (mPosition.x + mDimensions.x / 2.0f) ||
  212. pt.y < (mPosition.y - mDimensions.y / 2.0f) ||
  213. pt.y > (mPosition.y + mDimensions.y / 2.0f);
  214. return !no;
  215. }
  216. void Button::OnClick()
  217. {
  218. // Call attached handler, if it exists
  219. if (mOnClick)
  220. {
  221. mOnClick();
  222. }
  223. }