A pixel art painter geared specifically at NES pixel art. Includes export for .chr binary file as well as palette and namespace data.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

204 行
6.6KB

  1. /**
  2. * Event caller/listener system. Intended to be extended by classes which require
  3. * an event callback system.
  4. */
  5. export class EventCaller{
  6. constructor(){
  7. this.__listeners = {};
  8. }
  9. /**
  10. * @type {number}
  11. */
  12. get totalListeners(){
  13. var count = 0;
  14. for (key in Object.keys(this.__listeners)){
  15. count += this.__listeners[key].length
  16. }
  17. return count;
  18. }
  19. /**
  20. * @type {Array[string]}
  21. */
  22. get watchedEvents(){
  23. return Object.keys(this.__listeners);
  24. }
  25. /**
  26. * Returns true if the given callback is listening for the given event, and false otherwise.
  27. * @param {string} eventName - The name of the event to check.
  28. * @param {Function} callback - The function/method to check for
  29. * @param {Object} [owner=null] - The object to use as "this" when calling the callback function.
  30. * @returns {bool}
  31. */
  32. is_listening(eventName, callback, owner=null){
  33. if (typeof(eventName) !== 'string')
  34. throw new TypeError("Expected eventName to be string.");
  35. if (eventName.length <= 0)
  36. throw new ValueError("Argument eventName cannot be a zero-length string.");
  37. if (this.__listeners.hasOwnProperty(eventName)){
  38. if (typeof(callback) !== 'function')
  39. throw new TypeError("Expected callback argument to be a function or class method.");
  40. for (var i=0; i < this.__listeners[eventName].length; i++){
  41. if (this.__listeners[eventName][i][0] === callback &&
  42. this.__listeners[eventName][i][1] === owner){
  43. return true;
  44. }
  45. }
  46. }
  47. return false;
  48. }
  49. /**
  50. * Sets the given callback to listen for the given event.
  51. * If [once] is true, the callback will be cleared from the listeners list after the named
  52. * event has been emitted.
  53. * @param {string} eventName - The name of the event to listen for.
  54. * @param {Function} callback - The function to call when the given event is emitted.
  55. * @param {Object} [owner=null] - The owner to use when calling the callback.
  56. * @param {bool} [once=false] - If true, the callback will be cleared after the next emit of the given event.
  57. * @returns {this}
  58. */
  59. listen(eventName, callback, owner=null, once=false){
  60. if (typeof(callback) !== 'function')
  61. throw new TypeError("Expected callback argument to be a function or class method.");
  62. try{
  63. if (!this.is_listening(eventName, callback, owner)){
  64. if (!this.__listeners.hasOwnProperty(eventName)){
  65. this.__listeners[eventName] = [];
  66. }
  67. this.__listeners[eventName].push([callback, owner, once]);
  68. }
  69. } catch (e) {
  70. throw e;
  71. }
  72. return this;
  73. }
  74. /**
  75. * Removes the given callback from the given event.
  76. * NOTE: If the listener callback was set with it's owner, that owner must be included
  77. * to remove the listener callback successfully.
  78. * @param {string} eventName - The name of the event to remove from.
  79. * @param {Function} callback - The function/method to remove.
  80. * @param {Object} [owner=null] - The owner of the callback.
  81. * @returns {this}
  82. */
  83. unlisten(eventName, callback, owner=null){
  84. if (typeof(eventName) !== 'string')
  85. throw new TypeError("Expected eventName to be string.");
  86. if (eventName.length <= 0)
  87. throw new ValueError("Argument eventName cannot be a zero-length string.");
  88. if (this.__listeners.hasOwnProperty(eventName)){
  89. if (typeof(callback) !== 'function')
  90. throw new TypeError("Expected callback argument to be a function or class method.");
  91. for (var i=0; i < this.__listeners[eventName].length; i++){
  92. if (this.__listeners[eventName][i][0] === callback &&
  93. this.__listeners[eventName][i][1] === owner){
  94. this.__listeners[eventName].splice(i, 1);
  95. if (this.__listeners[eventName].length <= 0)
  96. delete this.__listeners[eventName];
  97. break;
  98. }
  99. }
  100. }
  101. return this;
  102. }
  103. /**
  104. * Removes all listeners from the given event.
  105. * @param {string} eventName - The name of the event to clear listeners from.
  106. * @returns {this}
  107. */
  108. unlisten_event(eventName){
  109. if (typeof(eventName) !== 'string')
  110. throw new TypeError("Expected eventName to be string.");
  111. if (eventName.length <= 0)
  112. throw new ValueError("Argument eventName cannot be a zero-length string.");
  113. if (this.__listener.hasOwnProperty(eventName))
  114. delete this.__listener[eventName];
  115. return this;
  116. }
  117. /**
  118. * Removes all listeners.
  119. * @returns {this}
  120. */
  121. unlisten_all(){
  122. // NOTE: Perhaps it's better to loop through and delete each property? This should do for now though.
  123. this.__listeners = {};
  124. return this;
  125. }
  126. /**
  127. * Returns the count of listeners attached to the given event.
  128. * @param {string} eventName - The name of the event to get the count of.
  129. * @returns {number}
  130. */
  131. event_listener_count(eventName){
  132. if (typeof(eventName) !== 'string')
  133. throw new TypeError("Expected eventName to be string.");
  134. if (eventName.length <= 0)
  135. throw new ValueError("Argument eventName cannot be a zero-length string.");
  136. if (this.__listener.hasOwnProperty(eventName)){
  137. return this.__listener[eventName].length;
  138. }
  139. return 0;
  140. }
  141. /**
  142. * Emits the given event, calling all listener callbacks attached to the event and passing each
  143. * the arguments (if any) given.
  144. * NOTE: All listeners of the given event designated to only listen once will be removed after
  145. * this call.
  146. * @param {string} eventName - The name of the event to emit.
  147. * @param {...*} args - The arguments to pass to every listener of this event.
  148. * @returns {this}
  149. */
  150. emit(){
  151. var args = Array.from(arguments);
  152. if (args.length <= 0)
  153. throw new Error("Missing required eventName argument.");
  154. var eventName = args[0];
  155. args = args.slice(1);
  156. if (typeof(eventName) !== 'string')
  157. throw new TypeError("Expected eventName to be string.");
  158. if (eventName.length <= 0)
  159. throw new ValueError("Argument eventName cannot be a zero-length string.");
  160. var once = [];
  161. if (this.__listeners.hasOwnProperty(eventName)){
  162. for (var i=0; i < this.__listeners[eventName].length; i++){
  163. var cb = this.__listeners[eventName][i][0];
  164. var own = this.__listeners[eventName][i][1];
  165. if (this.__listeners[eventName][i][2] === true)
  166. once.push([cb, own]);
  167. cb.apply(own, args);
  168. }
  169. if (once.length > 0){
  170. for (var i=0; i < once.length; i++){
  171. this.unlisten(eventName, once[i][0], once[i][1]);
  172. }
  173. }
  174. }
  175. return this;
  176. }
  177. }
  178. const GlobalEvent = new EventCaller();
  179. export default GlobalEvent;