Skip to content

Commit c76c574

Browse files
committed
Added in the new EventDispatch and Event system.
1 parent 1fe6731 commit c76c574

4 files changed

Lines changed: 291 additions & 1 deletion

File tree

v3/src/boot/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ module.exports = {
33
// Doing this makes it available under Phaser.Game
44
Game: require('./Game'),
55

6+
Event: require('../events/Event'),
7+
EventDispatcher: require('../events/EventDispatcher'),
8+
69
Loader: {
710
ImageFile: require('../loader/filetypes/ImageFile')
811
}

v3/src/events/Event.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
var Event = function (type, target)
2+
{
3+
this.dispatcher;
4+
5+
this.type = type;
6+
7+
this.target = target;
8+
9+
this._propagate = true;
10+
};
11+
12+
Event.prototype.constructor = Event;
13+
14+
Event.prototype = {
15+
16+
reset: function (dispatcher)
17+
{
18+
this.dispatcher = dispatcher;
19+
20+
this._propagate = true;
21+
},
22+
23+
stopPropagation: function ()
24+
{
25+
this._propagate = false;
26+
}
27+
28+
};
29+
30+
module.exports = Event;

v3/src/events/EventDispatcher.js

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
var EventDispatcher = function ()
2+
{
3+
this.listeners = {};
4+
5+
this._state = EventDispatcher.STATE_PENDING;
6+
};
7+
8+
EventDispatcher.STATE_PENDING = 0;
9+
EventDispatcher.STATE_DISPATCHING = 1;
10+
EventDispatcher.STATE_REMOVING_ALL = 2;
11+
EventDispatcher.STATE_DESTROYED = 3;
12+
13+
EventDispatcher.prototype.constructor = EventDispatcher;
14+
15+
EventDispatcher.prototype = {
16+
17+
// Private
18+
add: function (type, listener, priority, isOnce)
19+
{
20+
if (this.listeners === undefined)
21+
{
22+
// Has the EventDispatcher been destroyed?
23+
return;
24+
}
25+
26+
console.log('Add listener', type, listener);
27+
28+
if (!this.listeners[type])
29+
{
30+
this.listeners[type] = [];
31+
}
32+
33+
var listeners = this.listeners[type];
34+
35+
if (this.has(type, listener))
36+
{
37+
this.update(type, listener, priority, isOnce);
38+
}
39+
else
40+
{
41+
listeners.push({ listener: listener, priority: priority, isOnce: isOnce });
42+
}
43+
44+
listeners.sort(this.sortHandler);
45+
},
46+
47+
sortHandler: function (listenerA, listenerB)
48+
{
49+
if (listenerA.priority < listenerB.priority)
50+
{
51+
return -1;
52+
}
53+
else if (listenerA.priority > listenerB.priority)
54+
{
55+
return 1;
56+
}
57+
else
58+
{
59+
return 0;
60+
}
61+
},
62+
63+
update: function (type, listener, priority, isOnce)
64+
{
65+
var listeners = this.listeners[type];
66+
67+
for (var i = 0; i < listeners.length; i++)
68+
{
69+
if (listeners[i].listener === listener)
70+
{
71+
// They're trying to add the same listener again, so just update the priority + once
72+
listeners[i].priority = priority;
73+
listeners[i].isOnce = isOnce;
74+
}
75+
}
76+
77+
},
78+
79+
on: function (type, listener, priority)
80+
{
81+
if (priority === undefined) { priority = 0; }
82+
83+
this.add(type, listener, priority, false);
84+
85+
return this;
86+
},
87+
88+
once: function (type, listener, priority)
89+
{
90+
if (priority === undefined) { priority = 0; }
91+
92+
this.add(type, listener, priority, true);
93+
94+
return this;
95+
},
96+
97+
has: function (type, listener)
98+
{
99+
if (!this.listeners || !this.listeners[type])
100+
{
101+
return false;
102+
}
103+
104+
var listeners = this.listeners[type];
105+
106+
for (var i = 0; i < listeners.length; i++)
107+
{
108+
if (listeners[i].listener === listener)
109+
{
110+
return true;
111+
}
112+
}
113+
114+
return false;
115+
},
116+
117+
// Removes an event listener.
118+
// If there is no matching listener registered with the EventDispatcher, a call to this method has no effect.
119+
off: function (type, listener)
120+
{
121+
if (!this.listeners || !this.listeners[type])
122+
{
123+
return this;
124+
}
125+
126+
var listeners = this.listeners[type];
127+
128+
for (var i = 0; i < listeners.length; i++)
129+
{
130+
if (listeners[i].listener === listener)
131+
{
132+
console.log('Remove listener', type, listener);
133+
134+
listeners.splice(i, 1);
135+
break;
136+
}
137+
}
138+
139+
return this;
140+
},
141+
142+
dispatch: function (event)
143+
{
144+
// Add in a dispatch lock, to stop the dispatcher from being invoked during an event callback
145+
146+
if (this._state !== EventDispatcher.STATE_PENDING || !this.listeners[event.type])
147+
{
148+
return false;
149+
}
150+
151+
this._state = EventDispatcher.STATE_DISPATCHING;
152+
153+
var listeners = this.listeners[event.type];
154+
155+
event.reset(this);
156+
157+
var toRemove = [];
158+
var entries = listeners.slice();
159+
160+
console.log('Dispatching', entries.length, 'listeners');
161+
162+
for (var i = 0; i < entries.length; i++)
163+
{
164+
// Add Custom Events
165+
entries[i].listener.call(this, event);
166+
167+
// Has the callback done something disastrous? Like called removeAll, or nuked the dispatcher?
168+
if (this._state !== EventDispatcher.STATE_DISPATCHING)
169+
{
170+
// Yup! Let's get out of here ...
171+
break;
172+
}
173+
174+
if (entries[i].isOnce)
175+
{
176+
toRemove.push(entries[i]);
177+
}
178+
179+
// Has the event been halted?
180+
if (!event._propagate)
181+
{
182+
// Break out, a listener has called Event.stopPropagation
183+
break;
184+
}
185+
}
186+
187+
if (this._state === EventDispatcher.STATE_REMOVING_ALL)
188+
{
189+
this.removeAll();
190+
}
191+
else if (this._state === EventDispatcher.STATE_DESTROYED)
192+
{
193+
this.destroy();
194+
}
195+
else
196+
{
197+
// Anything in the toRemove list?
198+
199+
console.log('Cleaning out', toRemove.length, 'listeners');
200+
201+
for (i = 0; i < toRemove.length; i++)
202+
{
203+
this.off(toRemove[i].type, toRemove[i].listener);
204+
}
205+
206+
this._state = EventDispatcher.STATE_PENDING;
207+
}
208+
209+
return true;
210+
},
211+
212+
// Removes all listeners, but retains the event type entries
213+
removeAll: function ()
214+
{
215+
if (this._state === EventDispatcher.STATE_DISPATCHING)
216+
{
217+
this._state = EventDispatcher.STATE_REMOVING_ALL;
218+
219+
return;
220+
}
221+
222+
for (var eventType in this.listeners)
223+
{
224+
this.listeners[eventType].length = 0;
225+
}
226+
227+
return this;
228+
},
229+
230+
destroy: function ()
231+
{
232+
if (this._state === EventDispatcher.STATE_DISPATCHING)
233+
{
234+
this._state = EventDispatcher.STATE_DESTROYED;
235+
236+
return;
237+
}
238+
239+
for (var eventType in this.listeners)
240+
{
241+
this.listeners[eventType].length = 0;
242+
243+
delete this.listeners[eventType];
244+
}
245+
246+
this.listeners = undefined;
247+
}
248+
249+
};
250+
251+
module.exports = EventDispatcher;

v3/src/state/Systems.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
55
*/
66

7+
var EventDispatcher = require('../events/EventDispatcher');
78
var GameObjectFactory = require('./systems/GameObjectFactory');
89
var GameObjectCreator = require('./systems/GameObjectCreator');
910
var Loader = require('./systems/Loader');
@@ -16,6 +17,8 @@ var Systems = function (state, config)
1617

1718
this.config = config;
1819

20+
this.events;
21+
1922
// State specific managers (Factory, Tweens, Loader, Physics, etc)
2023
this.add;
2124
this.make;
@@ -43,8 +46,10 @@ Systems.prototype = {
4346
{
4447
console.log('State.Systems.init');
4548

46-
// State specific managers (Factory, Tweens, Loader, Physics, etc)
49+
// All of the systems can use the State level EventDispatcher
50+
this.events = new EventDispatcher();
4751

52+
// State specific managers (Factory, Tweens, Loader, Physics, etc)
4853
// All these to be set by a State Config package
4954

5055
this.add = new GameObjectFactory(this.state);
@@ -70,6 +75,7 @@ Systems.prototype = {
7075

7176
// Defaults
7277

78+
this.state.events = this.events;
7379
this.state.add = this.add;
7480
this.state.load = this.load;
7581
// this.state.children = this.children;

0 commit comments

Comments
 (0)