ScriptTarget.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. #ifndef SCRIPTTARGET_H_
  2. #define SCRIPTTARGET_H_
  3. #include "Script.h"
  4. namespace gameplay
  5. {
  6. /**
  7. * Macro to indidate the start of script event definitions for a class.
  8. *
  9. * This macro should be used at the top of a class declaration. The class
  10. * should extend ScriptTarget and the lines immediately following this
  11. * macro should be one or more GP_SCRIPT_EVENT macros, followed by
  12. * exactly one GP_SCRIPT_EVENTS_END macro.
  13. *
  14. * @script{ignore}
  15. */
  16. #define GP_SCRIPT_EVENTS_START() \
  17. public: \
  18. class ScriptEvents { \
  19. public: \
  20. static ScriptEvents* getInstance() \
  21. { \
  22. static ScriptEvents instance; \
  23. return &instance; \
  24. } \
  25. static ScriptTarget::EventRegistry* getRegistry() \
  26. { \
  27. static ScriptTarget::EventRegistry registry; \
  28. return &registry; \
  29. }
  30. /**
  31. * Macro to define a single supported script event for a class.
  32. *
  33. * This macro should follow exactly one prior GP_SCRIPT_EVENTS_START macro
  34. * and zero or more other GP_SCRIPT_EVENT macros.
  35. *
  36. * @param eventName The name of the script event.
  37. * @param eventArgs A string of arguments to be passed to the script event, using
  38. * the format specified in ScriptController::executeFunction.
  39. *
  40. * @script{ignore}
  41. */
  42. #define GP_SCRIPT_EVENT(eventName, eventArgs) \
  43. struct SCRIPT_EVENT_ ## eventName \
  44. { \
  45. SCRIPT_EVENT_ ## eventName() \
  46. { \
  47. _event = ScriptEvents::getRegistry()->addEvent(#eventName, eventArgs); \
  48. } \
  49. const ScriptTarget::Event* getEvent() \
  50. { \
  51. return _event; \
  52. } \
  53. private: \
  54. const ScriptTarget::Event* _event; \
  55. }; \
  56. SCRIPT_EVENT_ ## eventName eventName;
  57. /**
  58. * Macro to indiate the end of a series of script event defintions.
  59. *
  60. * @script{ignore}
  61. */
  62. #define GP_SCRIPT_EVENTS_END() \
  63. private: \
  64. ScriptEvents() { } \
  65. };
  66. /**
  67. * Macro used to retrieve a script event object the given class name.
  68. *
  69. * @param eventClass The C++ class that contains the specified script event.
  70. * @param eventName The name of the registered script event to retrieve.
  71. *
  72. * @script{ignore}
  73. */
  74. #define GP_GET_SCRIPT_EVENT(eventClass, eventName) \
  75. eventClass::ScriptEvents::getInstance()->eventName.getEvent()
  76. /**
  77. * Registers the defined script events for a ScriptTarget.
  78. *
  79. * This macro should be called at the beginning of all constructors of a
  80. * ScriptTarget child class that contains one or more script event
  81. * declarations (via the GP_SCRIPT_EVENT macro).
  82. *
  83. * @script{ignore}
  84. */
  85. #define GP_REGISTER_SCRIPT_EVENTS() \
  86. ScriptTarget::registerEvents(ScriptEvents::getInstance()->getRegistry())
  87. /**
  88. * Defines an interface for supporting script callbacks.
  89. *
  90. * Classes that extend ScriptTarget can expose script events using the GP_SCRIPT_EVENT macros.
  91. * Custom events should be registered using these macros at the top of the class definition.
  92. * Events can be fired by calling the ScriptTarget::fireScriptEvent method, passing the
  93. * registered ScriptTarget::Event object and any required parameters.
  94. *
  95. * In addition to script events that are explicitly defined by a custom ScriptTarget class,
  96. * all ScriptTarget scripts implicitly support an "attached" event. This event is called
  97. * immediately after such a script is attached to a ScriptTarget and it takes a single
  98. * parameter: the ScriptTarget object.
  99. */
  100. class ScriptTarget
  101. {
  102. friend class Game;
  103. public:
  104. /**
  105. * Defines a single script event.
  106. */
  107. class Event
  108. {
  109. friend class ScriptTarget;
  110. public:
  111. /**
  112. * Returns the name of this event.
  113. *
  114. * @return The event name.
  115. */
  116. const char* getName() const;
  117. /**
  118. * Returns the argument string for this event.
  119. *
  120. * @return The argument string.
  121. */
  122. const char* getArgs() const;
  123. private:
  124. /**
  125. * The event name.
  126. */
  127. std::string name;
  128. /**
  129. * The event arguments.
  130. *
  131. * @see ScriptController::executeFunction
  132. */
  133. std::string args;
  134. };
  135. /**
  136. * Script event registry that defines the supported script events
  137. * for a ScriptTarget.
  138. *
  139. * This class should generally only be used via the GP_REGISTER_SCRIPT_EVENTS macro.
  140. */
  141. class EventRegistry
  142. {
  143. friend class ScriptTarget;
  144. public:
  145. /**
  146. * Creates an empty event registry.
  147. */
  148. EventRegistry();
  149. /**
  150. * Destructor.
  151. */
  152. ~EventRegistry();
  153. /**
  154. * Adds a registered event to the registry.
  155. *
  156. * @param name The name of the script event.
  157. * @param args The argument string for the event.
  158. *
  159. * @return The added event.
  160. *
  161. * @see ScriptController::executeFunction
  162. */
  163. const Event* addEvent(const char* name, const char* args = NULL);
  164. /**
  165. * Returns the number of registered script events.
  166. *
  167. * @return The number of script events registered.
  168. */
  169. unsigned int getEventCount() const;
  170. /**
  171. * Returns the event with the given index.
  172. *
  173. * @param index The index of the event to retrieve.
  174. *
  175. * @return The event for the given index.
  176. */
  177. const Event* getEvent(unsigned int index) const;
  178. /**
  179. * Returns the event that matches the given name.
  180. *
  181. * @param name The name of the event to search for.
  182. *
  183. * @return The matching event, or NULL if no such event exists.
  184. */
  185. const Event* getEvent(const char* name) const;
  186. private:
  187. std::vector<Event*> _events;
  188. };
  189. /**
  190. * Implemented by child classes to return the type name identifier for
  191. * the class that extends ScriptTarget.
  192. *
  193. * @return A string describing the type name of the ScriptTarget child
  194. * class, as it is defined in the lua bindings (i.e. "Node").
  195. */
  196. virtual const char* getTypeName() const = 0;
  197. /**
  198. * Attaches a script to this object.
  199. *
  200. * Scripts attached to a ScriptTarget are loaded using the PROTECTED scope,
  201. * which loads scripts into their own protected script environment, allowing
  202. * variables with the same name to be used without colliding with other scripts.
  203. *
  204. * @param path Path to the script.
  205. *
  206. * @return A pointer to the successfully loaded script, or NULL if unsuccessful.
  207. */
  208. Script* addScript(const char* path);
  209. /**
  210. * Removes a previously attached script from this object.
  211. *
  212. * @param path The same path that was used to load the script being removed.
  213. *
  214. * @return True if a script is successfully removed, false otherwise.
  215. */
  216. bool removeScript(const char* path);
  217. /**
  218. * Adds the given global script function as a callback for the given event.
  219. *
  220. * Individual script callback events registered via this method are expected
  221. * to be global script functions. Registering individual callbacks in this
  222. * manner is generally slower than registering a single script to handle script
  223. * events for an object.
  224. *
  225. * @param event The event to add the callback for.
  226. * @param function The name of the script function to call when the event is fired; can either be
  227. * just the name of a function (if the function's script file has already been loaded), or can be
  228. * a URL of the form scriptFile.lua#functionName.
  229. */
  230. void addScriptCallback(const Event* event, const char* function);
  231. /**
  232. * Removes the given script function as a callback for the given event.
  233. *
  234. * @param event The event to remove the callback for.
  235. * @param function The name of the script function.
  236. */
  237. void removeScriptCallback(const Event* event, const char* function);
  238. /**
  239. * Removes all scripts and callbacks from this object.
  240. */
  241. void clearScripts();
  242. /**
  243. * Determines if there is a script installed that is listening for the given script
  244. * event (i.e. has a function callback defined for the given event).
  245. *
  246. * @param eventName The script event to check.
  247. *
  248. * @return True if there is a listener for the specified event, false otherwise.
  249. */
  250. bool hasScriptListener(const char* eventName) const;
  251. /**
  252. * Determines if there is a script installed that is listening for the given script
  253. * event (i.e. has a function callback defined for the given event).
  254. *
  255. * @param event The script event to check.
  256. *
  257. * @return True if there is a listener for the specified event, false otherwise.
  258. */
  259. bool hasScriptListener(const Event* event) const;
  260. /**
  261. * Returns the event object for the given event name, if it exists.
  262. *
  263. * @param eventName Name of the event.
  264. *
  265. * @return The event object for the given name, or NULL if no such event exists.
  266. */
  267. const Event* getScriptEvent(const char* eventName) const;
  268. /**
  269. * Fires the specified script event, passing the specified arguments.
  270. *
  271. * The only supported return types are void and boolean. When a boolean
  272. * return type is used and there are multiple scripts registered for the
  273. * given script event, event delegation will stop at the first script
  274. * that returns a value of true.
  275. *
  276. * @param event The script event to fire, which was returned from EventRegistry::addEvent.
  277. * @param ... Optional list of arguments to pass to the script event (should match the
  278. * script event argument definition).
  279. *
  280. * @script{ignore}
  281. */
  282. template<typename T> T fireScriptEvent(const Event* event, ...);
  283. protected:
  284. /**
  285. * Stores an EventRegistry entry for a ScriptTarget.
  286. */
  287. struct RegistryEntry
  288. {
  289. EventRegistry* registry;
  290. RegistryEntry* next;
  291. RegistryEntry* prev;
  292. RegistryEntry(EventRegistry* registry) : registry(registry), next(NULL), prev(NULL) { }
  293. };
  294. /**
  295. * Stores a Script that is registered for a ScriptTarget.
  296. */
  297. struct ScriptEntry
  298. {
  299. Script* script;
  300. ScriptEntry* next;
  301. ScriptEntry* prev;
  302. ScriptEntry(Script* script) : script(script), next(NULL), prev(NULL) { }
  303. };
  304. /**
  305. * Stores a single registered script callback function.
  306. */
  307. struct CallbackFunction
  308. {
  309. // The script the callback belongs to (or NULL if the callback is a global function)
  310. Script* script;
  311. // The function within the script to call
  312. std::string function;
  313. CallbackFunction(Script* script, const char* function) : script(script), function(function) { }
  314. };
  315. /**
  316. * Constructor.
  317. */
  318. ScriptTarget();
  319. /**
  320. * Destructor.
  321. */
  322. virtual ~ScriptTarget();
  323. /**
  324. * Removes the specified script.
  325. */
  326. void removeScript(ScriptEntry* se);
  327. /**
  328. * Registers a set of supported script events and event arguments for this ScriptTarget.
  329. *
  330. * The passed in EventRegistry object should contain a list of all script events to
  331. * be supported by this ScriptTarget, along with their parameter definitions. This
  332. * registry object will be held onto for the lifetime of the ScriptTarget and it is
  333. * recommended that it be shared among all ScriptTargets of the same class/type.
  334. *
  335. * This should normally be set using the GP_REGISTER_SCRIPT_EVENTS macro in the
  336. * constructor of the child class.
  337. *
  338. * @param registry The EventRegistry containing the list of supported script events.
  339. */
  340. void registerEvents(EventRegistry* registry);
  341. /** Holds the event registries for this script target. */
  342. RegistryEntry* _scriptRegistries;
  343. /** Holds the list of scripts referenced by this ScriptTarget. */
  344. ScriptEntry* _scripts;
  345. /** Holds the list of callback functions registered for this ScriptTarget. */
  346. std::map<const Event*, std::vector<CallbackFunction> >* _scriptCallbacks;
  347. };
  348. template<typename T> T ScriptTarget::fireScriptEvent(const Event* evt, ...)
  349. {
  350. GP_ERROR("Unsupported return type for template function ScriptTarget::fireScriptEvent.");
  351. }
  352. /** Template specialization. */
  353. template<> void ScriptTarget::fireScriptEvent<void>(const Event* event, ...);
  354. /** Template specialization. */
  355. template<> bool ScriptTarget::fireScriptEvent<bool>(const Event* event, ...);
  356. }
  357. #endif