Talos docs

EnvironmentInfo

Since 0.6Changed in next

The sky the scene is lit by, as it is drawn, and a behaviour's override of it.

Plain text

The scene file (and POST /environment, and the editor) author the sky. A behaviour that brings weather (a storm rolling in, mist thickening at dusk) draws an override over it with {@link EnvironmentInfo.override}. The override is never written to the scene, and after a hot reload it is drawn again over the document's new sky, so the two never fight. Reacting to the sky (dimming a torch at dusk) only needs the reads. See docs/SKY.md, "A behaviour's override".

Signature

export interface EnvironmentInfo {
  readonly kind: SkyKind
  /** The preset name for a procedural or atmosphere sky; null for the other kinds. */
  readonly preset: string | null
  /** Travel direction of the sun (sun -> scene), `[x, y, z]`. All zero when the sky has no sun. */
  readonly sunDirection: Vec3
  /** The sun's irradiance. 0 below the horizon, so `sunIntensity > 0` is "it is daytime". */
  readonly sunIntensity: number
  /** Scalar on the whole environment: background, diffuse and specular alike. */
  readonly intensity: number
  /** Yaw applied to the sky, radians. */
  readonly rotation: number
  /**
   * Draws `patch` over the scene's sky, fog, ambient and exposure at the end of this tick, merged
   * into what earlier calls asked (objects field by field); a field set to null is the scene's own
   * again. The override is above the scene: a `preset` it writes (a sky's, its `clouds`', a fog's)
   * sets aside the scene's fields that preset fills. The scene's own rules check it when it is
   * drawn: an override the scene file could not have is refused with one
   * `environment.override-refused` warning, and the last good one stays. Fog, ambient, exposure and
   * the sky's `intensity` and `rotation` are cheap to set every tick (a storm's ramp); a `preset`,
   * `kind` or sun change re-bakes the sky's light, once per change. What reflects the sky (in HD,
   * the sea) reflects it through the fog. The reads above say what is drawn, from the tick after. A
   * run with no renderer (headless) draws nothing, so its reads stay the scene's. Throws
   * `environment.override-invalid` (a `TypeError`, or a `RangeError` for a number that is not
   * finite) for a patch that is not one.
   *
   * ```ts
   * update(ctx) {
   *   const storm = Math.min(1, ctx.time.now / 60)
   *   ctx.environment.override({ fog: { visibilityM: 8000 - 7000 * storm }, sky: { intensity: 1 - 0.6 * storm }, exposureMode: "manual", exposure: 1 - 0.3 * storm })
   *   if (storm === 1) ctx.environment.override({ sky: { clouds: { preset: "storm" } } })
   * }
   * ```
   */
  override(patch: EnvironmentOverride): void
  /** Ends the override: the scene's own sky, fog, ambient and exposure again, from the next tick. */
  clearOverride(): void
}

Import: import type { EnvironmentInfo } from "@argus/api"

Members

MemberSignatureDescription
kindreadonly kind: SkyKind
presetreadonly preset: string | nullThe preset name for a procedural or atmosphere sky; null for the other kinds.
sunDirectionreadonly sunDirection: Vec3Travel direction of the sun (sun -> scene), [x, y, z]. All zero when the sky has no sun.
sunIntensityreadonly sunIntensity: numberThe sun's irradiance. 0 below the horizon, so sunIntensity > 0 is "it is daytime".
intensityreadonly intensity: numberScalar on the whole environment: background, diffuse and specular alike.
rotationreadonly rotation: numberYaw applied to the sky, radians.
overrideoverride(patch: EnvironmentOverride): voidDraws patch over the scene's sky, fog, ambient and exposure at the end of this tick, merged into what earlier calls asked (objects field by field); a field set to null is the scene's own again. The override is above the scene: a preset it writes (a sky's, its clouds', a fog's) sets aside the scene's fields that preset fills. The scene's own rules check it when it is drawn: an override the scene file could not have is refused with one environment.override-refused warning, and the last good one stays. Fog, ambient, exposure and the sky's intensity and rotation are cheap to set every tick (a storm's ramp); a preset, kind or sun change re-bakes the sky's light, once per change. What reflects the sky (in HD, the sea) reflects it through the fog. The reads above say what is drawn, from the tick after. A run with no renderer (headless) draws nothing, so its reads stay the scene's. Throws environment.override-invalid (a TypeError, or a RangeError for a number that is not finite) for a patch that is not one. ts update(ctx) { const storm = Math.min(1, ctx.time.now / 60) ctx.environment.override({ fog: { visibilityM: 8000 - 7000 * storm }, sky: { intensity: 1 - 0.6 * storm }, exposureMode: "manual", exposure: 1 - 0.3 * storm }) if (storm === 1) ctx.environment.override({ sky: { clouds: { preset: "storm" } } }) }
clearOverrideclearOverride(): voidEnds the override: the scene's own sky, fog, ambient and exposure again, from the next tick.

Example

The tested fixture fixtures/recipes/jump-pad-and-elevator/scenes/behaviors/camera-zone.ts.

import type { Behavior } from "@argus/api"

/**
 * A trigger volume that retunes the camera while the player is inside it.
 *
 * The engine has no camera-zone concept and needs none: a volume, a `trigger` component and this.
 * Here the player's behaviour owns the camera (it re-sends its params when the view is turned), so
 * the zone tells it what to change rather than calling `ctx.camera.set` itself. In a scene where
 * nothing else writes the camera, the zone can call `ctx.camera.set(kind, params)` directly.
 */
interface Props {
  /** `ctx.camera.set` params to merge in on the way in, and on the way out. */
  inside?: Record<string, unknown>
  outside?: Record<string, unknown>
}

export default {
  onTrigger(ctx, trigger) {
    const params = trigger.entering ? ctx.props.inside : ctx.props.outside
    if (params) ctx.events.emit("camera-zone", { target: trigger.other.id, params })
  },
} satisfies Behavior<Record<string, never>, Props>