The incoming video changed size — a different capture mode, a different console output setting, a stream restart. Fired before the first frame of the new size reaches OnFrameReceived, so anything you measured against the old frames can be thrown out in time. Note this is about the video, not the app window: resizing the window never moves a pixel of frame space, so there is deliberately no event for it.
Engine events
Events the engine fires into hook. Subscribe with hook.Add.
Fired on key-down, whatever the overlay is doing. Whether an open menu should silence your keybind is your call, not the engine's: check OVERLAY_OPEN and return early if that is what you want.
The one thing the engine does decide: a focused textbox takes the keystroke first, and no KeyPress follows. Typing is never a keybind — a letter going into a pinned note must not also fire out of somebody's sentence.
| Callback arg | Type | Notes |
|---|---|---|
| key | string | The key's display name, e.g. "P", "Space", "F1". |
Return true to consume the key. A consumed key goes no further: later mods' "KeyPress" hooks do not fire for it, and neither do the app's own defaults (Escape closing the overlay — or, with the overlay closed, quitting the program). This is how a mod-drawn text field takes typing safely: its letters stop doubling as other mods' keybinds, and Escape lets go of the field instead of closing the app. Return nothing for keys that are not yours — consuming everything would eat every other mod's binds and the app's own controls.
hook.Add("KeyPress", "screenshotter", function(key)
if OVERLAY_OPEN then return end -- not while the menu is up
if key == "P" then screenshot("screenshots/" .. os.time() .. ".png") end
end)
Fired once per element, every frame, just before it is drawn — for every element, native ones included. Mutate the passed element table to restyle, rename, hide (el.hidden = true), or re-mode anything on the overlay.
| Callback arg | Type | Notes |
|---|---|---|
| el | Element (table) | The live Element being drawn. Its el.id tells you which one; mutating it takes effect this frame. |
hook.Add("OverlayElement", "myskin", function(el)
if el.id == "options" then el.button.label = "Settings" end
if el.id == "close_overlay" then el.hidden = true end
end)
Fired for every captured video frame, before it is displayed. Mutate the frame's pixels in place (through the Frame object) to alter what's shown — no return value needed. Handlers run in turn; if one returns a non-nil value, the remaining handlers are skipped for that frame.
| Callback arg | Type | Notes |
|---|---|---|
| frame | Frame | A read/write view of the raw pixel buffer. See Frame. |
frame:format() — capture frames are usually NV12 (planar YUV), not RGBA.hook.Add("OnFrameReceived", "dim-top", function(frame)
local pitch = frame:pitch()
for row = 0, 40 do -- NV12: Y plane is the first rows
for col = 0, frame:width() - 1 do
frame:setByte(row * pitch + col, 16) -- Y=16 -> black band
end
end
end)