-
Notifications
You must be signed in to change notification settings - Fork 6
Delegates
Ruslan Mustakov edited this page May 16, 2016
·
1 revision
UE4 delegates allow you to call functions bound to them in a generic and type-safe way. The concept is similar to C# delegates.
Delegates are often used to implement events in a game - an actor can notify others when something of interest has happened without having to know who exactly is subscribed to the event.
nimue4 provides udelegate
macro to declare delegate types:
type DelegateKind* = enum
dkSimple,
dkMulticast,
dkDynamic,
dkDynamicMulticast,
dkSimpleRetVal,
dkMulticastRetVal,
dkDynamicRetVal,
dkDynamicMulticastRetVal
macro udelegate*(name: expr, kind: DelegateKind, params: varargs[expr]): stmt
Examples of declaring different kinds of delegates:
# Simple delegate with no parameters and no return value
udelegate(FSomethingHappened, dkSimple)
# Dynamic multicast delegate with 3 parameters
udelegate(FCharacterMovementUpdated, dkDynamicMulticast,
deltaSeconds: cfloat, oldLocation: FVector, oldVelocity: FVector)
# Dynamic multicast delegate with 3 parameters and boolean return value
# For RetVal delegates the third parameter denotes return value type
udelegate(FOnProcessEvent, dkDynamicMulticastRetVal, bool,
actor: ptr AActor, f: ptr UFunction, obj: ptr UObject)
# Simple delegate with no parameters and bool return value
udelegate(FCanUnpause, dkSimpleRetVal, bool)
After a delegate is declared, you can use it as an ordinary type:
# Gunner.nim
import ue4
udelegate(FNoAmmo, dkDynamicMulticast)
uclass AGunner of AActor:
var ammo* {.editorReadOnly, bpReadOnly, category: "Gunner".}: int32
var onNoAmmo* {.bpDelegate.}: FNoAmmo
method beginPlay() {.override, callSuper.} =
ammo = 42
onNoAmmo.addDynamic(this, noAmmoHandler)
method tick(deltaSeconds: float32) {.override, callSuper.} =
if ammo > 0:
dec ammo
if ammo == 0:
onNoAmmo.broadcast()
proc noAmmoHandler() =
ueLog("Oh no, the ammo is wasted!")
Procedures supported by all delegates are:
proc clear[T](delegate: T)
proc isBound[T](delegate: T): bool
Depending on their type, delegates support the following procedures and templates:
# Execution for non-multicast delegates:
proc execute(delegate: FYourDelegate, #[delegate params]#): #[delegate retval]#
proc executeIfBound(delegate: FYourDelegate, #[delegate params]#): #[delegate retval]#
# Binding for non-multicast dynamic delegates:
template bindDynamic(delegate: typed, obj: ptr, methodName: untyped)
# Binding for simple non-dynamic delegates:
template bind(delegate: typed, obj: ptr, methodName: untyped)
template bindUObject(delegate: typed, obj: ptr, methodName: untyped)
# Execution for multicast delegates:
proc broadcast(delegate: FYourDelegate, #[delegate params]#)
# Binding for non-dynamic multicast delegates:
template add(delegate: typed, obj: ptr, methodName: untyped)
template addUObject(delegate: typed, obj: ptr, methodName: untyped)
# Binding for dynamic multicast delegates:
template addDynamic(delegate: typed, obj: ptr, methodName: untyped)
# Unbinding for dynamic delegates:
template removeDynamic(delegate: typed, obj: ptr, methodName: untyped)
# Unbinding for multicast delegates:
proc removeAll[T](delegate: T, obj: ptr UObject)