ListScreen.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. //-----------------------------------------------------------------------------
  2. // ListScreen.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using System.Collections.Generic;
  9. using Microsoft.Xna.Framework;
  10. using Microsoft.Xna.Framework.Graphics;
  11. using Microsoft.Xna.Framework.Content;
  12. using RolePlayingGameData;
  13. using System.Collections.ObjectModel;
  14. namespace RolePlaying
  15. {
  16. abstract class ListScreen<T> : GameScreen
  17. {
  18. protected readonly Vector2 iconOffset = new Vector2(0f, 0f);
  19. protected readonly Vector2 descriptionTextPosition = new Vector2(200, 550);
  20. private readonly Vector2 listPositionTopPosition = new Vector2(1160, 354);
  21. private readonly Vector2 listPositionBottomPosition = new Vector2(1160, 384);
  22. private Texture2D backgroundTexture;
  23. private readonly Rectangle backgroundDestination =
  24. new Rectangle(0, 0, RolePlayingGame.BUFFER_WIDTH, RolePlayingGame.BUFFER_HEIGHT);
  25. private Texture2D fadeTexture;
  26. private Texture2D listTexture;
  27. private readonly Vector2 listTexturePosition = new Vector2(187f, 180f);
  28. protected readonly Vector2 listEntryStartPosition = new Vector2(200f, 202f);
  29. protected const int listLineSpacing = 76;
  30. private Texture2D plankTexture;
  31. private Vector2 plankTexturePosition;
  32. protected string titleText = String.Empty;
  33. protected Texture2D goldTexture;
  34. private readonly Vector2 goldTexturePosition = new Vector2(490f, 640f);
  35. protected string goldText = String.Empty;
  36. private readonly Vector2 goldTextPosition = new Vector2(565f, 648f);
  37. private Texture2D highlightTexture;
  38. private readonly Vector2 highlightStartPosition = new Vector2(170f, 237f);
  39. private Texture2D selectionArrowTexture;
  40. private readonly Vector2 selectionArrowPosition = new Vector2(135f, 245f);
  41. private Texture2D leftTriggerTexture;
  42. private readonly Vector2 leftTriggerTexturePosition = new Vector2(340f, 50f);
  43. protected string leftTriggerText = String.Empty;
  44. private Texture2D rightTriggerTexture;
  45. private readonly Vector2 rightTriggerTexturePosition = new Vector2(900f, 50f);
  46. protected string rightTriggerText = String.Empty;
  47. private Texture2D leftQuantityArrowTexture;
  48. private Texture2D rightQuantityArrowTexture;
  49. private Texture2D backButtonTexture;
  50. private readonly Vector2 backButtonTexturePosition = new Vector2(80f, 640f);
  51. protected string backButtonText = String.Empty;
  52. private Vector2 backButtonTextPosition = new Vector2(90f, 645f); // + tex width
  53. private Texture2D selectButtonTexture;
  54. private readonly Vector2 selectButtonTexturePosition = new Vector2(1150f, 640f);
  55. protected string selectButtonText = String.Empty;
  56. private Texture2D xButtonTexture;
  57. private readonly Vector2 xButtonTexturePosition = new Vector2(240f, 640f);
  58. protected string xButtonText = String.Empty;
  59. private Vector2 xButtonTextPosition = new Vector2(250f, 645f); // + tex width
  60. private Texture2D yButtonTexture;
  61. private readonly Vector2 yButtonTexturePosition = new Vector2(890f, 640f);
  62. protected string yButtonText = String.Empty;
  63. /// <summary>
  64. /// Get the list that this screen displays.
  65. /// </summary>
  66. /// <returns></returns>
  67. public abstract ReadOnlyCollection<T> GetDataList();
  68. /// <summary>
  69. /// The index of the selected entry.
  70. /// </summary>
  71. private int selectedIndex = 0;
  72. /// <summary>
  73. /// The index of the selected entry.
  74. /// </summary>
  75. public int SelectedIndex
  76. {
  77. get { return selectedIndex; }
  78. set
  79. {
  80. if (selectedIndex != value)
  81. {
  82. selectedIndex = value;
  83. EnsureVisible(selectedIndex);
  84. }
  85. }
  86. }
  87. /// <summary>
  88. /// Ensure that the given index is visible on the screen.
  89. /// </summary>
  90. public void EnsureVisible(int index)
  91. {
  92. if (index < startIndex)
  93. {
  94. // if it's above the current selection, set the first entry
  95. startIndex = index;
  96. }
  97. if (selectedIndex > (endIndex - 1))
  98. {
  99. startIndex += selectedIndex - (endIndex - 1);
  100. }
  101. // otherwise, it should be in the current selection already
  102. // -- note that the start and end indices are checked in Draw.
  103. }
  104. /// <summary>
  105. /// Move the current selection up one entry.
  106. /// </summary>
  107. protected virtual void MoveCursorUp()
  108. {
  109. if (SelectedIndex > 0)
  110. {
  111. SelectedIndex--;
  112. }
  113. }
  114. /// <summary>
  115. /// Move the current selection down one entry.
  116. /// </summary>
  117. protected virtual void MoveCursorDown()
  118. {
  119. SelectedIndex++; // safety-checked in Draw()
  120. }
  121. /// <summary>
  122. /// Decrease the selected quantity by one.
  123. /// </summary>
  124. protected virtual void MoveCursorLeft() { }
  125. /// <summary>
  126. /// Increase the selected quantity by one.
  127. /// </summary>
  128. protected virtual void MoveCursorRight() { }
  129. /// <summary>
  130. /// The first index displayed on the screen from the list.
  131. /// </summary>
  132. private int startIndex = 0;
  133. /// <summary>
  134. /// The first index displayed on the screen from the list.
  135. /// </summary>
  136. public int StartIndex
  137. {
  138. get { return startIndex; }
  139. set { startIndex = value; } // safety-checked in Draw
  140. }
  141. /// <summary>
  142. /// The last index displayed on the screen from the list.
  143. /// </summary>
  144. private int endIndex = 0;
  145. /// <summary>
  146. /// The last index displayed on the screen from the list.
  147. /// </summary>
  148. public int EndIndex
  149. {
  150. get { return endIndex; }
  151. set { endIndex = value; } // safety-checked in Draw
  152. }
  153. /// <summary>
  154. /// The maximum number of list entries that the screen can show at once.
  155. /// </summary>
  156. public const int MaximumListEntries = 4;
  157. /// <summary>
  158. /// Constructs a new ListScreen object.
  159. /// </summary>
  160. public ListScreen()
  161. : base()
  162. {
  163. this.IsPopup = true;
  164. }
  165. /// <summary>
  166. /// Load the graphics content from the content manager.
  167. /// </summary>
  168. public override void LoadContent()
  169. {
  170. ContentManager content = ScreenManager.Game.Content;
  171. // load the background textures
  172. fadeTexture = content.Load<Texture2D>(@"Textures\GameScreens\FadeScreen");
  173. backgroundTexture =
  174. content.Load<Texture2D>(@"Textures\GameScreens\GameScreenBkgd");
  175. listTexture =
  176. content.Load<Texture2D>(@"Textures\GameScreens\InfoDisplay");
  177. plankTexture =
  178. content.Load<Texture2D>(@"Textures\MainMenu\MainMenuPlank03");
  179. goldTexture =
  180. content.Load<Texture2D>(@"Textures\GameScreens\GoldIcon");
  181. // load the foreground textures
  182. highlightTexture =
  183. content.Load<Texture2D>(@"Textures\GameScreens\HighlightLarge");
  184. selectionArrowTexture =
  185. content.Load<Texture2D>(@"Textures\GameScreens\SelectionArrow");
  186. // load the trigger images
  187. leftTriggerTexture =
  188. content.Load<Texture2D>(@"Textures\Buttons\LeftTriggerButton");
  189. rightTriggerTexture =
  190. content.Load<Texture2D>(@"Textures\Buttons\RightTriggerButton");
  191. leftQuantityArrowTexture =
  192. content.Load<Texture2D>(@"Textures\Buttons\QuantityArrowLeft");
  193. rightQuantityArrowTexture =
  194. content.Load<Texture2D>(@"Textures\Buttons\QuantityArrowRight");
  195. backButtonTexture =
  196. content.Load<Texture2D>(@"Textures\Buttons\BButton");
  197. selectButtonTexture =
  198. content.Load<Texture2D>(@"Textures\Buttons\AButton");
  199. xButtonTexture =
  200. content.Load<Texture2D>(@"Textures\Buttons\XButton");
  201. yButtonTexture =
  202. content.Load<Texture2D>(@"Textures\Buttons\YButton");
  203. // calculate the centered positions
  204. Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
  205. plankTexturePosition = new Vector2(
  206. viewport.X + (viewport.Width - plankTexture.Width) / 2f, 67f);
  207. // adjust positions for texture sizes
  208. if (backButtonTexture != null)
  209. {
  210. backButtonTextPosition.X += backButtonTexture.Width;
  211. }
  212. if (xButtonTexture != null)
  213. {
  214. xButtonTextPosition.X += xButtonTexture.Width;
  215. }
  216. base.LoadContent();
  217. }
  218. /// <summary>
  219. /// Handle user input.
  220. /// </summary>
  221. public override void HandleInput()
  222. {
  223. if (InputManager.IsActionTriggered(InputManager.Action.PageLeft))
  224. {
  225. PageScreenLeft();
  226. }
  227. else if (InputManager.IsActionTriggered(InputManager.Action.PageRight))
  228. {
  229. PageScreenRight();
  230. }
  231. else if (InputManager.IsActionTriggered(InputManager.Action.CursorUp))
  232. {
  233. MoveCursorUp();
  234. }
  235. else if (InputManager.IsActionTriggered(InputManager.Action.CursorDown))
  236. {
  237. MoveCursorDown();
  238. }
  239. else if (InputManager.IsActionTriggered(InputManager.Action.IncreaseAmount))
  240. {
  241. MoveCursorRight();
  242. }
  243. else if (InputManager.IsActionTriggered(InputManager.Action.DecreaseAmount))
  244. {
  245. MoveCursorLeft();
  246. }
  247. else if (InputManager.IsActionTriggered(InputManager.Action.Back))
  248. {
  249. BackTriggered();
  250. }
  251. else if (InputManager.IsActionTriggered(InputManager.Action.Ok))
  252. {
  253. ReadOnlyCollection<T> dataList = GetDataList();
  254. if ((selectedIndex >= 0) && (selectedIndex < dataList.Count))
  255. {
  256. SelectTriggered(dataList[selectedIndex]);
  257. }
  258. }
  259. else if (InputManager.IsActionTriggered(InputManager.Action.DropUnEquip))
  260. {
  261. ReadOnlyCollection<T> dataList = GetDataList();
  262. if ((selectedIndex >= 0) && (selectedIndex < dataList.Count))
  263. {
  264. ButtonXPressed(dataList[selectedIndex]);
  265. }
  266. }
  267. else if (InputManager.IsActionTriggered(InputManager.Action.TakeView))
  268. {
  269. ReadOnlyCollection<T> dataList = GetDataList();
  270. if ((selectedIndex >= 0) && (selectedIndex < dataList.Count))
  271. {
  272. ButtonYPressed(dataList[selectedIndex]);
  273. }
  274. }
  275. base.HandleInput();
  276. }
  277. /// <summary>
  278. /// Switch to the screen to the "left" of this one in the UI, if any.
  279. /// </summary>
  280. protected virtual void PageScreenLeft() { }
  281. /// <summary>
  282. /// Switch to the screen to the "right" of this one in the UI, if any.
  283. /// </summary>
  284. protected virtual void PageScreenRight() { }
  285. /// <summary>
  286. /// Respond to the triggering of the Back action.
  287. /// </summary>
  288. protected virtual void BackTriggered()
  289. {
  290. ExitScreen();
  291. }
  292. /// <summary>
  293. /// Respond to the triggering of the Select action.
  294. /// </summary>
  295. protected virtual void SelectTriggered(T entry) { }
  296. /// <summary>
  297. /// Respond to the triggering of the X button (and related key).
  298. /// </summary>
  299. protected virtual void ButtonXPressed(T entry) { }
  300. /// <summary>
  301. /// Respond to the triggering of the Y button (and related key).
  302. /// </summary>
  303. protected virtual void ButtonYPressed(T entry) { }
  304. /// <summary>
  305. /// Draws the screen.
  306. /// </summary>
  307. public override void Draw(Microsoft.Xna.Framework.GameTime gameTime)
  308. {
  309. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  310. // get the content list
  311. ReadOnlyCollection<T> dataList = GetDataList();
  312. // turn off the buttons if the list is empty
  313. if (dataList.Count <= 0)
  314. {
  315. selectButtonText = String.Empty;
  316. xButtonText = String.Empty;
  317. yButtonText = String.Empty;
  318. }
  319. // fix the indices for the current list size
  320. SelectedIndex = (int)MathHelper.Clamp(SelectedIndex, 0, dataList.Count - 1);
  321. startIndex = (int)MathHelper.Clamp(startIndex, 0,
  322. dataList.Count - MaximumListEntries);
  323. endIndex = Math.Min(startIndex + MaximumListEntries, dataList.Count);
  324. spriteBatch.Begin();
  325. DrawBackground();
  326. if (dataList.Count > 0)
  327. {
  328. DrawListPosition(SelectedIndex + 1, dataList.Count);
  329. }
  330. DrawButtons();
  331. DrawPartyGold();
  332. DrawColumnHeaders();
  333. DrawTitle();
  334. // draw each item currently shown
  335. Vector2 position = listEntryStartPosition +
  336. new Vector2(0f, listLineSpacing / 2);
  337. if (startIndex >= 0)
  338. {
  339. for (int index = startIndex; index < endIndex; index++)
  340. {
  341. T entry = dataList[index];
  342. if (index == selectedIndex)
  343. {
  344. DrawSelection(position);
  345. DrawEntry(entry, position, true);
  346. DrawSelectedDescription(entry);
  347. }
  348. else
  349. {
  350. DrawEntry(entry, position, false);
  351. }
  352. position.Y += listLineSpacing;
  353. }
  354. }
  355. spriteBatch.End();
  356. }
  357. /// <summary>
  358. /// Draw the entry at the given position in the list.
  359. /// </summary>
  360. /// <param name="entry">The entry to draw.</param>
  361. /// <param name="position">The position to draw the entry at.</param>
  362. /// <param name="isSelected">If true, this entry is selected.</param>
  363. protected abstract void DrawEntry(T entry, Vector2 position, bool isSelected);
  364. /// <summary>
  365. /// Draw the selection graphics over the selected item.
  366. /// </summary>
  367. /// <param name="position"></param>
  368. protected virtual void DrawSelection(Vector2 position)
  369. {
  370. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  371. spriteBatch.Draw(highlightTexture,
  372. new Vector2(highlightStartPosition.X, position.Y), Color.White);
  373. spriteBatch.Draw(selectionArrowTexture,
  374. new Vector2(selectionArrowPosition.X, position.Y + 10f), Color.White);
  375. }
  376. /// <summary>
  377. /// Draw the background of the screen.
  378. /// </summary>
  379. protected virtual void DrawBackground()
  380. {
  381. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  382. spriteBatch.Draw(fadeTexture, backgroundDestination, Color.White);
  383. spriteBatch.Draw(backgroundTexture, backgroundDestination, Color.White);
  384. spriteBatch.Draw(listTexture, listTexturePosition, Color.White);
  385. }
  386. /// <summary>
  387. /// Draw the current list position in the appropriate location on the screen.
  388. /// </summary>
  389. /// <param name="position">The current position in the list.</param>
  390. /// <param name="total">The total elements in the list.</param>
  391. protected virtual void DrawListPosition(int position, int total)
  392. {
  393. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  394. // draw the top number - the current position in the list
  395. string listPositionTopText = position.ToString();
  396. Vector2 drawPosition = listPositionTopPosition;
  397. drawPosition.X -= (float)Math.Ceiling(
  398. Fonts.GearInfoFont.MeasureString(listPositionTopText).X / 2);
  399. spriteBatch.DrawString(Fonts.GearInfoFont, listPositionTopText,
  400. drawPosition, Fonts.CountColor);
  401. // draw the bottom number - the current position in the list
  402. string listPositionBottomText = total.ToString();
  403. drawPosition = listPositionBottomPosition;
  404. drawPosition.X -= (float)Math.Ceiling(
  405. Fonts.GearInfoFont.MeasureString(listPositionBottomText).X / 2);
  406. spriteBatch.DrawString(Fonts.GearInfoFont, listPositionBottomText,
  407. drawPosition, Fonts.CountColor);
  408. }
  409. /// <summary>
  410. /// Draw the party gold text.
  411. /// </summary>
  412. protected virtual void DrawPartyGold()
  413. {
  414. if (!IsActive)
  415. {
  416. return;
  417. }
  418. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  419. spriteBatch.Draw(goldTexture, goldTexturePosition, Color.White);
  420. spriteBatch.DrawString(Fonts.ButtonNamesFont,
  421. Fonts.GetGoldString(Session.Party.PartyGold), goldTextPosition,
  422. Color.White);
  423. }
  424. /// <summary>
  425. /// Draw the description of the selected item.
  426. /// </summary>
  427. protected abstract void DrawSelectedDescription(T entry);
  428. /// <summary>
  429. /// Draw the column headers above the list.
  430. /// </summary>
  431. protected abstract void DrawColumnHeaders();
  432. /// <summary>
  433. /// Draw all of the buttons used by the screen.
  434. /// </summary>
  435. protected virtual void DrawButtons()
  436. {
  437. if (!IsActive)
  438. {
  439. return;
  440. }
  441. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  442. // draw the left trigger texture and text
  443. if ((leftTriggerTexture != null) && !String.IsNullOrEmpty(leftTriggerText))
  444. {
  445. Vector2 position = leftTriggerTexturePosition + new Vector2(
  446. leftTriggerTexture.Width / 2f - (float)Math.Ceiling(
  447. Fonts.PlayerStatisticsFont.MeasureString(leftTriggerText).X / 2f),
  448. 90f);
  449. spriteBatch.Draw(leftTriggerTexture, leftTriggerTexturePosition,
  450. Color.White);
  451. spriteBatch.DrawString(Fonts.PlayerStatisticsFont, leftTriggerText,
  452. position, Color.Black);
  453. }
  454. // draw the right trigger texture and text
  455. if ((rightTriggerTexture != null) && !String.IsNullOrEmpty(rightTriggerText))
  456. {
  457. Vector2 position = rightTriggerTexturePosition + new Vector2(
  458. rightTriggerTexture.Width / 2f - (float)Math.Ceiling(
  459. Fonts.PlayerStatisticsFont.MeasureString(rightTriggerText).X / 2f),
  460. 90f);
  461. spriteBatch.Draw(rightTriggerTexture, rightTriggerTexturePosition,
  462. Color.White);
  463. spriteBatch.DrawString(Fonts.PlayerStatisticsFont, rightTriggerText,
  464. position, Color.Black);
  465. }
  466. // draw the left trigger texture and text
  467. if ((backButtonTexture != null) && !String.IsNullOrEmpty(backButtonText))
  468. {
  469. spriteBatch.Draw(backButtonTexture, backButtonTexturePosition,
  470. Color.White);
  471. spriteBatch.DrawString(Fonts.ButtonNamesFont, backButtonText,
  472. backButtonTextPosition, Color.White);
  473. }
  474. // draw the left trigger texture and text
  475. if ((selectButtonTexture != null) && !String.IsNullOrEmpty(selectButtonText))
  476. {
  477. spriteBatch.Draw(selectButtonTexture, selectButtonTexturePosition,
  478. Color.White);
  479. Vector2 position = selectButtonTexturePosition - new Vector2(
  480. Fonts.ButtonNamesFont.MeasureString(selectButtonText).X, 0f) +
  481. new Vector2(0f, 5f);
  482. spriteBatch.DrawString(Fonts.ButtonNamesFont, selectButtonText,
  483. position, Color.White);
  484. }
  485. // draw the left trigger texture and text
  486. if ((xButtonTexture != null) && !String.IsNullOrEmpty(xButtonText))
  487. {
  488. spriteBatch.Draw(xButtonTexture, xButtonTexturePosition,
  489. Color.White);
  490. spriteBatch.DrawString(Fonts.ButtonNamesFont, xButtonText,
  491. xButtonTextPosition, Color.White);
  492. }
  493. // draw the left trigger texture and text
  494. if ((yButtonTexture != null) && !String.IsNullOrEmpty(yButtonText))
  495. {
  496. spriteBatch.Draw(yButtonTexture, yButtonTexturePosition,
  497. Color.White);
  498. Vector2 position = yButtonTexturePosition - new Vector2(
  499. Fonts.ButtonNamesFont.MeasureString(yButtonText).X, 0f) +
  500. new Vector2(0f, 5f);
  501. spriteBatch.DrawString(Fonts.ButtonNamesFont, yButtonText,
  502. position, Color.White);
  503. }
  504. }
  505. /// <summary>
  506. /// Draw the title of the screen, if any.
  507. /// </summary>
  508. protected virtual void DrawTitle()
  509. {
  510. SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
  511. // draw the left trigger texture and text
  512. if ((plankTexture != null) && !String.IsNullOrEmpty(titleText))
  513. {
  514. Vector2 titleTextSize = Fonts.HeaderFont.MeasureString(titleText);
  515. Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
  516. Vector2 position = new Vector2(
  517. (float)Math.Floor(viewport.X + viewport.Width / 2 -
  518. titleTextSize.X / 2f), 90f);
  519. spriteBatch.Draw(plankTexture, plankTexturePosition, Color.White);
  520. spriteBatch.DrawString(Fonts.HeaderFont, titleText, position,
  521. Fonts.TitleColor);
  522. }
  523. }
  524. }
  525. }