Beams.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*namespace Terminal.Gui.TextEffects.Effects;
  2. public class BeamsConfig : EffectConfig
  3. {
  4. public string [] BeamRowSymbols { get; set; } = { "▂", "▁", "_" };
  5. public string [] BeamColumnSymbols { get; set; } = { "▌", "▍", "▎", "▏" };
  6. public int BeamDelay { get; set; } = 10;
  7. public (int, int) BeamRowSpeedRange { get; set; } = (10, 40);
  8. public (int, int) BeamColumnSpeedRange { get; set; } = (6, 10);
  9. public Color [] BeamGradientStops { get; set; } = { new Color ("ffffff"), new Color ("00D1FF"), new Color ("8A008A") };
  10. public int [] BeamGradientSteps { get; set; } = { 2, 8 };
  11. public int BeamGradientFrames { get; set; } = 2;
  12. public Color [] FinalGradientStops { get; set; } = { new Color ("8A008A"), new Color ("00D1FF"), new Color ("ffffff") };
  13. public int [] FinalGradientSteps { get; set; } = { 12 };
  14. public int FinalGradientFrames { get; set; } = 5;
  15. public GradientDirection FinalGradientDirection { get; set; } = GradientDirection.Vertical;
  16. public int FinalWipeSpeed { get; set; } = 1;
  17. }
  18. public class Beams : BaseEffect<BeamsConfig>
  19. {
  20. public Beams (string inputData) : base (inputData)
  21. {
  22. }
  23. protected override BaseEffectIterator<BeamsConfig> CreateIterator ()
  24. {
  25. return new BeamsIterator (this);
  26. }
  27. }
  28. public class BeamsIterator : BaseEffectIterator<BeamsConfig>
  29. {
  30. private class Group
  31. {
  32. public List<EffectCharacter> Characters { get; private set; }
  33. public string Direction { get; private set; }
  34. private Terminal Terminal;
  35. private BeamsConfig Config;
  36. private double Speed;
  37. private float NextCharacterCounter;
  38. private List<EffectCharacter> SortedCharacters;
  39. public Group (List<EffectCharacter> characters, string direction, Terminal terminal, BeamsConfig config)
  40. {
  41. Characters = characters;
  42. Direction = direction;
  43. Terminal = terminal;
  44. Config = config;
  45. Speed = new Random ().Next (config.BeamRowSpeedRange.Item1, config.BeamRowSpeedRange.Item2) * 0.1;
  46. NextCharacterCounter = 0;
  47. SortedCharacters = direction == "row"
  48. ? characters.OrderBy (c => c.InputCoord.Column).ToList ()
  49. : characters.OrderBy (c => c.InputCoord.Row).ToList ();
  50. if (new Random ().Next (0, 2) == 0)
  51. {
  52. SortedCharacters.Reverse ();
  53. }
  54. }
  55. public void IncrementNextCharacterCounter ()
  56. {
  57. NextCharacterCounter += (float)Speed;
  58. }
  59. public EffectCharacter GetNextCharacter ()
  60. {
  61. NextCharacterCounter -= 1;
  62. var nextCharacter = SortedCharacters.First ();
  63. SortedCharacters.RemoveAt (0);
  64. if (nextCharacter.Animation.ActiveScene != null)
  65. {
  66. nextCharacter.Animation.ActiveScene.ResetScene ();
  67. return null;
  68. }
  69. Terminal.SetCharacterVisibility (nextCharacter, true);
  70. nextCharacter.Animation.ActivateScene (nextCharacter.Animation.QueryScene ("beam_" + Direction));
  71. return nextCharacter;
  72. }
  73. public bool Complete ()
  74. {
  75. return !SortedCharacters.Any ();
  76. }
  77. }
  78. private List<Group> PendingGroups = new List<Group> ();
  79. private Dictionary<EffectCharacter, Color> CharacterFinalColorMap = new Dictionary<EffectCharacter, Color> ();
  80. private List<Group> ActiveGroups = new List<Group> ();
  81. private int Delay = 0;
  82. private string Phase = "beams";
  83. private List<List<EffectCharacter>> FinalWipeGroups;
  84. public BeamsIterator (Beams effect) : base (effect)
  85. {
  86. Build ();
  87. }
  88. private void Build ()
  89. {
  90. var finalGradient = new Gradient (Effect.Config.FinalGradientStops, Effect.Config.FinalGradientSteps);
  91. var finalGradientMapping = finalGradient.BuildCoordinateColorMapping (
  92. Effect.Terminal.Canvas.Top,
  93. Effect.Terminal.Canvas.Right,
  94. Effect.Config.FinalGradientDirection
  95. );
  96. foreach (var character in Effect.Terminal.GetCharacters (fillChars: true))
  97. {
  98. CharacterFinalColorMap [character] = finalGradientMapping [character.InputCoord];
  99. }
  100. var beamGradient = new Gradient (Effect.Config.BeamGradientStops, Effect.Config.BeamGradientSteps);
  101. var groups = new List<Group> ();
  102. foreach (var row in Effect.Terminal.GetCharactersGrouped (Terminal.CharacterGroup.RowTopToBottom, fillChars: true))
  103. {
  104. groups.Add (new Group (row, "row", Effect.Terminal, Effect.Config));
  105. }
  106. foreach (var column in Effect.Terminal.GetCharactersGrouped (Terminal.CharacterGroup.ColumnLeftToRight, fillChars: true))
  107. {
  108. groups.Add (new Group (column, "column", Effect.Terminal, Effect.Config));
  109. }
  110. foreach (var group in groups)
  111. {
  112. foreach (var character in group.Characters)
  113. {
  114. var beamRowScene = character.Animation.NewScene (id: "beam_row");
  115. var beamColumnScene = character.Animation.NewScene (id: "beam_column");
  116. beamRowScene.ApplyGradientToSymbols (
  117. beamGradient, Effect.Config.BeamRowSymbols, Effect.Config.BeamGradientFrames);
  118. beamColumnScene.ApplyGradientToSymbols (
  119. beamGradient, Effect.Config.BeamColumnSymbols, Effect.Config.BeamGradientFrames);
  120. var fadedColor = character.Animation.AdjustColorBrightness (CharacterFinalColorMap [character], 0.3f);
  121. var fadeGradient = new Gradient (CharacterFinalColorMap [character], fadedColor, steps: 10);
  122. beamRowScene.ApplyGradientToSymbols (fadeGradient, character.InputSymbol, 5);
  123. beamColumnScene.ApplyGradientToSymbols (fadeGradient, character.InputSymbol, 5);
  124. var brightenGradient = new Gradient (fadedColor, CharacterFinalColorMap [character], steps: 10);
  125. var brightenScene = character.Animation.NewScene (id: "brighten");
  126. brightenScene.ApplyGradientToSymbols (
  127. brightenGradient, character.InputSymbol, Effect.Config.FinalGradientFrames);
  128. }
  129. }
  130. PendingGroups = groups;
  131. new Random ().Shuffle (PendingGroups);
  132. }
  133. public override bool MoveNext ()
  134. {
  135. if (Phase != "complete" || ActiveCharacters.Any ())
  136. {
  137. if (Phase == "beams")
  138. {
  139. if (Delay == 0)
  140. {
  141. if (PendingGroups.Any ())
  142. {
  143. for (int i = 0; i < new Random ().Next (1, 6); i++)
  144. {
  145. if (PendingGroups.Any ())
  146. {
  147. ActiveGroups.Add (PendingGroups.First ());
  148. PendingGroups.RemoveAt (0);
  149. }
  150. }
  151. }
  152. Delay = Effect.Config.BeamDelay;
  153. }
  154. else
  155. {
  156. Delay--;
  157. }
  158. foreach (var group in ActiveGroups)
  159. {
  160. group.IncrementNextCharacterCounter ();
  161. if ((int)group.NextCharacterCounter > 1)
  162. {
  163. for (int i = 0; i < (int)group.NextCharacterCounter; i++)
  164. {
  165. if (!group.Complete ())
  166. {
  167. var nextChar = group.GetNextCharacter ();
  168. if (nextChar != null)
  169. {
  170. ActiveCharacters.Add (nextChar);
  171. }
  172. }
  173. }
  174. }
  175. }
  176. ActiveGroups = ActiveGroups.Where (g => !g.Complete ()).ToList ();
  177. if (!PendingGroups.Any () && !ActiveGroups.Any () && !ActiveCharacters.Any ())
  178. {
  179. Phase = "final_wipe";
  180. }
  181. }
  182. else if (Phase == "final_wipe")
  183. {
  184. if (FinalWipeGroups.Any ())
  185. {
  186. for (int i = 0; i < Effect.Config.FinalWipeSpeed; i++)
  187. {
  188. if (!FinalWipeGroups.Any ()) break;
  189. var nextGroup = FinalWipeGroups.First ();
  190. FinalWipeGroups.RemoveAt (0);
  191. foreach (var character in nextGroup)
  192. {
  193. character.Animation.ActivateScene (character.Animation.QueryScene ("brighten"));
  194. Effect.Terminal.SetCharacterVisibility (character, true);
  195. ActiveCharacters.Add (character);
  196. }
  197. }
  198. }
  199. else
  200. {
  201. Phase = "complete";
  202. }
  203. }
  204. Update ();
  205. return true;
  206. }
  207. else
  208. {
  209. return false;
  210. }
  211. }
  212. }
  213. */