ListScreen.cs 24 KB

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