From 0908f1bd900dc53a12b7ceba89e61bbaf2a4f639 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Mon, 2 Jan 2017 19:31:53 +0100 Subject: Initial --- System.c4g/Global.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 System.c4g/Global.c (limited to 'System.c4g/Global.c') diff --git a/System.c4g/Global.c b/System.c4g/Global.c new file mode 100644 index 0000000..d3b126c --- /dev/null +++ b/System.c4g/Global.c @@ -0,0 +1,419 @@ +#strict 2 + +static Event_Stack; +static Event_StackPos; +static Event_Listeners; + +static const Event_Sender = 0; +static const Event_Name = 1; +static const Event_ReturnValue = 2; +static const Event_Accepted = 3; +static const Event_Prevented = 4; + +global func AddEventListener(eventName, array listener, int priority, customArgs) +{ + if(GetType(eventName) == C4V_Array) + { + for(var i = 0; i < GetLength(eventName); ++i) + { + if(GetType(customArgs) == C4V_Array) + { + AddEventListener(eventName[i], listener, priority, customArgs[i]); + } + else + { + AddEventListener(eventName[i], listener, priority, customArgs); + } + } + return; + } + + if(GetType(customArgs) != C4V_Array) + { + customArgs = [customArgs]; + } + + var sender = this; + if(GetType(sender) == C4V_C4Object) + { + sender = ObjectNumber(sender); + } + if(GetLength(listener) == 3) + { + customArgs = listener[2]; + listener = [listener[0], listener[1]]; + } + var newListener = [listener, customArgs]; + var listeners = GetEventListeners(sender, eventName); + var i; + for(i = 0; i < GetLength(listeners); ++i) + { + if(GetType(listeners[i]) != C4V_Array) + { + listeners[i] = [priority, [newListener]]; + i = -1; + break; + } + else if(listeners[i][0] == priority) + { + listeners[i][1][GetLength(listeners[i][1])] = newListener; + i = -1; + break; + } + else if(listeners[i][0] > priority) + { + break; + } + } + if(i != -1) + { + var swap = listeners[i], swap2; + listeners[i] = [priority, [newListener]]; + var length = GetLength(listeners); + for(; i < length; ++i) + { + swap2 = listeners[i + 1]; + listeners[i + 1] = swap; + swap = swap2; + } + } + SetEventListeners(sender, eventName, listeners); +} + +global func RemoveEventListener(sender, eventName, listener, customArgs) +{ + if(GetType(sender) == C4V_C4Object) + { + sender = ObjectNumber(sender); + } + if(sender == -1) + { + var i = 0; + for(var i = 0; i < GetLength(Event_Listeners); ++i) + { + if(GetType(Event_Listeners[i]) == C4V_Array) + { + RemoveEventListener(i, eventName, listener, customArgs); + } + } + } + else + { + if(eventName == -1) + { + for(var event in Event_Listeners[sender]) + { + RemoveEventListener(sender, event[0], listener, customArgs); + } + } + else + { + var emptyPrios = 0; + var eventListeners = GetEventListeners(sender, eventName); + for(var i = 0; i < GetLength(eventListeners); ++i) + { + if(GetType(eventListeners[i]) != C4V_Array) + { + ++emptyPrios; + continue; + } + var listeners = eventListeners[i][1]; + eventListeners[i][1] = []; + for(var eventListener in listeners) + { + if(!((listener == -1 || eventListener[0] == listener) && (customArgs == -1 || eventListener[1] == customArgs))) + { + eventListeners[i][1][GetLength(eventListeners[i][1])] = eventListener; + } + } + if(GetLength(eventListeners[i][1]) == 0) + { + ++emptyPrios; + } + } + if(emptyPrios == GetLength(eventListeners)) + { + ClearEventListener(sender, eventName); + } + else + { + ClearEmptyPrios(eventListeners); + SetEventListeners(sender, eventName, eventListeners); + } + } + } +} + +global func ClearEventListener(sender, eventName) +{ + var eventListeners = Event_Listeners[sender]; + Event_Listeners[sender] = []; + for(var i = 0; i < GetLength(eventListeners); ++i) + { + if(eventListeners[i][0] != eventName) + { + Event_Listeners[sender][GetLength(Event_Listeners[sender])] = eventListeners[i]; + } + } + if(GetLength(Event_Listeners[sender]) == 0) + { + Event_Listeners[sender] = 0; + } +} + +global func ClearEmptyPrios(&prios) +{ + var oldPrios = prios; + prios = []; + + for(var prio in oldPrios) + { + if(GetType(prio) == C4V_Array) + { + if(GetLength(prio[1]) != 0) + { + prios[GetLength(prios)] = prio; + } + } + } +} + +global func GetEventListeners(sender, eventName) +{ + if(GetType(Event_Listeners) == C4V_Array && GetType(Event_Listeners[sender])) + { + for(var event in Event_Listeners[sender]) + { + if(event[0] == eventName) + { + return event[1]; + } + } + } + return []; +} + +global func SetEventListeners(sender, eventName, listeners) +{ + if(GetType(Event_Listeners) != C4V_Array) + { + Event_Listeners = CreateArray(sender); + Event_Listeners[sender] = [[eventName, listeners]]; + } + else + { + if(GetType(Event_Listeners[sender]) == C4V_Array) + { + for(var i = 0; i < GetLength(Event_Listeners[sender]); ++i) + { + if(Event_Listeners[sender][i][0] == eventName) + { + Event_Listeners[sender][i][1] = listeners; + return; + } + } + } + else + { + Event_Listeners[sender] = []; + } + Event_Listeners[sender][GetLength(Event_Listeners[sender])] = [eventName, listeners]; + } +} + +global func PushEvent(array event) +{ + if(GetType(Event_Stack) != C4V_Array) + { + /*Event_Stack = [0, 0]; // otherwise there is a really stupid operator "=" left side: got "any" but expected "&" error at this line in Event(): + * // Event_Stack[Event_StackPos][Event_ReturnValue] = CallListener(listener[0], listener[1], args, event); + * Event_StackPos = 0; + * PopEvent();*/ + Event_Stack = []; + Event_StackPos = -1; + } + Event_Stack[++Event_StackPos] = event; +} + +global func PopEvent() +{ + if(Event_StackPos >= 0) + { + var event = Event_Stack[Event_StackPos]; + SetLength(Event_Stack, Event_StackPos--); + return event; + } +} + +global func Accept() +{ + Event_Stack[Event_StackPos][Event_Accepted] = true; +} + +global func Prevent() +{ + Event_Stack[Event_StackPos][Event_Prevented] = true; +} + +global func Accepted(array event) +{ + if(event) + { + return event[Event_Accepted]; + } + else + { + return Event_Stack[Event_StackPos][Event_Accepted]; + } +} + +global func Prevented(array event) +{ + if(event) + { + return event[Event_Prevented]; + } + else + { + return Event_Stack[Event_StackPos][Event_Prevented]; + } +} + +global func ReturnValue(array event) +{ + if(event) + { + return event[Event_ReturnValue]; + } + else + { + return Event_Stack[Event_StackPos][Event_ReturnValue]; + } +} + +global func Event(string eventName, array args) +{ + var sender = this; + var event = [sender, eventName, 0, false, false]; + PushEvent(event); + + if(GetType(sender) == C4V_C4Object) + { + sender = ObjectNumber(sender); + } + + var allListeners = [GetEventListeners(sender, eventName)]; + if(sender != 0) + { + allListeners[1] = GetEventListeners(0, eventName); + } + + for(var listeners in allListeners) + { + for(var listenerPrio in listeners) + { + if(GetType(listenerPrio) == C4V_Array) + { + for(var listener in listenerPrio[1]) + { + var ret = CallListener(listener[0], listener[1], args, event); + var e = Event_Stack[Event_StackPos]; + e[Event_ReturnValue] = ret; + Event_Stack[Event_StackPos] = e; + + if(Accepted()) + { + break; + } + } + } + } + } + + event = PopEvent(); + return event; +} + +global func CallListener(array listener, array customArgs, array args, array event) +{ + if(GetType(listener[0]) == C4V_Any) + { + return eval(Format("%s(%s, %s, %s)", listener[1], Serialize(event), Serialize(customArgs), Serialize(args))); + } + else if(GetType(listener[0]) == C4V_C4Object) + { + if(GetType(listener[1]) == C4V_String) + { + return eval(Format("%s->%s(%s, %s, %s)", Serialize(listener[0]), listener[1], Serialize(event), Serialize(customArgs), Serialize(args))); + } + else if(GetType(listener[1]) == C4V_Array) + { + return listener[0]->f(listener[1], [event, customArgs, args]); + } + } + else if(listener[0] == -1 && event[0] != 0) + { + if(GetType(listener[1]) == C4V_String) + { + return eval(Format("%s->%s(%s, %s, %s)", Serialize(event[0]), listener[1], Serialize(event), Serialize(customArgs), Serialize(args))); + } + else if(GetType(listener[1]) == C4V_Array) + { + return event[0]->f(listener[1], [event, customArgs, args]); + } + } + else if(GetType(listener[0]) == C4V_Array) + { + return f(listener, [event, customArgs, args]); + } +} + +global func Event_Adapter(target, string function, passArgs) +{ + return [target, "Event_AdapterListener", [target, function, passArgs]]; +} + +global func Event_AdapterListener(array event, array customArgs, array args) +{ + if(customArgs[2] == -1) + { + args = []; + } + else if(GetType(customArgs[2]) == C4V_Array) + { + args = customArgs[2]; + } + + var argString = ""; + for(var i = 0; i < GetLength(args) && i < 10; ++i) + { + if(i != 0) + { + argString = Format("%s, ", argString); + } + + argString = Format("%s%s", argString, Serialize(args[i])); + } + + if(GetType(customArgs[0]) == C4V_Any || customArgs[0] == -1) + { + return eval(Format("%s(%s)", customArgs[1], argString)); + } + else if(GetType(customArgs[0]) == C4V_C4Object) + { + return eval(Format("%s->%s(%s)", Serialize(customArgs[0]), customArgs[1], argString)); + } +} + +global func GameCallEx(string function) +{ + var event = Event(Format("GameCallEx%s", function), CreateFilledArray(...)); + if(Prevented(event)) + { + return ReturnValue(event); + } + else + { + return _inherited(function, ...); + } +} -- cgit v1.2.3-54-g00ecf