EntryGroup.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. using Microsoft.Xna.Framework;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. namespace FF8
  6. {
  7. public class EntryGroup : IEnumerator, IEnumerable
  8. {
  9. #region Fields
  10. private List<Entry> list;
  11. private Rectangle rectangle;
  12. public EntryGroup(int capacity = 1)
  13. {
  14. list = new List<Entry>(capacity);
  15. rectangle = new Rectangle();
  16. }
  17. public EntryGroup(params Entry[] entries)
  18. {
  19. list = new List<Entry>(entries.Length);
  20. rectangle = new Rectangle();
  21. Add(entries);
  22. }
  23. #endregion Fields
  24. #region Properties
  25. public int Count => list.Count;
  26. public int Height { get => rectangle.Height; private set => rectangle.Height = value; }
  27. public int Width { get => rectangle.Width; private set => rectangle.Width = value; }
  28. public Rectangle GetRectangle => rectangle;
  29. public object Current
  30. {
  31. get { return list[position-1]; }
  32. }
  33. #endregion Properties
  34. #region Indexers
  35. /// <summary>
  36. /// donno if this works for assigning. perfer add.
  37. /// </summary>
  38. /// <param name="id"></param>
  39. /// <returns></returns>
  40. public Entry this[int id] => list[id]; /*set { if (list.Count - 1 < id) Add(value); else list[id] = value; }*/
  41. #endregion Indexers
  42. #region Methods
  43. private Vector2 nag_Offset = new Vector2();
  44. private Vector2 pos_Offset = new Vector2();
  45. public void Add(params Entry[] entries)
  46. {
  47. foreach (Entry entry in entries)
  48. {
  49. //TODO fix math
  50. if (list.Count >= 1)
  51. {
  52. //DiscFix
  53. if (entry.Height < float.Epsilon)
  54. {
  55. entry.Height = Height; // one item had a missing height.
  56. if (Math.Abs(nag_Offset.X) + pos_Offset.X + entry.Offset.X < float.Epsilon) //assumes if the items are overlapping put them next to each other instead.
  57. entry.Offset.X = (short)Width;
  58. }
  59. //BarFix
  60. //has 2 sides and no filling.
  61. //if(entry.CurrentPos == 1872)
  62. if (list.Capacity == 2 && list.Count == 1 && (list[0].Width * 2) + list[0].X == entry.X && list[0].Y == entry.Y)
  63. Add(new Entry
  64. {
  65. X = entry.X - list[0].Width,
  66. Y = entry.Y,
  67. Size = list[0].Size,
  68. Tile = Vector2.UnitX,
  69. Offset = new Vector2((int)list[0].Width, 0),
  70. End = new Vector2((int)-list[0].Width, 0)
  71. });
  72. }
  73. list.Add(entry);
  74. Vector2 size = Abs(entry.Offset) + entry.Size;
  75. if (Width < size.X) Width = (int)size.X;
  76. if (Height < size.Y) Height = (int)size.Y;
  77. }
  78. }
  79. internal static Vector2 Abs(Vector2 v2) => new Vector2(Math.Abs(v2.X), Math.Abs(v2.Y));
  80. internal static Point RoundedPoint(Vector2 v) => v.RoundedPoint();
  81. internal void Draw(List<TextureHandler> textures, int pallet, Rectangle inputdst, Vector2 inscale, float fade = 1f) =>
  82. Draw(textures, list, pallet, inputdst, inscale, fade, new Point(Width, Height));
  83. internal static int GetChange(int tot,int goal, float scale = 1f)
  84. {
  85. return (int) Math.Round(Math.Abs(tot* scale - goal));
  86. }
  87. internal static void Draw(List<TextureHandler> textures,List<Entry> elist, int pallet, Rectangle inputdst, Vector2 inscale, float fade, Point totalSize)
  88. {
  89. Rectangle dst;
  90. inscale = Abs(inscale);
  91. inputdst.Width = Math.Abs(inputdst.Width);
  92. inputdst.Height = Math.Abs(inputdst.Height);
  93. if (inputdst.X + inputdst.Width < 0 || inputdst.Y + inputdst.Height < 0) return;
  94. Vector2 autoscale = new Vector2((float)inputdst.Width / totalSize.X, (float)inputdst.Height / totalSize.Y);
  95. Vector2 scale;
  96. if (inscale == Vector2.Zero || inscale == Vector2.UnitX)
  97. scale = new Vector2(autoscale.X);
  98. else if (inscale == Vector2.UnitY)
  99. scale = new Vector2(autoscale.Y);
  100. else
  101. scale = inscale;
  102. foreach (Entry e in elist)
  103. {
  104. if (totalSize == new Point(0))
  105. {
  106. totalSize.X = (int)e.Width;
  107. totalSize.Y = (int)e.Height;
  108. }
  109. int cpallet = e.CustomPallet < 0 || e.CustomPallet >= textures.Count ? pallet : e.CustomPallet;
  110. dst = inputdst;
  111. Vector2 Offset = e.Offset * scale;
  112. Point offset2 = RoundedPoint(e.End * scale);
  113. dst.Offset(e.Snap_Right ? inputdst.Width : 0, e.Snap_Bottom ? inputdst.Height : 0);
  114. dst.Offset(RoundedPoint(Offset));
  115. dst.Size = RoundedPoint(e.Size * scale);
  116. Rectangle src = e.GetRectangle;
  117. bool testY = false;
  118. bool testX = false;
  119. if ((inputdst.Width!=0) && dst.X + dst.Width > inputdst.X + inputdst.Width)
  120. {
  121. int change = GetChange(totalSize.X,inputdst.Width,scale.X);
  122. src.Width -= (int)Math.Round(change / scale.X);
  123. dst.Width -= change;
  124. }
  125. else if (e.Fill.X > 0 && autoscale.X > scale.X)
  126. {
  127. scale.X = autoscale.X;
  128. dst.Width = (int)Math.Round((src.Width * autoscale.X));
  129. }
  130. if ((inputdst.Height != 0) && dst.Y + dst.Height > inputdst.Y + inputdst.Height)
  131. {
  132. int change = GetChange(totalSize.Y, inputdst.Height, scale.Y); ;
  133. src.Height -= (int)Math.Round(change / scale.Y);
  134. dst.Height -= change;
  135. }
  136. else if (e.Fill.Y > 0 && autoscale.Y > scale.Y)
  137. {
  138. scale.Y = autoscale.Y;
  139. dst.Height = (int)Math.Round((src.Height * autoscale.Y));
  140. }
  141. if (dst.Height <= 0 || dst.Height <= 0) continue; //infinate loop prevention
  142. do
  143. {
  144. do
  145. {
  146. if (e.Tile.Y > 0)
  147. {
  148. testY = (dst.Y + dst.Height) < (inputdst.Y + inputdst.Height + offset2.Y);
  149. if (!testY)
  150. {
  151. int correction = (inputdst.Y + inputdst.Height + offset2.Y) - (dst.Y + dst.Height);
  152. dst.Height += correction;
  153. src.Height += (int)Math.Round(correction / scale.Y);
  154. }
  155. }
  156. if (e.Tile.X > 0)
  157. {
  158. testX = (dst.X + dst.Width) < (inputdst.X + inputdst.Width + offset2.X);
  159. if (!testX)
  160. {
  161. int correction = (inputdst.X + inputdst.Width + offset2.X) - (dst.X + dst.Width);
  162. dst.Width += correction;
  163. src.Width += (int)Math.Round(correction / scale.X);
  164. }
  165. }
  166. textures[cpallet].Draw(dst, src, Color.White * fade);
  167. if (e.Tile.Y > 0)
  168. {
  169. dst.Y += dst.Height;
  170. }
  171. if (e.Tile.X > 0)
  172. {
  173. dst.X += dst.Width;
  174. }
  175. }
  176. while (e.Tile.Y > 0 && testY);
  177. }
  178. while (e.Tile.X > 0 && testX);
  179. }
  180. }
  181. int position = 0;
  182. public bool MoveNext() => ++position<=list.Count;
  183. public void Reset() => position = 0;
  184. public IEnumerator GetEnumerator() => this;
  185. #endregion Methods
  186. }
  187. }