Some C++ APIs take a delegate pointer for an interface with virtual methods:
- touch delegates
- keyboard delegates
- scroll view delegates
- alert protocols
In Luau, pass a table with method names as keys and Luau functions as values. The runtime builds a C++ trampoline that calls the matching table function for each virtual method.
Each supported delegate has a Luau type stub. The stub lists optional function fields, one per virtual method. Include only the methods you care about.
Touch delegates register on the dispatcher, not on the layer:
local director = geode.cocos2d.CCDirector.sharedDirector()
if not director then return end
director:getTouchDispatcher():addTargetedDelegate({
ccTouchBegan = function(touch: CCTouch, event: CCEvent): boolean
return true
end,
ccTouchEnded = function(touch: CCTouch, event: CCEvent)
print("touch ended")
end,
}, 0, false)Default behavior on error or missing method:
- If a callback errors or times out, LuauAPI logs the failure and returns the method default.
- A missing method returns the default without logging.
- Defaults:
boolreturnsfalse,int/float/doublereturn0,stringreturns empty, object methods returnnil.
Method names and argument types match the C++ interface. Multi-touch variants use CCSet.
Pass a CCKeyboardDelegate table to CCKeyboardDispatcher:addDelegate.
Use Keyboard input for the global Geode event stream.
local director = geode.cocos2d.CCDirector.sharedDirector()
if not director then return end
director:getKeyboardDispatcher():addDelegate({
keyDown = function(key: number, dt: number)
print("down", key, dt)
end,
keyUp = function(key: number, dt: number)
print("up", key, dt)
end,
})Dispatchers also expose removeDelegate and forceRemoveDelegate to unregister.
Delegate trampolines use the same anchor and orphan registry rules as other callbacks. See callbacks for retention, cleanup, and caps.
When a bound method returns a delegate pointer:
- If the native object is a Luau-bound trampoline, the runtime pushes the same table you passed in.
- Otherwise it pushes
nil(a native C++ delegate, not round-trippable to Luau).
Supported interfaces include:
- Cocos2d input delegates:
CCTouchDelegateCCKeyboardDelegateCCKeypadDelegateCCMouseDelegateCCIMEDelegateCCTextFieldDelegateCCEditBoxDelegate
- Geode/game interfaces from Broma, such as:
- alert protocols
- scroll delegates
- download callbacks
Geode and game interfaces follow the Broma *Delegate/*Protocol types.
See the exact members in type stubs.
The dominant Geode pattern is a delegate-typed field:
popup.m_delegate = {
setIDPopupClosed = function(popup: SetIDPopup, id: number)
print("closed", id)
end,
}Generated trampolines live under build/luauapi-gen/src/framework/callback/ and regenerate with the normal build.
See Codegen.
See Limits and errors for callback budgets and orphan-registry caps.
src/framework/callback/LuaDelegate.hpptools/luau_codegen/model/delegate_specs.pytools/luau_codegen/emit/delegates.pytools/luau_codegen/cli/main.py