I have been writing as3 for many years, and recently I feel that the event mechanism of U3D is not as good as as3. The first version is implemented based on C # delegation. Not much nonsense.
The eventdispatcher code is as follows:
Using unityengine;
Using system. collections;
Using system;
Using system. Collections. Generic;
/**
* The eventdispatcher class is the base class of all classes for event scheduling.
* @ Author
**/
Public abstract class eventdispatcher: monobehaviour
{
// Define the delegate
Public Delegate void eventdelegate (eventobject EVT );
Protected dictionary <string, list <eventdelegate> capturelisteners = NULL;
Protected dictionary <string, list <eventdelegate> bubblelisteners = NULL;
Protected eventdispatcher _ parent;
Public void addeventlistener (string types, eventdelegate listener, bool usecapture = false, int priority = 0, bool useweakreference = false)
{
Dictionary <string, list <eventdelegate> listeners = NULL;
If (listener = NULL)
{
Throw new argumentnullexception ("parameter listener must be non-null .");
}
If (usecapture)
{
If (capturelisteners = NULL) capturelisteners = new dictionary <string, list <eventdelegate> ();
Listeners = capturelisteners;
}
Else
{
If (bubblelisteners = NULL) bubblelisteners = new dictionary <string, list <eventdelegate> ();
Listeners = bubblelisteners;
}
List <eventdelegate> vector = NULL;
If (listeners. containskey (types ))
{
Vector = listeners [Types];
}
If (vector = NULL)
{
Vector = new list <eventdelegate> ();
Listeners. Add (types, vector );
}
If (vector. indexof (listener) <0)
{
Vector. Add (listener );
}
}
Public void removeeventlistener (string types, eventdelegate listener, bool usecapture = false)
{
If (listener = NULL)
{
Throw new argumentnullexception ("parameter listener must be non-null .");
}
Dictionary <string, list <eventdelegate> listeners = usecapture? Capturelisteners: bubblelisteners;
If (listeners! = NULL)
{
List <eventdelegate> vector = listeners [Types];
If (Vector! = NULL)
{
Int I = vector. indexof (listener );
If (I> = 0)
{
Int length = vector. count;
For (Int J = I + 1; j <length; j ++, I ++)
{
Vector [I] = vector [J];
}
Listeners. Remove (types );
Foreach (keyvaluepair <string, list <eventdelegate> O in listeners)
{
If (O. Key = NULL)
{
If (listeners = capturelisteners)
{
Capturelisteners = NULL;
}
Else
{
Bubblelisteners = NULL;
}
}
}
}
}
}
}
Public bool haseventlistener (string types)
{
Return (capturelisteners! = NULL & capturelisteners. containskey (types) | (bubblelisteners! = NULL & bubblelisteners. containskey (types ));
}
Public bool willtrigger (string types)
{
For (eventdispatcher _ OBJECT = This; _ object! = NULL; _ OBJECT = _ OBJECT. _ parent)
{
If (_ OBJECT. capturelisteners! = NULL & _ OBJECT. capturelisteners. containskey (types) | (_ OBJECT. bubblelisteners! = NULL & _ OBJECT. bubblelisteners. containskey (types )))
Return true;
}
Return false;
}
Public bool dispatchevent (eventobject EVT)
{
If (EVT = NULL)
{
Throw new argumentnullexception ("parameter eventobject must be non-null .");
}
Eventobject event3d = EVT;
If (event3d! = NULL)
{
Event3d. settarget = this;
}
List <eventdispatcher> branch = new list <eventdispatcher> ();
Int branchlength = 0;
Eventdispatcher _ object;
Int I, j = 0;
Int length;
List <eventdelegate> vector;
List <eventdelegate> functions;
For (_ OBJECT = This; _ object! = NULL; _ OBJECT = _ OBJECT. _ parent)
{
Branch. Add (_ OBJECT );
Branchlength ++;
}
For (I = branchlength-1; I> 0; I --)
{
_ OBJECT = branch [I];
If (event3d! = NULL)
{
Event3d. setcurrenttarget = _ object;
Event3d. seteventphase = eventphase. capturing_phase;
}
If (_ OBJECT. capturelisteners! = NULL)
{
Vector = _ OBJECT. capturelisteners [EVT. Types];
If (Vector! = NULL)
{
Length = vector. count;
Functions = new list <eventdelegate> ();
For (j = 0; j <length; j ++) functions [J] = vector [J];
For (j = 0; j <length; j ++) (functions [J] As eventdelegate) (EVT );
}
}
}
If (event3d! = NULL)
{
Event3d. seteventphase = eventphase. at_target;
}
For (I = 0; I <branchlength; I ++ ){
_ OBJECT = branch [I];
If (event3d! = NULL ){
Event3d. setcurrenttarget = _ object;
If (I> 0 ){
Event3d. seteventphase = eventphase. bubbling_phase;
}
}
If (_ OBJECT. bubblelisteners! = NULL ){
Vector = _ OBJECT. bubblelisteners [EVT. Types];
If (Vector! = NULL ){
Length = vector. count;
Functions = new list <eventdelegate> ();
For (j = 0; j <length; j ++) functions. Add (vector [J]);
For (j = 0; j <length; j ++) (functions [J] As eventdelegate) (EVT );
}
}
If (! Event3d. Bubbles) break;
}
Return true;
}
}
The eventphase code is as follows:
Using unityengine;
Using system. collections;
/**
* The eventphase class can provide values for the eventphase attribute of the event class.
* @ Author
**/
Public class eventphase
{
Public const int capturing_phase = 1;
Public const int at_target = 2;
Public const int bubbling_phase = 3;
}
The eventobject code is as follows:
Using unityengine;
Using system. collections;
Using system;
/**
* The eventobject class serves as the base class for creating event objects. when an event occurs, the event object is passed as a parameter to the event listener.
* @ Author
**/
Public class eventobject
{
Public const string activate = "Activate ";
Public const string added = "added ";
Public const string added_to_stage = "addedtostage ";
Public const string cancel = "cancel ";
Public const string change = "change ";
Public const string clear = "clear ";
Public const string close = "close ";
Public const string closing = "Closing ";
Public const string complete = "complete ";
Public const string connect = "Connect ";
Public const string open = "open ";
Private eventdispatcher _ target;
Private int _ eventphase;
Private eventdispatcher _ currenttarget;
Private bool _ bubbles;
Private bool _ cancelable;
Private string _ types;
Public eventobject (string types, bool bubbles = false, bool cancelable = false)
{
This. _ types = types;
This. _ bubbles = bubbles;
This. _ cancelable = cancelable;
}
Public eventdispatcher target
{
Get {return _ target ;}
}
Internal eventdispatcher settarget
{
Set {_ target = value ;}
}
Public eventdispatcher currenttarget
{
Get {return _ currenttarget ;}
}
Internal eventdispatcher setcurrenttarget
{
Set {_ currenttarget = value ;}
}
Public int eventphase
{
Get {return _ eventphase ;}
}
Internal int seteventphase
{
Set {_ eventphase = value ;}
}
Public bool bubbles
{
Get {return _ bubbles ;}
}
Public String types
{
Get {return _ types ;}
}
Public bool cancelable
{
Get {return _ cancelable ;}
}
}
During usage, you can replace the default base class inherited by the new class in U3D with eventdispatcher so that you have the same event mechanism as as3.
You are welcomed to provide more suggestions on any bugs.