Eye Tracking Handler

From Frictional Wiki
< HPL3‎ | SOMA‎ | Scripting
Revision as of 14:32, 2 October 2026 by TiMan (talk | contribs) (Expand the practical source walkthrough and clarify how to use the handler.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search


The Eye Tracking Handler registers entities and exposes gaze, blink and extended-view data. IsAvailable checks whether the eye-tracking engine is installed; IsActive checks whether eye tracking is active. Entity registration makes an entity available for gaze queries.

Before you start

  1. Open the map script inside your own mod. Keep its generated includes, cScrMap : iScrMap class and callback structure. See Add your first script if you have not edited a map script yet.
  2. Add the helper include shown below alongside the script’s other includes.
  3. Read the stock example before copying its calls: named entities, voice subjects, materials and callbacks must belong to the map or resources you are using.

Follow the stock example

#include "helpers/helper_modules.hps"

EyeTracking_IsAvailable

If the eye tracking engine is installed

In script/modules/MenuHandler.hps, SOMA calls EyeTracking_IsAvailable as follows.

EyeTracking_IsAvailable();

This is an excerpt from that stock script; its referenced names and variables belong to that script.

Register a target, then query it

The transport-station map registers AmyTalkTrigger in maps/chapter01/01_04_transport_station/01_04_transport_station.hps:

EyeTracking_RegisterEntity("AmyTalkTrigger", true, false, true, 15.0f, 4.0f);

This call enables line-of-sight checking, leaves the closest-entity line-of-sight option false, enables gaze zoom, and supplies checking and zoom distances of 15.0f and 4.0f. These distances are compared with the length of the entity-to-player position vector in the handler.

In the map’s Update callback, the registered target is queried by the same name:

if (EyeTracking_IsEnvironmentReactive() && EyeTracking_IsEntityBeingLookedAt("AmyTalkTrigger") && mbSpottedAmy == false)
{
    Audio_SpotAmy();
}

Audio_SpotAmy sets mbSpottedAmy to true, so this event does not keep firing after Amy has been spotted. That flag and function belong to the stock map; use your own event and state when adapting this pattern.

Adapt and troubleshoot

  1. Include helpers/helper_modules.hps and register your map’s target by its entity name. The named overload returns without registering anything if that name cannot be resolved.
  2. Query that same name in the callback that handles your event. The stock example also checks EyeTracking_IsEnvironmentReactive() before reacting.
  3. If the target is not detected, trace UpdateTrackedObjects in script/modules/EyeTrackingHandler.hps. It skips inactive entities, targets beyond the checking distance and targets without a physics-body or mesh bounding volume. When line-of-sight checking is enabled, it also checks visibility before testing the gaze against the projected rectangle.

Gaze zoom is controlled separately from the event call: the handler changes the player’s field-of-view multiplier to 0.85f when its tracking threshold is exceeded within the zoom distance, and restores it to 1.0f when tracking drops below the threshold or the target moves beyond that distance.

Check your change

Save the script and restart the map in development mode with F5. If the script fails, open F1 and use Show Error List or Show HPL Log. See the development loop for the launch and debugging steps.

See also