/src/MenuLog.cpp

http://github.com/clintbellanger/flare · C++ · 293 lines · 175 code · 64 blank · 54 comment · 32 complexity · 863dc4bfe93841342e0288db9af62eb9 MD5 · raw file

  1. /*
  2. Copyright 2011 Clint Bellanger
  3. This file is part of FLARE.
  4. FLARE is free software: you can redistribute it and/or modify it under the terms
  5. of the GNU General Public License as published by the Free Software Foundation,
  6. either version 3 of the License, or (at your option) any later version.
  7. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY
  8. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  9. PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License along with
  11. FLARE. If not, see http://www.gnu.org/licenses/
  12. */
  13. /**
  14. * class MenuLog
  15. */
  16. #include "MenuLog.h"
  17. #include "SharedResources.h"
  18. #include "WidgetLabel.h"
  19. using namespace std;
  20. MenuLog::MenuLog() {
  21. visible = false;
  22. for (int i=0; i<LOG_TYPE_COUNT; i++) {
  23. log_count[i] = 0;
  24. for (int j=0; j<MAX_LOG_MESSAGES; j++) {
  25. msg_buffer[i][j] = NULL;
  26. }
  27. }
  28. active_log = 0;
  29. tab_labels[LOG_TYPE_MESSAGES] = msg->get("Messages");
  30. tab_labels[LOG_TYPE_QUESTS] = msg->get("Quests");
  31. tab_labels[LOG_TYPE_STATISTICS] = msg->get("Statistics");
  32. // TODO: allow menu size to be configurable
  33. menu_area.x = 0;
  34. menu_area.y = (VIEW_H - 416)/2;
  35. menu_area.w = 320;
  36. menu_area.h = 416;
  37. list_area.x = menu_area.x + 40;
  38. list_area.y = menu_area.y + 56;
  39. list_area.w = 224;
  40. list_area.h = 328;
  41. tabs_area.x = menu_area.x + 32;
  42. tabs_area.y = menu_area.y + 30;
  43. tabs_area.w = 240;
  44. tabs_area.h = 20;
  45. tab_padding.y = 4;
  46. tab_padding.x = 6;
  47. paragraph_spacing = font->getLineHeight()/2;
  48. for (int i=0; i<LOG_TYPE_COUNT; i++) {
  49. tab_rect[i].y = tabs_area.y;
  50. tab_rect[i].h = tabs_area.h;
  51. if (i==0) tab_rect[i].x = tabs_area.x;
  52. else tab_rect[i].x = tab_rect[i-1].x + tab_rect[i-1].w;
  53. tab_rect[i].w = font->calc_width(tab_labels[i]) + tab_padding.x + tab_padding.x;
  54. }
  55. loadGraphics();
  56. closeButton = new WidgetButton(mods->locate("images/menus/buttons/button_x.png"));
  57. closeButton->pos.x = 294;
  58. closeButton->pos.y = (VIEW_H - 480)/2 + 34;
  59. }
  60. void MenuLog::loadGraphics() {
  61. background = IMG_Load(mods->locate("images/menus/log.png").c_str());
  62. tab_active = IMG_Load(mods->locate("images/menus/tab_active.png").c_str());
  63. tab_inactive = IMG_Load(mods->locate("images/menus/tab_inactive.png").c_str());
  64. if(!background || !tab_active || !tab_inactive) {
  65. fprintf(stderr, "Couldn't load image: %s\n", IMG_GetError());
  66. SDL_Quit();
  67. }
  68. // optimize
  69. SDL_Surface *cleanup = background;
  70. background = SDL_DisplayFormatAlpha(background);
  71. SDL_FreeSurface(cleanup);
  72. cleanup = tab_active;
  73. tab_active = SDL_DisplayFormatAlpha(tab_active);
  74. SDL_FreeSurface(cleanup);
  75. cleanup = tab_inactive;
  76. tab_inactive = SDL_DisplayFormatAlpha(tab_inactive);
  77. SDL_FreeSurface(cleanup);
  78. }
  79. /**
  80. * Perform one frame of logic
  81. */
  82. void MenuLog::logic() {
  83. if (!visible) return;
  84. if (closeButton->checkClick()) {
  85. visible = false;
  86. }
  87. }
  88. /**
  89. * Render graphics for this frame when the menu is open
  90. */
  91. void MenuLog::render() {
  92. if (!visible) return;
  93. SDL_Rect src;
  94. // background
  95. src.x = 0;
  96. src.y = 0;
  97. src.w = menu_area.w;
  98. src.h = menu_area.h;
  99. SDL_BlitSurface(background, &src, screen, &menu_area);
  100. // close button
  101. closeButton->render();
  102. // text overlay
  103. WidgetLabel label;
  104. label.set(menu_area.x+160, menu_area.y+8, JUSTIFY_CENTER, VALIGN_TOP, msg->get("Log"), FONT_WHITE);
  105. label.render();
  106. // display tabs
  107. for (int i=0; i<LOG_TYPE_COUNT; i++) {
  108. renderTab(i);
  109. }
  110. // display latest log messages
  111. int display_number = 0;
  112. int total_size = 0;
  113. // first calculate how many entire messages can fit in the log view
  114. for (int i=log_count[active_log]-1; i>=0; i--) {
  115. total_size += msg_buffer[active_log][i]->h + paragraph_spacing;
  116. if (total_size < list_area.h) display_number++;
  117. else break;
  118. }
  119. // now display these messages
  120. SDL_Rect dest;
  121. dest.x = list_area.x;
  122. dest.y = list_area.y;
  123. for (int i=log_count[active_log]-display_number; i<log_count[active_log]; i++) {
  124. SDL_BlitSurface(msg_buffer[active_log][i], NULL, screen, &dest);
  125. dest.y += msg_buffer[active_log][i]->h + paragraph_spacing;
  126. }
  127. }
  128. /**
  129. * Display the specified tab
  130. * Render the font and tab background
  131. * The active tab will look different
  132. */
  133. void MenuLog::renderTab(int log_type) {
  134. int i = log_type;
  135. // draw tab background
  136. SDL_Rect src;
  137. SDL_Rect dest;
  138. src.x = src.y = 0;
  139. dest.x = tab_rect[i].x;
  140. dest.y = tab_rect[i].y;
  141. src.w = tab_rect[i].w;
  142. src.h = tab_rect[i].h;
  143. if (i == active_log)
  144. SDL_BlitSurface(tab_active, &src, screen, &dest);
  145. else
  146. SDL_BlitSurface(tab_inactive, &src, screen, &dest);
  147. // draw tab right edge
  148. src.x = 128 - tab_padding.x;
  149. src.w = tab_padding.x;
  150. dest.x = tab_rect[i].x + tab_rect[i].w - tab_padding.x;
  151. if (i == active_log)
  152. SDL_BlitSurface(tab_active, &src, screen, &dest);
  153. else
  154. SDL_BlitSurface(tab_inactive, &src, screen, &dest);
  155. // set tab label text color
  156. int tab_label_color;
  157. if (i == active_log) tab_label_color = FONT_WHITE;
  158. else tab_label_color = FONT_GREY;
  159. WidgetLabel label;
  160. label.set(tab_rect[i].x + tab_padding.x, tab_rect[i].y + tab_padding.y, JUSTIFY_LEFT, VALIGN_TOP, tab_labels[i], tab_label_color);
  161. label.render();
  162. }
  163. /**
  164. * Add a new message to the log
  165. */
  166. void MenuLog::add(const string& s, int log_type) {
  167. if (log_count[log_type] == MAX_LOG_MESSAGES) {
  168. remove(0, log_type);
  169. }
  170. // add new message
  171. log_msg[log_type][log_count[log_type]] = s;
  172. // render the log entry and store it in a buffer
  173. Point size = font->calc_size(s, list_area.w);
  174. msg_buffer[log_type][log_count[log_type]] = createSurface(size.x, size.y);
  175. font->renderShadowed(s, 0, 0, JUSTIFY_LEFT, msg_buffer[log_type][log_count[log_type]], list_area.w, FONT_WHITE);
  176. log_count[log_type]++;
  177. }
  178. /**
  179. * Remove log message with the given id
  180. */
  181. void MenuLog::remove(int msg_index, int log_type) {
  182. SDL_FreeSurface(msg_buffer[log_type][msg_index]);
  183. msg_buffer[log_type][msg_index] = NULL;
  184. for (int i=msg_index; i<MAX_LOG_MESSAGES-1; i++) {
  185. log_msg[log_type][i] = log_msg[log_type][i+1];
  186. msg_buffer[log_type][i] = msg_buffer[log_type][i+1];
  187. }
  188. log_count[log_type]--;
  189. }
  190. /**
  191. * Called by MenuManager
  192. * The tab area was clicked. Change the active tab
  193. */
  194. void MenuLog::clickTab(Point mouse) {
  195. for (int i=0; i<LOG_TYPE_COUNT; i++) {
  196. if(isWithin(tab_rect[i], mouse)) {
  197. active_log = i;
  198. return;
  199. }
  200. }
  201. }
  202. void MenuLog::clear(int log_type) {
  203. log_count[log_type] = 0;
  204. for (int i=0; i<MAX_LOG_MESSAGES; i++) {
  205. SDL_FreeSurface(msg_buffer[log_type][i]);
  206. msg_buffer[log_type][i] = NULL;
  207. }
  208. }
  209. void MenuLog::clear() {
  210. for (int i=0; i<LOG_TYPE_COUNT; i++) {
  211. clear(i);
  212. }
  213. }
  214. MenuLog::~MenuLog() {
  215. for (int i=0; i<LOG_TYPE_COUNT; i++) {
  216. log_count[i] = 0;
  217. for (int j=0; j<MAX_LOG_MESSAGES; j++) {
  218. SDL_FreeSurface(msg_buffer[i][j]);
  219. }
  220. }
  221. SDL_FreeSurface(background);
  222. SDL_FreeSurface(tab_active);
  223. SDL_FreeSurface(tab_inactive);
  224. delete closeButton;
  225. }