tools.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /**
  2. \brief ScriptCallQueue Class provide "lazy" calls - when we don't want to execute function immediately but later during frame update (used mainly in UI)
  3. \n usage:
  4. @code
  5. class Arkanoid extends Game
  6. {
  7. ref ScriptCallQueue m_CallQueue = new ScriptCallQueue();
  8. ScriptCallQueue GetCallQueue() {
  9. return m_CallQueue;
  10. }
  11. override void OnUpdate(float timeslice)
  12. {
  13. m_CallQueue.Tick(timeslice);
  14. ...
  15. }
  16. ...
  17. }
  18. class MyObject
  19. {
  20. int m_cnt = 0;
  21. void Hello(int p1, string p2)
  22. {
  23. Print("Hello( " + p1 + " , " + p2 + ")");
  24. }
  25. void Test()
  26. {
  27. Print(m_cnt);
  28. m_cnt++;
  29. if (m_cnt > 10)
  30. {
  31. ScriptCallQueue queue = GetGame().GetCallQueue();
  32. queue.Remove(Test);
  33. }
  34. }
  35. }
  36. void Test(MyObject obj)
  37. {
  38. ScriptCallQueue queue = GetGame().GetCallQueue();
  39. queue.CallLater(obj.Hello, 5000, false, 65, "world"); // adds call 'obj.Hello(65, "world")' into queue, and it will be executed once after 5s
  40. queue.CallLater(obj.Test, 3000, true); // adds call 'obj.Test()' into queue, and it will be executed each 3s
  41. queue.Call(obj.Hello, 72, "world 2"); // adds call 'obj.Hello(72, "world 2")' into queue, and it will be executed next frame (on next call of ScriptCallQueue.Tick)
  42. }
  43. @endcode
  44. */
  45. class ScriptCallQueue
  46. {
  47. //! executes calls on queue if their time is already elapsed, if 'repeat = false' call is removed from queue
  48. proto native void Tick(float timeslice);
  49. //! adds call into the queue with given parameters and arguments (arguments are held in memory until the call is executed/removed or ScriptCallQueue is destroyed)
  50. proto void Call(func fn, void param1 = NULL, void param2 = NULL, void param3 = NULL, void param4 = NULL, void param5 = NULL, void param6 = NULL, void param7 = NULL, void param8 = NULL, void param9 = NULL);
  51. //! adds call into the queue with given parameters and arguments (arguments are held in memory until the call is executed/removed or ScriptCallQueue is destroyed)
  52. proto void CallByName(Class obj, string fnName , Param params = NULL);
  53. //! adds call into the queue with given parameters and arguments (arguments are held in memory until the call is executed/removed or ScriptCallQueue is destroyed)
  54. proto void CallLater(func fn, int delay = 0, bool repeat = false, void param1 = NULL, void param2 = NULL, void param3 = NULL, void param4 = NULL, void param5 = NULL, void param6 = NULL, void param7 = NULL, void param8 = NULL, void param9 = NULL);
  55. //! adds call into the queue with given parameters and arguments (arguments are held in memory until the call is executed/removed or ScriptCallQueue is destroyed)
  56. proto void CallLaterByName(Class obj, string fnName, int delay = 0, bool repeat = false, Param params = NULL);
  57. //! remove specific call from queue
  58. proto void Remove(func fn);
  59. //! return Remaining time to the call execution (in miliseconds)
  60. proto int GetRemainingTime(func fn);
  61. //! remove specific call from queue
  62. proto void RemoveByName(Class obj, string fnName);
  63. //! return Remaining time to the call execution (in miliseconds)
  64. proto int GetRemainingTimeByName(Class obj, string fnName);
  65. //! remove all calls from queue
  66. proto native void Clear();
  67. };
  68. /**
  69. \brief ScriptInvoker Class provide list of callbacks
  70. \n usage:
  71. @code
  72. class Player
  73. {
  74. ref ScriptInvoker m_DeathInvoker = new ScriptInvoker();
  75. void OnKilled()
  76. {
  77. m_DeathInvoker.Invoke(this);
  78. }
  79. }
  80. void LogPlayerDeath(p)
  81. {
  82. Print("RIP " + p);
  83. }
  84. class Game
  85. {
  86. void RemovePlayer(Player p)
  87. {
  88. }
  89. void GameOver()
  90. {
  91. }
  92. }
  93. void OnPlayerSpaned(Player p)
  94. {
  95. Game game = GetGame();
  96. p.m_DeathInvoker.Insert(LogPlayerDeath);
  97. p.m_DeathInvoker.Insert(game.RemovePlayer);
  98. p.m_DeathInvoker.Insert(game.GameOver);
  99. }
  100. @endcode
  101. */
  102. class ScriptInvoker
  103. {
  104. //! invoke call on all inserted methods with given arguments
  105. proto void Invoke(void param1 = NULL, void param2 = NULL, void param3 = NULL, void param4 = NULL, void param5 = NULL, void param6 = NULL, void param7 = NULL, void param8 = NULL, void param9 = NULL);
  106. //! insert method to list
  107. proto bool Insert(func fn, int flags = EScriptInvokerInsertFlags.IMMEDIATE);
  108. //! remove specific call from list
  109. proto bool Remove(func fn, int flags = EScriptInvokerRemoveFlags.ALL);
  110. //! count how many times this fn is actively present in the Invoker
  111. proto int Count(func fn);
  112. //! remove all calls from list
  113. proto native void Clear();
  114. };
  115. enum EScriptInvokerInsertFlags
  116. {
  117. NONE,
  118. /**
  119. \brief It gets added in immediately, which means that when called while an invoker is running, it will call this newly added call in the same run
  120. \note Default flag, as that is the original behaviour, although it might cause endless Insert chain now... (still better than undefined behaviour)
  121. \note In case of "Possible endless Insert detected" VME, either create an exit, remove the IMMEDIATE flag or make the insert UNIQUE
  122. \note The Endless Insert is detected by seeing if "amount of calls > initial size + 128"
  123. */
  124. IMMEDIATE,
  125. /**
  126. \brief Only one call to this instance+method is ever expected
  127. \note Will throw a VME when a second one is attempted to be added
  128. \note If it was already added without the flag, it will also throw a VME and keep the first of all previously inserted
  129. */
  130. UNIQUE,
  131. }
  132. enum EScriptInvokerRemoveFlags
  133. {
  134. NONE,
  135. /**
  136. \brief Default flag
  137. \note Don't use this if you want it to remove only the last insert instead of all of them
  138. */
  139. ALL,
  140. }
  141. /**
  142. \brief Designed to hold 1 valid call
  143. */
  144. class ScriptCaller
  145. {
  146. //! ScriptCaller is meant to be created through Create
  147. private void ScriptCaller();
  148. //! Creates a ScriptCaller
  149. static proto ScriptCaller Create(func fn);
  150. //! Replaces the current registered func with the new one, throws errors if unsuccessful
  151. proto void Init(func fn);
  152. //! Invoke call on the registered func, throws errors if unsuccessful
  153. proto void Invoke(void param1 = null, void param2 = null, void param3 = null, void param4 = null, void param5 = null, void param6 = null, void param7 = null, void param8 = null, void param9 = null);
  154. //! Checks if the ScriptCaller is valid
  155. proto bool IsValid();
  156. /**
  157. \brief Compares this script caller against another script caller
  158. \note May return true even if either one is invalid
  159. @code
  160. class SomeClass
  161. {
  162. void SomeMethod()
  163. {
  164. }
  165. }
  166. void Test()
  167. {
  168. SomeClass instanceA = new SomeClass();
  169. SomeClass instanceB = new SomeClass();
  170. ScriptCaller callerA;
  171. ScriptCaller callerB;
  172. //! Two methods that are to the same instance
  173. callerA = ScriptCaller.Create(instanceA.SomeMethod);
  174. callerB = ScriptCaller.Create(instanceA.SomeMethod);
  175. Print(callerA.Equals(callerB)); //! "1"
  176. Print(callerA == callerB); //! "0"
  177. Print(callerA); //! "ScriptCaller callerA = ScriptCaller<87bc2d40>"
  178. Print(callerB); //! "ScriptCaller callerB = ScriptCaller<87bc3600>"
  179. //! Two methods belonging to different instances
  180. callerA = ScriptCaller.Create(instanceA.SomeMethod);
  181. callerB = ScriptCaller.Create(instanceB.SomeMethod);
  182. Print(callerA.Equals(callerB)); //! "0"
  183. Print(callerA == callerB); //! "0"
  184. Print(callerA); //! "ScriptCaller callerA = ScriptCaller<87bc3c40>"
  185. Print(callerB); //! "ScriptCaller callerB = ScriptCaller<87bc2d40>"
  186. }
  187. @endcode
  188. */
  189. proto bool Equals(notnull ScriptCaller other);
  190. };