Skip to content

Instantly share code, notes, and snippets.

@gamedevsam
Last active December 16, 2015 03:29
Show Gist options
  • Save gamedevsam/5370635 to your computer and use it in GitHub Desktop.
Save gamedevsam/5370635 to your computer and use it in GitHub Desktop.
A super simple string based event system.
package ;
import flixel.FlxG;
import flixel.util.FlxPool;
import haxe.ds.ObjectMap;
class Events
{
public static function addHandler(object:Dynamic, event:String, handler:Dynamic -> Void, permanent:Bool = false)
{
// events are not case sensitive
event = event.toLowerCase();
// recycle event handler object
var eventHandler:EventHandler = eventHandlerPool.get();
eventHandler.init(object, event, handler, permanent);
// store handlers on string map, for fast dispatch
var handlers:EventHandlerArray = eventMap.get(event);
if (handlers == null)
{
handlers = eventHandlerArrayPool.get();
eventMap.set(event, handlers);
}
handlers.array.push(eventHandler);
// store handlers on object map as well, for fast removal of events from an object
if (object != null)
{
handlers = objectMap.get(object);
if (handlers == null)
{
handlers = eventHandlerArrayPool.get();
objectMap.set(object, handlers);
}
handlers.array.push(eventHandler);
}
}
public static function removeHandler(object:Dynamic, event:String, handler:Dynamic -> Void)
{
// events are not case sensitive
event = event.toLowerCase();
var handlers:EventHandlerArray = eventMap.get(event);
if (handlers != null && handlers.array.length > 0)
{
var i = handlers.array.length - 1;
while (i >= 0)
{
var eventHandler:EventHandler = handlers.array[i--];
if (eventHandler.handler == handler)
{
if (object != null)
{
var objHandlers:EventHandlerArray = objectMap.get(object);
if (objHandlers != null)
{
objHandlers.array.remove(eventHandler);
if (objHandlers.array.length == 0)
{
eventHandlerArrayPool.putUnsafe(objHandlers);
objectMap.remove(object);
}
}
}
handlers.array.remove(eventHandler);
eventHandlerPool.putUnsafe(eventHandler);
break;
}
}
if (handlers.array.length == 0)
{
eventHandlerArrayPool.putUnsafe(handlers);
eventMap.remove(event);
}
}
}
// convenience function to remove all events registered to an object
public static function removeObject(object:Dynamic)
{
var handlers:EventHandlerArray = objectMap.get(object);
if (handlers != null)
{
for (eventHandler in handlers.array)
{
removeHandler(null, eventHandler.event, eventHandler.handler);
}
eventHandlerArrayPool.putUnsafe(handlers);
objectMap.remove(object);
}
}
public static function dispatch(event:String, data:Dynamic = null #if(!FLX_NO_DEBUG), ?pos:haxe.PosInfos #end)
{
// events are not case sensitive
event = event.toLowerCase();
#if !FLX_NO_DEBUG
var msg = "Dispatch event: '" + event + "' from ["+pos.fileName+","+pos.lineNumber+"]";
FlxG.log.add(msg);
//trace(msg);
#end
var handlers:EventHandlerArray = eventMap.get(event);
if (handlers != null)
{
for (eventHandler in handlers.array)
{
eventHandler.handler(data);
}
}
else
{
var msg = "Could not find any handlers for the event '" + event + "'. Make sure you didn't mispell the event name";
FlxG.log.warn(msg);
//trace(msg);
}
}
// simple function to ensure that all non-permanent events have been cleaned up
public static function cleanup()
{
#if !FLX_NO_DEBUG
// Verify if there aren't any non-permanent events left
for (handlers in eventMap)
{
for (handler in handlers.array)
{
if (!handler.permanent)
{
var msg = "Handler for event '" + handler.event + "' not cleaned up in " + handler.object + "!";
FlxG.log.error(msg);
//trace(msg);
}
}
}
for (handlers in objectMap)
{
for (handler in handlers.array)
{
if (!handler.permanent)
{
var msg = "Handler for event '" + handler.event + "' not cleaned up in " + handler.object + "!";
FlxG.log.error(msg);
//trace(msg);
}
}
}
#end
}
private static var eventMap :Map<String, EventHandlerArray> = new Map<String, EventHandlerArray>();
private static var objectMap :ObjectMap<Dynamic, EventHandlerArray> = new ObjectMap<Dynamic, EventHandlerArray>();
private static var eventHandlerPool :FlxPool<EventHandler> = new FlxPool<EventHandler>();
private static var eventHandlerArrayPool:FlxPool<EventHandlerArray> = new FlxPool<EventHandlerArray>();
}
private class EventHandler
{
public var event:String;
public var object:Dynamic;
public var handler:Dynamic -> Void;
public var permanent:Bool;
public function new() {}
public function init(o:Dynamic, e:String, h:Dynamic -> Void, p:Bool)
{
event = e;
object = o;
handler = h;
permanent = p;
}
public function destroy()
{
event = null;
object = null;
handler = null;
}
}
private class EventHandlerArray
{
public var array:Array<EventHandler>;
public function new() { array = new Array<EventHandler>(); }
public function destroy()
{
if (array.length > 0)
{
#if(flash || cpp)
untyped array.length = 0;
#else
array = [];
#end
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment