Assetto Corsa の自作HUDを Lua で作成しよう

# Assetto Corsa の自作HUDを Lua で作成しよう

## はじめに

Assetto Corsa (初代) で自作したHUDに関する覚え書きです。SimHubなどのオーバーレイ機能でも簡単にHUDを作成してカスタマイズできますが、スクリーンショットや録画がしづらかったため、直接アプリを作成するに至りました。

英語のドキュメントも少なかったため、何かの参考になれば幸いです。Content Manager と CSP 1.76 以降 (カスタムシェーダーパッチ) は必須です。

### 参考になるサイト

- [CPS 公式の Github Wiki によるガイド (英語)](https://github.com/ac-custom-shaders-patch/acc-lua-sdk/wiki/Lua-apps)

## 基本構造

Assetto Corsa のアプリは、インストールフォルダの `apps/lua` ディレクトリ内に `myApp` などの専用フォルダを作成し、その中に必要なファイルを配置することで動作します。

### 必要なファイル

- `manifest.ini` - アプリのメタ情報を定義するファイル
- `myApp.lua` - メインのスクリプト

### manifest.ini の概要

`manifest.ini` はアプリの基本情報を記述する必須のファイルです。以下のように記述します。詳細については後述します。

```ini
[INFO]
NAME = App Name
AUTHOR = YourName
VERSION = 1.0
DESCRIPTION = App Description

[CORE]
LAZY = FULL

[WINDOW_...]
ID = main
NAME = My App Main Window
FUNCTION_MAIN = windowMain
SIZE = 300, 300
```

### Lua スクリプトの基本

まずは "Hello World!" を表示するシンプルな例を見てみましょう。

```lua
function script.windowMain(dt)
  ui.text("Hello Assetto Corsa World!")
end
```

これで "Hello World!" を表示する簡単なアプリが完成です。ゲーム内で表示を確認してみましょう。

## 簡単な車両情報の表示例

次に、具体的に車両情報を表示する例を見てみましょう。

```lua
function script.windowMain(dt)
  ui.drawRectFilled(vec2(0, 0), vec2(200, 100), rgbm(0, 0, 0, 0.5)) -- 半透明の黒で背景を描画
  ui.text(string.format("Speed: %d km/h", ac.getCar(0).speedKmh))
  ui.text(string.format("Lap Time: %s", ac.lapTimeToString(ac.getCar(0).lapTimeMs)))
end
```

`script.windowMain(dt)` は毎フレーム呼び出されるため、常に最新の情報が表示されます。なお、`windowMain` という関数名でなくても、`manifest.ini` の `FUNCTION_MAIN` で指定した関数名であれば何でも大丈夫です。

## 代表的なプロパティ・メソッド

### データ取得API

`ac.getCar(carIndex)`: 指定した車両の情報を取得。`carIndex = 0` はプレイヤーの車両を指す。返り値の型は `ac.StateCar` クラス。`ac.StateCar` クラスには様々なプロパティやメソッドが紐づいており、車両に関する様々なデータを取得できる。

同様に `ac.getSim()` や、 `ac.getSession(ac.getSim().currentSessionIndex)` などから、レース内容やゲーム全体の情報にアクセスできる。

#### タコメーター等を作る場合に必要になるデータ

- `ac.getCar(0).speedKmh`: 車の速度 (km/h)
- `ac.getCar(0).rpm`: エンジンの回転数
- `ac.getCar(0).rpmLimiter`: エンジンの回転数の最大値
- `ac.getCar(0).gear`: 現在のギア

#### ラップ数や順位を表示するのに必要になるデータ

- `ac.getCar(0).lapCount`: プレイヤー車両の現在のラップ
- `ac.getSession(getSim().currentSessionIndex).laps`: レースの最大ラップ数
- `ac.getCar(0).racePosition`: プレイヤー車両の現在の順位
- `ac.getSim().carsCount`: 参加車両数

#### ラップタイムを表示するのに必要になるデータ

- `ac.getCar(0).lapTimeMs`: 現在のラップタイム (ミリ秒)
- `ac.getCar(0).previousLapTimeMs`: 前のラップのラップタイム (ミリ秒)
- `ac.getCar(0).bestLapTimeMs`: ベストラップのラップタイム (ミリ秒)

#### リーダーボードを表示するのに必要になるデータ

- `ac.getCar.leaderboard(racePosition)`: リーダーボード上の順位から車の情報を入手
- `ac.getCar.leaderboard(racePosition).index`: 車両のインデックス
- `ac.getCar.leaderboard(racePosition):driver()`: ドライバー名
- `ac.getCar.leaderboard(racePosition):driverNationCode()`: ドライバー所属の国コード
- `ac.getGapBetweenCars(carMainIndex, carComparingToIndex)` : 2台の車のタイムギャップ (秒) を計算

### 描画系 API

#### 以下のAPIで使う型

- `vec2(x, y)`: 以下で使用する2次元座標の指定手段
- `rgbm(r, g, b, alpha)`: 以下で使用する色の指定手段。r, g, b, alpha ともに0～1で指定

#### テキストの描画

- `ui.setCursor(vec2)`: テキストの表示位置の指定
- `ui.text(text)`: 基本的なテキスト表示
- `ui.dwriteTextAligned(text, fontSize, horizontalAlignment, verticalAlignment, size, allowWordWrapping, color)`: エリアを指定した詳細なテキスト表示
  - `Alignment` は `ui.Alignment.Start`, `ui.Alignment.Center`, `ui.Alignment.End` の3つから指定

#### 図形の描画

- `ui.drawLine(p1, p2, color, thickness)`: 線の描画
- `ui.drawRect(p1, p2, color, rounding, roundingFlag, thickness)`: 四角形の描画
- `ui.drawRectFilled(p1, p2, color, rounding, roundingFlag)`: 塗りつぶした四角形の描画
- `ui.drawCircle(p1, radius, color, numSegments, thickness)`: 円の描画
- `ui.drawImage(imageSource, p1, p2, color, uv1, uv2, mode)`: 画像の描画
- `ui.drawIcon(iconID, p1, p2)`: 様々なアイコンの描画。iconIDに国コードを入れることで国旗が描画可能

#### パスを使った描画

線を引いた後、必ず `ui.pathStroke` で線を描画するか、 `ui.pathFillConvex` で塗りつぶすように。

- `ui.pathLineTo(pos)`: 直線を引く
- `ui.pathArcTo(center, radius, angleFrom, angleTo, numSegments)`: 弧を描く
- `ui.pathStroke(color, closed, thickness)`: パスの描画
- `ui.pathFillConvex(color)`: パスで囲った領域の塗りつぶし

#### 描画補助

- `ui.beginOutline()`, `ui.endOutline(color, scale)` : 囲った内容のアウトラインの描画
- `ui.beginRotation()`, `ui.endRotation(deg, offset)`: 囲った内容を、要素の中心を軸にして回転

### その他補助系API

- `ac.lapTimeToString(time, allowHours)`: ラップタイム(ミリ秒)を `"mm:ss.ff"` のテキストに変換

## サンプルコード

### manifest.ini の例

```ini
[INFO]
NAME = My HUD App
AUTHOR = YourName
VERSION = 0.01
DESCRIPTION = Custom HUD for Assetto Corsa

[CORE]
LAZY = FULL

[WINDOW_...]
ID = tachometer
NAME = My Tachometer
FUNCTION_MAIN = tachometer
SIZE = 300, 300
FLAGS = FADING

[WINDOW_...]
ID = leaderboard
NAME = My Leaderboard
FUNCTION_MAIN = leaderboard
SIZE = 300, 800
FLAGS = FADING

[WINDOW_...]
ID = map
NAME = My Map
FUNCTION_MAIN = map
SIZE = 300, 300
FLAGS = FADING, NO_BACKGROUND
```

この `manifest.ini` を使うと、以下の3つのアプリウィンドウを表示できます。

### タコメーターの描画例

```lua
function script.tachometer(dt)
  local playerCar = ac.getCar(0) --- プレイヤーの車両情報を取得
  local rpm = playerCar.rpm --- エンジンの回転数
  local maxRpm = playerCar.rpmLimiter --- RPMの最大値
  local gear = playerCar.gear --- 現在のギア
  local center = vec2(150, 150)

  ui.pathArcTo(center, 100, math.rad(150), math.rad(390), 20) --- タコメーターの背景の描画
  ui.pathStroke(rgbm(0, 0, 0, 1), false, 4)
  ui.pathArcTo(center, 100, math.rad(150), math.rad(150 + (390 - 150) * (rpm / maxRpm)), 20) --- タコメーターの描画
  ui.pathStroke(rgbm(1, 1, 1, 1), false, 4)
  ui.setCursor(center +  vec2(-25, -25))
  ui.dwriteTextAligned(gear, 50, ui.Alignment.Center, ui.Alignment.Center, vec2(50, 50), false, rgbm(1, 1, 1, 1)) --- ギアのテキスト表示
end
```

使用した主なプロパティ

- `ac.getCar(0).rpm`, `ac.getCar(0).rpmLimiter`: エンジンの回転数, 最大回転数
- `ac.getCar(0).gear`: ギア

### ランキングボードの描画例

```lua
function script.leaderboard(dt)
  for racePosition = 1, ac.getSim().carsCount do
    local car = ac.getCar.leaderboard(racePosition - 1)
    local gap = ac.getGapBetweenCars(car.index, 0)
    local posY = 20 + 30 * (racePosition - 1)

    ui.setCursor(vec2(20, posY))
    ui.dwriteTextAligned(racePosition, 15, ui.Alignment.Center, ui.Alignment.Center, vec2(30, 30))
    ui.setCursor(vec2(50, posY))
    ui.dwriteTextAligned(car:driverName(), 15, ui.Alignment.Start, ui.Alignment.Center, vec2(150, 30))
    ui.drawIcon(car:driverNationCode(), vec2(200, 20 + (racePositionIndex - 1) * 30), vec2(229, 50 + (racePosition - 1) * 30) )
    ui.setCursor(vec2(230, posY))
    ui.dwriteTextAligned(string.format("%.2f", gap), 15, ui.Alignment.Center, ui.Alignment.Center, vec2(80, 30))
  end
end
```

### マップの描画例

```lua
function script.map(dt)
  local trackPoints = {}
  local minX, minZ, maxX, maxZ = math.huge, math.huge, -math.huge, -math.huge
  local center = vec2(150, 150)
  local radius = 130

  -- マップデータの読み込み
  for i = 1, 1000 do
    local trackPoint = ac.trackProgressToWorldCoordinate(i / 1000)
    table.insert(trackPoints, trackPoint)
  end

  -- 拡大縮小率の算出
  for _, v in ipairs(trackPoints) do
    minX = math.min(minX, v.x)
    minZ = math.min(minZ, v.z)
    maxX = math.max(maxX, v.x)
    maxZ = math.max(maxZ, v.z)
  end
  local scale =  math.min(radius * 2 / (maxX - minX), radius * 2 / (maxZ - minZ))

  -- マップデータの描画
  ui.beginOutline()
  for i = 1, #trackPoints - 1 do
    local p1 = vec2(trackPoints[i].x, trackPoints[i].z)
    ui.pathLineTo(center + p1 * scale)
  end
  ui.pathStroke(rgbm(1, 1, 1, 1), true, 3)
  ui.endOutline(rgbm(0.2, 0.2, 0.2, 1), 2) --- アウトラインの描画

  -- 車両の描画
  for carIndex = 1, ac.getSim().carsCount - 1 do
    local car = ac.getCar(carIndex)
    local carPosition = vec2(car.position.x, car.position.z)
    ui.beginOutline()
    ui.drawCircleFilled(center + carPosition * scale, 4, rgbm(0.9,0.9,0.9,1))
    ui.endOutline(rgbm(0.2, 0.2, 0.2, 1), 1.5) --- アウトラインの描画  
  end

  -- プレイヤーの車両の描画
  local playerCar = ac.getCar(0)
  local playerCarPosition = vec2(playerCar.position.x, playerCar.position.z)
  ui.beginOutline()
  ui.drawCircleFilled(center + playerCarPosition * scale, 5, rgbm(1,0,0,1))
  ui.endOutline(rgbm(0.2, 0.2, 0.2, 1), 2) --- アウトラインの描画
end
```

`ac.trackProgressToWorldCoordinate(i / 1000)` でコースのプロットデータ (`vec3`) を取得し、`ui.pathLineTo(vec2)` で描画するという流れです。

## manifest.ini の詳細設定

`mainfest.ini` では、上述した以外にも様々なプロパティが設定できます

```ini
[INFO]
NAME = My App                              ; アプリ名
AUTHOR = YourName                          ; 制作者名
VERSION = 1.0                              ; バージョン
DESCRIPTION = Custom HUD for Assetto Corsa ; 説明文
REQUIRED_VERSION = 0                       ; 必要なCSPのバージョン

[CORE]
LAZY = FULL
; NONE (デフォルト値): Assetto Corsa のロード時にスクリプトをロードし、閉じられるまで実行
; PARTIAL: アプリが最初に開かれたときにのみスクリプトをロードし、Assetto Corsa が閉じられるまで実行
; FULL: アプリが開かれたときにスクリプトをロードし、すべてのウィンドウが閉じられたときにアプリを完全にアンロードする

[WINDOW_...]
ID = main                  ; アプリのID (スクリプト内で使用することがある)
NAME = My App Main Window  ; アプリの表示名
SIZE = 300, 300            ; アプリウィンドウのサイズ
MIN_SIZE = 40, 20          ; アプリウィンドウの最小サイズ
MAX_SIZE = 1920, 1080      ; アプリウィンドウの最大サイズ
PADDING = 10, 20           ; アプリウィンドウの余白
FLAGS = FADING, NO_BACKGROUND
  ; AUTO_RESIZE: 内容に合わせてウィンドウサイズを自動的にリサイズ
  ; DARK_HEADER: タイトルバーのフォントと記号を黒くする
  ; FADING: 非アクティブなときにウィンドウをフェードアウト
  ; FIXED_SIZE: ウィンドウをリサイズ不可能にする
  ; FLOATING_TITLE_BAR: text and symbols floating/stacked
  ; HIDDEN_OFFLINE: オフラインモードではウィンドウを表示しない
  ; HIDDEN_ONLINE: オンラインモードではウィンドウを表示しない
  ; HIDDEN_RENDER_CUSTOM: カスタムスクリーン設定の状態では表示しない
  ; HIDDEN_RENDER_SINGLE: 1画面モードでは表示しない
  ; HIDDEN_RENDER_TRIPLE: 3画面モードでは表示しない
  ; HIDDEN_RENDER_VR: VRではウィンドウを表示しない
  ; MAIN: このウィンドウをメインウィンドウとして動作させる (指定がない場合、最初のウィンドウがメインウィンドウになる)
  ; NO_BACKGROUND: 背景を透過させる
  ; NO_COLLAPSE: 折りたたみボタンを非表示にする
  ; NO_SCROLL_WITH_MOUSE: マウスホイールでスクロールできないようにする
  ; NO_SCROLLBAR: スクロールバーを表示しない
  ; NO_TITLE_BAR: タイトルバーを表示しない
  ; SETTINGS: タイトルバーに設定ボタンを追加し、設定ウィンドウを開く
  ; SETUP: 設定画面で表示する
  ; SETUP_HIDDEN: 設定画面で表示しない
FUNCTION_MAIN = windowMain ; ウィンドウの内容を描画するために毎フレーム呼び出される関数
FUNCTION_SETTINGS = fn     ; 対応する設定ウィンドウの内容を描画するために呼び出される関数 (SETTINGS フラグがある場合のみ)
FUNCTION_ON_SHOW = fn      ; ウィンドウが開いたときに1度だけ呼び出される関数
FUNCTION_ON_HIDE = fn      ; ウィンドウが閉じるときに1度だけ呼び出される関数
ICON = icon.png            ; ウィンドウのアイコン
FUNCTION_ICON = fn         ; ダイナミックアイコンの場合、ウィンドウアイコンを描画するために代わりに呼び出される関数

[WINDOW_...]
ID = tachometer
NAME = MY APP Tachometer
FUNCTION_MAIN = tachometer
...
; 上記のようにして、複数のウィンドウを設置できる

[SIM_CALLBACKS]
FRAME_BEGIN = fn
UPDATE = fn

[RENDER_CALLBACKS]
OPAQUE = fn
TRANSPARENT = fn

[UI_CALLBACKS]
IN_GAME = fn
```

### 追加の関数

#### `script.update(dt)`

すべてのアプリのワールドマトリックス処理が完了した後、毎フレーム実行される。ウィンドウが非アクティブでも呼び出されるため、高負荷な処理は避けること（必要な場合を除く）。


## さらに詳しく知るには

提供されているプロパティ・メソッドなどのより詳細な情報は、Assetto Corsa 本体フォルダ内のライブラリである `extension/internal/lua-sdk` 内の `lib.lua` または、Github の [CSP の Lua ソースコード](https://github.com/ac-custom-shaders-patch/acc-lua-sdk) を参照してください（内容はほぼ同一）。公開されている他の方のMODを参考にするのもよいと思います。

## 付録: lib.lua より抜粋して紹介

全部並べるとすごい数になるのでよく使いそうな情報を抜粋して紹介。分かる範囲で説明をつけています。より詳細な情報が知りたい方は、`lib.lua` を直接読んでください。

### ac.StateCar

`ac.getCar(carIndex)`, `ac.getCar.leaderborad(racePosition)` などの返り値として得られる車両情報のオブジェクトのクラス

- システム
  - `.index`: プレイヤー車両を0とした車両のインデックス
- 位置情報
  - `.splinePosition`: コースの進行度 (0～1)
  - `.position`: 車両のワールド座標の3次元ベクトル (vec3)
  - `.velocity`: 車両の速度の3次元ベクトル (vec3)
  - `.acceleration`: 車両の加速度の3次元ベクトル (vec3)
  - `.compass`: 車両の向いている方向 (degree) (0が北で90が東)
  - `.altitude`: 車両の海面高度 (m)
- リーダーボード向け
  - `.racePosition`: 順位
  - `.lapCount`: このセッションで完了したラップ数
  - `.sessionLapCount`
  - `:name()`: 車両名
  - `:brand()`: 車両のブランド名
  - `:country()`: 車両の開発国
  - `.year`: 車両の開発年
  - `:driverName()`: ドライバー名
  - `:driverNationCode()`: ドライバーの国コード
  - `:driverNationality()`: ドライバーの国名
  - `:driverTeam()`: ドライバーの所属チーム名
  - `:driverNumber()`: ドライバーの番号
  - `.isRaceFinished`
  - `.isInPit`
  - `.isInPitlane`
  - `.isRetired`
  - `.isAIControlled`: AIコントロールかどうか (boolean)
  - `.aiLevel`: AIレベル
  - `.aiAggression`: AIの攻撃性
- タコメーター・ブーストメーター向け
  - `.rpm`: エンジンの回転数
  - `.rpmLimiter`: エンジンの最大回転数
  - `.rpmMinimum`: エンジンの最小回転数
  - `.speedKmh`: 車両の速度 (kmh: キロメートル毎時)
  - `.speedMs`: 車両の速度 (Ms: メートル毎秒)
  - `.gear`: 現在のギア (-1:R, 0:N) - シーケンシャルではNを経由しない\
    `ac.getCarGearLabel(carIndex)` も参照のこと
  - `.engagedGear`: 現在のギア (-1: R, 0: N) - シーケンシャルでもNを経由する  
  - `.gearCount`: ギア数
  - `.turboCount`: ターボの数
  - `.turboBoost`: ターボのブースト値
  - `.drivetrainPower`: ドライブトレインの馬力
  - `.drivetrainTorque`: ドライブトレインのトルク (Nm)
  - `.batteryVoltage`
  - `.oilPressure`
  - `.oilTemperature`
  - `.exhaustTemperature`
- 入力
  - `.gas`: スロットル (0～1)
  - `.brake`: ブレーキ (0～1)
  - `.clutch`: クラッチ (0～1)
  - `.handbrake`: ハンドブレーキ (0～1)
  - `.steer`: ステアリングの角度 (degree)
  - `.steerLock`: ステアリングの最大角度 (degree)
  - `.autoShift`: オートシフト (boolean)
  - `.autoClutch`: オートクラッチ (boolean)
  - `.hornActive`: ホーン (boolean)
- ライト
  - `.headlightsActive`: ヘッドライトON/OFF (boolean)
  - `.hazardLights`: ハザードランプ (boolean)
  - `.turningLeftLights`: 左折ウィンカー (boolean)
  - `.turningRightLights`: 右折ウィンカー (boolean)
  - `.lowBeams`: ロービーム (boolean)
- 燃料
  - `.fuel`: 燃料 (L)
  - `.maxFuel`: 最大燃料 (L)
  - `.fuelMap`: 現在の燃料マップ
  - `.fuelMaps`: 燃料マップの最大値
  - `.fuelPerLap`: 1ラップごとの燃料消費量 (L)
- タイヤ
  - `.wheels[]`: クラス `ac.StateWheel` のオブジェクトの配列を返す
  - `:tyresName()`: タイヤの短縮名
  - `:tyresLongName()`: タイヤの名前
- ダメージ
  - `.damage[]`: 車体ダメージ (前,後,左,右)
  - `.engineLifeLeft`: エンジンの残りライフ (0～1000)
  - `.gearboxDamage`: ギアボックスのダメージ(0～1)
- オンライン
  - `.ping`
- ラップタイム・スプリットタイム
  - `.lapTimeMs`: 現在のラップのラップタイム (ミリ秒)
  - `.previousLapTimeMs`: 前のラップのラップタイム (ミリ秒)
  - `.bestLapTimeMs`: ベストラップのラップタイム (ミリ秒)
  - `.estimatedLapTimeMs`: 現在のラップ完了時の想定ラップタイム (ミリ秒)
  - `.currentSector`: 現在のセクターのインデックス
  - `.previousSectorTime`: 前のセクターのセクタータイム (ミリ秒)
  - `.currentSplits[]`: 現在のラップのスプリットタイム (ミリ秒) の配列
  - `.lastSplits[]`: 前のラップのスプリットタイム (ミリ秒) の配列
  - `.bestLapSplits[]`: ベストラップのスプリットタイム (ミリ秒) の配列
  - `.bestSplits[]`: スプリットごとのベストタイム (ミリ秒) の配列
- パフォーマンスデルタ
  - `.performanceMeter`: 現在のラップとベストラップを比較するパフォーマンスメーター (秒)
  - `.performanceMeterSpeedDifferenceMs`: 現在ラップとベストラップでのスピードの差
- 走行距離
  - `.distanceDrivenTotalKm`: 累計走行距離 (km)
  - `.distanceDrivenSessionKm`: セッション内での走行距離 (km)
  - `.drivenInRace`: レース内での走行距離 (m)
- ABS・TC等
  - `.absMode`: ABSレベル
  - `.absInAction`: ABSが起動中かどうか (boolean)
  - `.tractionControlMode`: TCのレベル
  - `.tractionControlInAction`: TCが起動中かどうか (boolean)
  - `.brakeBias`: ブレーキバイアス (0～1)
  - `.brakesBiasStep`
  - `.engineBrakeSettingsCount`
  - `.currentEngineBrakeSetting`
  - `.speedLimiter`
  - `.speedLimiterInAction`
  - `.userSpeedLimiterEnabled`
  - `.manualPitsSpeedLimiterEnabled`
- キャスター角
  - `.caster`
- DRS・KERS (回生システム)
  - `.drsPresent`
  - `.drsAvailable`
  - `.drsActive`
  - `.kersPresent`
  - `.kersHasButtonOverride`
  - `.kersButtonPressed`
  - `.kersCharge`
  - `.kersInput`
  - `.kersCurrentKJ`
  - `.kersMaxKJ`
  - `.kersLoad`
<!--
  - `.sessionID`: オンラインレースでの車のインデックス ( `.index` とは異なる)
  - `:id()`: 車両のフォルダ名
  - `.focused`: 注目中の車両かどうか (boolean)
- 車両情報
  - `.mass`: 車両重量 (kg)
  - `.tractionType`
  - `.restrictor`: リストリクター
  - `.ballast`: バラスト (kg)
- 車両設定
  - `.differentialPreload`
  - `.differentialCoast`
  - `.differentialPower`
  - `.awdFrontShare`
  - `.awdCenterLock`
- エアロ
  - `.aeroLiftFront`
  - `.aeroLiftRear`
  - `.aeroDrag`
- FFB (フォースフィードバック)
  - `.steerTorque`
  - `.ffbSteerAssist`
  - `.ffbBase`
  - `.ffbFinal`
  - `.ffbPure`
  - `.ffbMultiplier`
- ペナルティ
  - `.currentPenaltyType`
  - `.currentPenaltyParameter`
- スキン
  - `:skin()`: スキンのフォルダ名
-->

---

### ac.StateWheel

`ac.getCar(carIndex).wheels[]` で得られるオブジェクトのクラス

- ゲーム中に変化する情報
  - `.tyreWear`: タイヤの摩耗 (0～1)
  - `.tyreDirty`: タイヤの汚れ具合(0～1)
  - `.tyreVirtualKM`: タイヤごとの走行距離 (km)
- 温度
  - `.tyreCoreTemperature`: タイヤのコア温度 (℃)  
  - `.tyreInsideTemperature`: タイヤの内側 (車体側) の温度 (℃)  
  - `.tyreMiddleTemperature`: タイヤの中央の温度 (℃)  
  - `.tyreOutsideTemperature`: タイヤの外側 (路面側) の温度 (℃)  
  - `.tyreOptimumTemperature`: タイヤの最適温度 (℃)  
  - `.discTemperature`: ブレーキディスクの温度 (℃)  
  - `.temperatureMultiplier`
- 荷重やスリップ関係
  - `.slip`
  - `.slipAngle`: スリップアングル (degree) - タイヤの進行方向と実際の移動方向の角度差
  - `.slipRatio`: スリップ率 - タイヤの回転速度と実際の速度の比率
  - `.ndSlip`
  - `.load`: タイヤ荷重 (N)
  - `.tyreLoadedRadius`: 負荷時のタイヤ半径 (m)
  - `.speedDifference`: 接地点の速度差 (m/s)
  - `.suspensionTravel`: サスペンションストローク (m)
  - `.camber`: キャンバー角 (dgree)
  - `.toeIn`: トー角 (dgree) - トーインが正、トーアウトが負
- ダメージ
  - `.suspensionDamage`: サスペンションのダメージ
- 基本的な情報
  - `.tyreRadius`: タイヤの半径 (m)
  - `.tyreWidth`: タイヤの幅 (m)
  - `.rimRadius`: リムの半径 (m)
<!--
- ゲーム中に変化する情報
  - `.tyreGrain`: グレイニングの進行度 (0～1) - タイヤ表面の細かいささくれ
  - `.tyreBlister`: ブリスターの進行度 (0～1) - ゴムの膨れや剥離
  - `.tyreFlatSpot`: フラットスポットの度合い (0～1) - ロック時の摩耗
  - `.tyreStaticPressure`: 静的タイヤ空気圧 (kPa?) - 走行前の基準圧
  - `.tyrePressure`: 実際のタイヤ空気圧 (kPa?) - 走行中の変化を含む
- 荷重やスリップ関係
  - `.loadK`
  - `.angularSpeed`: 角速度
- 路面の情報
  - `.surfaceDirt`: ホイール下の路面の汚れ付加係数
  - `.waterThickness`: 水の厚さ (m)
  - `.surfaceSectorID`: ホイール下面の路面のセクターID
  - `.surfaceSectionIndex`: ホイールが乗っている路面に対応する "surface.ini "のセクションのインデックス
  - `.surfaceGrip`: ホイール下面の路面のグリップ
  - `.surfaceDamping`
  - `.surfaceGranularity`
  - `.surfaceVibrationGain`
  - `.surfaceVibrationLength`
  - `.surfacePitlane`: ホイールの下の路面がピットレーン内かどうか (boolean)
  - `.surfaceValidTrack`: ホイールの下の路面が有効なトラックかどうか (boolean)
  - `.isSpecialSurface`: この値が `true` の場合、スキッドオーディオを再生しない
  - `.surfaceType`: ビジュアルに使用される基本的なタイプヒント
- 位置や方向の情報
  - `.contactNormal`: 接点面の法線 (vec3)
  - `.contactPoint`: ワールド座標での接点位置 (vec3)
  - `.position`: ワールド座標でのタイヤの位置 (vec3)
  - `.look`
  - `.up`
  - `.outside`
  - `.velocity`
  - `.dx`
  - `.dy`
  - `.mz`: セルフアライニングトルク (Nm)
  - `.fx`
  - `.fy`
- `.transform`
- `.transformWheel`
- `.isBlown`
- `.isHot`
-->

---

### ac.StateSession

`ac.getSession(ac.getSim().currentSessionIndex)` などの返り値で得られるオブジェクトのクラス

- セッション情報
  - `.type`: セッションタイプ (Race, Qualify, Practice, Hotlapなど)
  - `.laps`: 合計ラップ数
  - `.isTimedRace`: 時間制限レースかどうか (boolean)
  - `.hasAdditionalLap`
  - `.leaderCompletedLaps`
  - `.isOver`
  - `.forcedPosition`
- 時間
  - `.durationMinutes`
  - `.startTime`
  - `.overtimeMs`
- リーダーボード
  - `.leaderboard[]`: クラス `ac.StateLeaderboardEntry` のオブジェクトの配列を返す

---

### ac.StateLeaderboardEntry

- `.car`: `ac.StateCar` クラスのオブジェクトを返す
- `.totalTimeMs`
- `.bestLapTimeMs`
- `.laps`: 現在のラップ数
- `.raceMode`
- `.blackFlagged`
- `.hasCompletedLastLap`

---

### ac.StateSim

`ac.getSim()` などの返り値で得られるオブジェクトのクラス

- セッション
  - `.currentSessionIndex`: セッションインデックス
  - `.sessionsCount`
  - `.isSessionStarted`: レース開始後かどうか
  - `.isSessionFinished`: レース終了後かどうか
  - `.raceSessionType`
  - `.timeToSessionStart`: レース開始までの時間 (ミリ秒)
  - `.sessionTimeLeft`
- レース情報
  - `.carsCount`: 車両数 (最低1)
  - `.closelyFocusedCar`: 車両のインデックス。フリーカメラ等でフォーカスがない場合は-1を返す
  - `.focusedCar`: 車両のインデックス。フリーカメラ等でフォーカスがない場合は-1を返す
  - `.raceFlagType`
  - `.raceFlagCause`
  - `.leaderLapCount`
  - `.isTimedRace`
  - `.leaderLastLap`
  - `.timeRaceEnded`
  - `.timeRaceLastLap`
  - `.timeRaceAdditionalLap`
- レース設定
  - `.allowTyreBlankets`: タイヤウォーマーON/OFF (boolean)
  - `.allowedTyresOut`
  - `.mechanicalDamageRate`
  - `.tyreConsumptionRate`
  - `.fuelConsumptionRate`
  - `.gravity`
  - `.customAISplinesAllowed`
  - `.penaltiesEnabled`
  - `.fixedSetup`
  - `.idealLineShown`
  - `.damageDisplayerShown`
  - `.driverNamesShown`
  - `.isPitsSpeedLimiterForced`
  - `.pitsSpeedLimit`
  - `.pitWindowStartTime`
  - `.pitWindowEndTime`
- コース
  - `.trackLengthM`: コースの長さ (m)
  - `.speedLimitKmh`
  - `.baseAltitude`
  - `.lapSplits[]`: トラックの分割点の正規化された位置
- 時間
  - `.timeTotalSeconds`: ゲーム内時間の 0:00 からの経過秒数 (小数点以下も含む)
  - `.timeHours`: ゲーム内時間の現在の時刻 (0～23, 小数点以下切り捨て)
  - `.timeMinutes`: ゲーム内時間の現在の分 (0～59, 小数点以下切り捨て)
  - `.timeSeconds`: ゲーム内時間の現在の秒 (0～59, 小数点以下切り捨て)
  - `.timeMultiplier`: ゲーム内時間の進行速度の倍率
  - `.timestamp`: 1970年1月1日 0:00:00 (UTC) からの経過秒数 (システムのタイムゾーンに基づく)
  - `.dayOfYear`: ゲーム内の日付 (1月1日を 1 とする, 1～365)
- ディスプレイ情報
  - `.windowWidth`
  - `.windowHeight`
  - `.windowHandle`
  - `.isWindowForeground`
- ゲームモード
  - `.isReplayOnlyMode`
  - `.isOnlineRace`
  - `.isShowroomMode`
  - `.isPreviewsGenerationMode`
  - `.freeCameraAllowed`
<!--
- 環境
  - `.neutralSunTrajectoryTimestamp`
  - `.isWeatherFXActive`
  - `.ambientTemperature`
  - `.roadTemperature`
  - `.roadGrip`
  - `.windSpeedKmh`
  - `.windVelocityKmh`
  - `.windDirectionDeg`
  - `.rainIntensity`
  - `.rainWetness`
  - `.rainWater`
  - `.weatherType`
  - `.weatherSkyOcclusion`
  - `.equinoxSunTrajectory`
  - `.explicitDateSet`
  - `.skyColor`
  - `.horizonColor`
  - `.fogColor`
  - `.lightColor`
  - `.lightDirection`
  - `.weatherConditions`
- 実績
  - `.specialEvent`
- 画面設定
  - `.isTripleMode`
  - `.isCustomVideoMode`
  - `.isTripleScreenAvailable`
- リプレイ
  - `.replayFrameMs`
  - `.replayFrames`
  - `.replayCurrentFrame`
  - `.replayPlaybackRate`
- 入力
  - `.inputMode`
  - `.needsDPad`
  - `.controlsWithShifter`
- グラフィック設定
  - `.msaaSamples`
  - `.worldDetailLevel`
  - `.isFullscreen`
  - `.isVSyncActive`
  - `.isPostProcessingActive`
  - `.staticReflections`
  - `.isFSRActive`
  - `.isTripleFSRActive`
  - `.isLinearColorSpaceActive`
- VR
  - `.isVRMode`
  - `.isOculusMode`
  - `.isOpenVRMode`
  - `.isVRConnected`
- システム
  - `.time`
  - `.gameTime`
  - `.systemTime`
  - `.frame`
  - `.dt`
  - `.isMakingScreenshot`
  - `.isPaused`
  - `.isInMainMenu`
  - `.isLookingAtSessionResults`
  - `.isLive`
  - `.isReplayActive`
  - `.fps`
  - `.fpsCapped`
  - `.physicsLate`
  - `.cpuOccupancy`
  - `.cpuTime`
- オンライン
  - `.directMessagingAvailable`
  - `.directUDPMessagingAvailable`
  - `.timeSinceLastUDPPacket`
  - `.connectedCars`
  - `.randomSeed`
  - `.handshakeServerTime`
  - `.currentServerTime`
  - `.currentSessionTime`
- OpenGL
  - `.currentVAOMode`
  - `.isVAOPatchLoaded`
- ライティング
  - `.ambientLightingMultiplier`
  - `.lightSuggestion`
- カメラ
  - `.cameraPosition`
  - `.cameraLook`
  - `.cameraUp`
  - `.cameraSide`
  - `.cameraFOV`
  - `.cameraClipNear`
  - `.cameraClipFar`
  - `.cameraDOFFactor`
  - `.cameraDOFFocus`
  - `.cameraExposure`
  - `.exposureMultiplier`
  - `.isFreeCameraOutside`
  - `.isFocusedOnInterior`
  - `.orbitOnboardCamera`
  - `.cameraJumped`
  - `.firstPersonCameraFOV`
  - `.cameraMode`
  - `.driveableCameraMode`
  - `.carCameraIndex`
  - `.trackCamerasSetsCount`
  - `.trackCamerasSet`
- オーディオ
  - `.audioMasterVolume`
- ミラー
  - `.isVirtualMirrorActive`
  - `.isVirtualMirrorForced`
- `.whiteReferencePoint`
- チャット
  - `.isAdmin`
  - `.sentAdminCommand`
-->

---

### ac

APIで提供されるグローバルオブジェクト

- 車両情報 ( `ac.StateCar` 型のオブジェクト) を返すメソッド
  - `.getCar(index)`: プレイヤー車両を0としたインデックスで指定
  - `.getCar.ordered(index)`: カメラに近い順にインデックスで指定
  - `.getCar.leaderboard(index)`: リーダーボードの順位の順でインデックスで指定
  - `.getCar.serverSlot(index)`: サーバーのエントリー順でインデックスで指定。オフラインモードでは `nil` を返す
- シム全体やセッションの情報
  - `.getSim()`
  - `.getSessionName(sessionIndex)`
  - `.getSession(index)`
  - `.getUI()`
- 汎用関数
  - `.lapTimeToString(time, allowHours)`: ラップタイム (ミリ秒) をテキスト `"mm:ss.ff"` に変換
  - `.getCountryName(nationCode)`: 国コードから国名を取得
  - `.getCarByDriverName(driverName)`: ドライバー名から車両のインデックスを取得
  - `.getGapBetweenCars(carMainIndex, carComparingToIndex)`: 車両のタイムギャップ (秒) を返す
  - `.getCompassAngle(dir)`: vec3データを角度 (degree) に変換。0は北、90は東
- コンフィグ系
  - `.INIConfig(format, sections)`
- 車両情報
  - `.getCarTags(carIndex)`
  - `.getCarGearLabel(carIndex)`
  - `.getCarOptimalBrakingAmount(carIndex)`
- コース情報
  - `.trackProgressToWorldCoordinate(v, linear)`: ラップ進行度 (0～1) をワールド座標に (vec3) 変換
  - `.trackProgressToWorldCoordinateTo(v, r, linear)`
  - `.worldCoordinateToTrackProgress(v)`: ワールド座標 (vec3) をラップ進行度 (0～1) に変換
  - `.worldCoordinateToTrack(v)`: ワールド座標 (vec3) を トラック座標 (vec3) に変換
  - `.trackCoordinateToWorld(v)`: トラック座標 (vec3) をワールド座標 (vec3) に変換
  - `.hasTrackSpline()`: AIスプラインを持っているかどうか
  - `.getTrackAISplineSides(v)`: ラップの進行度 (0～1) を引数とし、AIスプラインから左右のトラック境界までの距離を返す
  - `.getTrackCoordinatesDeg()`: コースの北緯と東経を返す
  - `.getTrackTimezoneBaseDst(time)`
  - `.getTrackSectorName(trackProgress)`: 現在のセクター名を返す
  - `.getRealTrackHeadingAngle()`
  - `.getTrackUpcomingTurn(carIndex)`: 次のコーナーまでの距離とコーナーの角度を返す
  - `.getTrackName()`: (JSONファイルに設定されている) トラック名を返す
  - `.getTrackID()`: コースのフォルダ名を返す
  - `.getTrackLayout()`: コースのレイアウトのフォルダ名を返す (コースのフォルダ名は含まない)
  - `.getTrackFullID(separator)`: コースのレイアウトのフォルダ名を返す (コースのフォルダ名を含む)
  - `.getTrackDataFilename(fileName)`: コースファイルのフルパスを返す
- カメラ
  - `.isInteriorView()`
  - `.isVisibleInMainCamera(pos, radius)`
  - `.getCameraPosition()`
  - `.getAltitude()`: カメラの海面高度 (m) を返す
  - `.getCameraFOV()`
  - `.distanceToRenderSquared(pos)`: メインカメラまでの距離の二乗を返す
  - `.distanceToRender(pos)`: メインカメラまでの距離を返す
  - `.closerToRenderThan(pos, distance)`: 位置が閾値よりもメインカメラに近い場合に `true` を返す
- 環境情報
  - `.getSunAngle()`
  - `.getSunPitchAngle()`
  - `.getSunHeadingAngle()`
  - `.getAirPressure(p)`
  - `.getAirHumidity(p)`
  - `.getWindVelocity()`
  - `.getWindVelocityTo(r)`
  - `.isWeatherFxActive()`
  - `.getSkyFeatureDirection(skyFeature, distance, time)`
  - `.getSkyStarDirection(declRad, rightAscRad)`
  - `.getConditionsTimeScale()`
  - `.getConditionsSet()`
  - `.getConditionsSetTo(r)`
- リプレイ
  - `.isInReplayMode()`
- コールバック
  - `.onTrackPointCrossed(carIndex, progress, callback)`
  - `.onSessionStart(callback)`
  - `.onResolutionChange(callback)`
  - `.onCarJumped(carIndex, callback)`
  - `.onTyresSetChange(carIndex, callback)`
  - `.onScreenshot(callback)`
- デバッグ
  - `.debug(key, value)`
  - `.console(message, withoutPrefix)`
  - `.log(...)`
<!--
- 汎用関数
  - `.getCarIndexInFront(carMainIndex, distance)`
- 環境情報
  - `.getMoonFraction()`
  - `.getSoundSpeedMs()`: 現在の環境での音速を返す
- コールバック
  - `.onControlSettingsChanged(callback)`
  - `.onClientConnected(callback)`
  - `.onClientDisconnected(callback)`
  - `.onFileChanged(filename, callback)`
  - `.onFolderChanged(folder, filter, recursive, callback)`
  - `.onTripleConfigurationChanged(callback)`
  - `.onCSPConfigChanged(cspModuleID, callback)`
- 入力
  - `.isKeyDown(keyIndex)`
  - `.isKeyPressed(keyIndex)`
  - `.isKeyReleased(keyIndex)`
  - `.getSessionSpawnSet(sessionIndex)`
  - `.forceVisibleHeadNodes(carIndex, force)`
  - `.isGamepadButtonPressed(gamepadIndex, gamepadButtonID)`
  - `.getGamepadAxisValue(gamepadIndex, gamepadAxisID)`
  - `.getJoystickCount()`
  - `.getJoystickName(joystick)`
  - `.getJoystickInstanceGUID(joystick)`
  - `.getJoystickProductGUID(joystick)`
  - `.getJoystickIndexByInstanceGUID(guid)`
  - `.getJoystickAxisCount(joystick)`
  - `.getJoystickButtonsCount(joystick)`
  - `.getJoystickDpadsCount(joystick)`
  - `.isJoystickButtonPressed(joystick, button)`
  - `.getJoystickAxisValue(joystick, axis)`
  - `.isJoystickAxisValue(joystick, axis)`
  - `.getJoystickDpadValue(joystick, dpad)`
  - `.isJoystickDpadValue(joystick, dpad)`
  - `.getPenPressure()`
  - `.getVR()`
  - `.getTrackIR()`
  - `.getCarPhysics(index)`
  - `.getDualSense(gamepadIndex)`
  - `.setDualSense(gamepadIndex, priority, holdFor)`
  - `.getDualShock(gamepadIndex)`
  - `.setDualShock(gamepadIndex, priority, holdFor)`
  - `.setXbox(gamepadIndex, priority, holdFor)`
- メディアプレイヤー
  - `.onAlbumCoverUpdate(callback)`
  - `.mediaNextTrack()`
  - `.mediaPreviousTrack()`
  - `.mediaPlayPause()`
- オンライン
  - `.getServerName()`
  - `.getServerIP()`
  - `.getServerPortHTTP()`
  - `.getServerPortTCP()`
  - `.getServerPortUDP()`
- 車両情報
  - `.iterateCars()`: プレイヤー車両を0としたインデックス順で配列で返す\
    以下のような使い方ができる
    ```lua
    for i, car in ac.iterateCars() do
      ac.debug(i, car.position)
    end
    ```
  - `.iterateCars.ordered(inverse)`: カメラに近い順で配列で返す。全車両が入るとは限らない
  - `.iterateCars.leaderboard()`: リーダーボードの順で配列で返す
  - `.iterateCars.serverSlots()`: サーバーのエントリー順で配列で返す
- 汎用関数
  - `.utf8To16(data)`
  - `.utf16To8(data)`
- デバッグ
  - `.warn(...)`
  - `.error(...)`
  - `.setMessage(title, description)`
  - `.setSystemMessage(title, description)`
  - `.setClipboardText(text)`
  - `.setLogSilent(value)`
  - `.clearDebug(filter)`
- オーディオ
  - `.getAudioVolume(audioChannelKey, carIndex, fallbackValue)`
  - `.getAudioOutputDevice()`
- タイヤ情報
  - `.getTyresName(carIndex, compoundIndex)`
  - `.getTyresIndex(carIndex, tyresShortName)`
- ファイル
  - `.dirname()`: スクリプトのフォルダ名を返す
  - `.findFile(fileName)`
  - `.getFolder(folderID)`
  - `.readDataFile(filename)`: "data.acd "内のファイルにアクセスし、例えば車のスペックを読むのに使用できる
- システム
  - `.uniqueMachineKeyAsync(callback)`: 個々のPCに固有のキーを返す (プロセッサーとマザーボードのシリアル番号を使用)
  - `.getDeltaT()`
  - `.getGameDeltaT()`
  - `.getScriptDeltaT()`
- CSP
  - `.getPatchVersion()`
  - `.getPatchVersionCode()`
  - `.getPpFilter()`
- パフォーマンス計測
  - `.perfBegin(value)`: 時間を計測してパフォーマンスを分析するためのシンプルなヘルパー
  - `.perfEnd(value)`
  - `.perfFrameBegin(value)`
  - `.perfFrameEnd(value)`
- 時間
  - `.getTrackDateTime()`
  - `.getTimeZoneOffset()`
  - `.getTimeZoneDstOffset()`
  - `.getTimeZoneBaseOffset()`
- 修復
  - `.refreshCarShape(carIndex)`
  - `.refreshCarColor(carIndex)`
  - `.updateDriverModel(carIndex, forceVisible)`
- `.getDriverHeadTransformTo(ret, carIndex)`
- `.blockSystemMessages(regex)`
- `.isLuaAppRunning(appID)`
- `.storageSetPath(relativePath, prefix)`
- `.broadcastSharedEvent(key, data)`
- `.onSharedEvent(key, callback, processPostponed)`
- `.onLuaScriptDisposal(callback)`
- `.setVRHandBusy(hand, busy)`
- `.setVRHandVibration(hand, frequency, amplitude, duration)`
- `.isModuleActive(cspModuleID)`
- `.getPerformanceCPUAndGPUTime()`
- `.mediaCurrentPeak(output)`
- `.setTextureKey(key)`
- `.encodeTexture(filename, outputFilename, key, applyLz4Compression)`
- `.getTripleConfiguration()`
-->
---

### ui

- プロパティ
  - `.windowSize`
  - `.mousePos`
  - `.dt`: 前の命令呼び出しからの秒数 (ミリ秒)
- カーソル: テキストやウィジェットの表示位置を指定
  - `.getCursor()`, `.getCursorX()`, `.getCursorY()`
  - `.getMaxCursorX()`. `.getMaxCursorY()`
  - `.setCursor(v)`, `.setCursorX(v)`, `.setCursorY(v)`
  - `.setMaxCursorX(v)`, `.setMaxCursorY(v)`
  - `.offsetCursor(v)`, `.offsetCursorX(v)`, `.offsetCursorY(v)`
  - `.backupCursor()`
  - `.restoreCursor()`
  - `.sameLine(offsetFromStart, spacing)`
  - `.newLine(spacing)`
  - `.indent(indentW)`
  - `.unindent(indentW)`
  - `.cursorStartPos()`
  - `.cursorScreenPos()`
  - `.setCursorScreenPos(pos)`
- テキストの描画
  - `.text(text)`: カーソル位置にテキストを描画
  - `.textAligned(text, alignment, size, ellipsis)`
  - `.textHyperlink(text, hyperlinkColor)`
  - `.textWrapped(text, wrapPos)`
  - `.textColored(text, color)`
  - `.textDisabled(text)`
  - `.bulletText(text)`
  - `.pushFont(fontType)`, `.popFont()`
  - `.setNextTextBold()`
  - `.measureText(text, wrapWidth)`
  - `.acText(text, letter, marginOffset, color, lineSpace, monospace)`
  - `.calculateACTextSize(text, letter, marginOffset, lineSpace, monospace)`
  - `.pushACFont(name)`, `.popACFont()`
  - `.dwriteText(text, fontSize, color)`
  - `.dwriteTextHyperlink(text, fontSize, hyperlinkColor)`
  - `.dwriteTextWrapped(text, fontSize, color)`
  - `.dwriteTextAligned(text, fontSize, horizontalAligment, verticalAlignment, size, allowWordWrapping, color)`
  - `.pushDWriteFont(name)`, `.popDWriteFont()`: 囲った範囲のフォントを変更する
    - システムフォントを使用する際は、`"Arial:@System;Weight=Bold;Style=Italic"` などの指定方法をする
    - `.ttf` 形式のフォントを同梱する際は `"fontName:fontFilePath"` とパス (相対パス) を指定
  - `.measureDWriteText(text, fontSize, wrapWidth)`
- アイコンの描画
  - `.icon(iconID, size, tintCol, iconSize)`
  - `.addIcon(iconID, size, alignment, colorOpt, padding)`
  - `.icon24(iconID, size, tintCol)`
  - `.icon32(iconID, size, tintCol)`
  - `.icon64(iconID, size, tintCol)`
  - `.flag(iconID, size, tintCol)`
  - `.isKnownIcon24(iconID)`
- 画像の描画
  - `.drawImage(imageSource, p1, p2, color, uv1, uv2, mode)`
  - `.drawIcon(iconID, p1, p2, color)`
  - `.drawLoadingSpinner(p1, p2, color)`
  - `.drawImageRounded(imageSource, p1, p2, color, uv1, uv2, rounding, corners)`
  - `.drawImageQuad(imageSource, p1, p2, p3, p4, color, uv1, uv2, uv3, uv4)`
  - `.drawQuadFilled(p1, p2, p3, p4, color)`
  - `.drawQuad(p1, p2, p3, p4, color)`
  - `.beginTextureShade(imageSource)`, `.endTextureShade(p1, p2, uv1, uv2, clamp)`
  - `.pushClipRect(p1, p2, intersectWithExisting)`, `.popClipRect()`
  - `.pushClipRectFullScreen()`
  - `.imageSize(imageSource)`
  - `.imageState(imageSource)`
  - `.isImageReady(imageSource)`
  - `.unloadImage(imageSource)`
  - `.decodeImage(data)`
  - `.drawDriverIcon(carIndex, pos, useCustomIcon)`
- 図形の描画
  - `.drawRect(p1, p2, color, rounding, roundingFlags, thickness)`: 始点 (vec2), 終点 (vec2) を指定しての描画
  - `.drawRectFilled(p1, p2, color, rounding, roundingFlags)`
  - `.drawRectFilledMultiColor(p1, p2, colorTopLeft, colorTopRight, colorBottomRight, colorBottomLeft)`
  - `.drawLine(p1, p2, color, thickness)`
  - `.drawSimpleLine(p1, p2, color, thickness)`
  - `.drawBezierCurve(p1, p2, p3, p4, color, thickness)`
  - `.drawCircle(p1, radius, color, numSegments, thickness)`
  - `.drawCircleFilled(p1, radius, color, numSegments)`
  - `.drawEllipseFilled(p1, radius, color, numSegments)`
  - `.drawTriangle(p1, p2, p3, color, thickness)`
  - `.drawTriangleFilled(p1, p2, p3, color)`
- パスの描画
  - `.pathClear()`
  - `.pathLineTo(pos)`
  - `.pathLineToMergeDuplicate(pos)`
  - `.pathFillConvex(color)`
  - `.pathStroke(color, closed, thickness)`
  - `.pathSimpleStroke(color, closed, thickness)`
  - `.pathSmoothStroke(color, closed, thickness)`
  - `.pathArcTo(center, radius, angleFrom, angleTo, numSegments)`
  - `.pathUnevenArcTo(center, radius, angleFrom, angleTo, numSegments)`
  - `.pathVariableArcTo(center, radiusFrom, radiusTo, angleFrom, angleTo, numSegments)`
  - `.pathArcToFast(center, radius, angleMinOf_12, angleMaxOf_12)`
  - `.pathBezierCurveTo(p1, p2, p3, numSegments)`
  - `.pathRect(rectMin, rectMax, rounding, roundingCorners)`
- テキストの描画
  - `.drawText(text, pos, color)`
  - `.dwriteDrawText(text, fontSize, pos, color)`
  - `.drawTextClipped(text, posMin, posMax, color, alignment, ellipsis)`
  - `.dwriteDrawTextClipped(text, fontSize, posMin, posMax, horizontalAligment, verticalAlignment, allowWordWrapping, color)`
- その他描画
  - `.drawVirtualMirror(p1, p2)`
- 描画される要素の加工
  - `.beginRotation()`: これと .endRotation() または .endPivotRotation() で囲った範囲を回転
  - `.endRotation(deg, offset)`: 要素の中心を軸にして回転
  - `.endPivotRotation(deg, pivot, offset)`: 軸を指定して回転
  - `.beginScale()`: これと .endScale() または .endPivotScale() で囲った範囲を拡大縮小
  - `.endScale(scale)`: 要素の中心を中心にして拡大縮小
  - `.endPivotScale(scale, pivot)`: 中心を指定して拡大縮小
  - `.beginTransformMatrix()`, `.endTransformMatrix(mat)`
  - `.beginOutline()`, `.endOutline(color, scale)`: 囲った範囲の要素のアウトラインを描画
  - `.beginGradientShade()`, `.endGradientShade(p1, p2, col1, col2, useAlpha)`
  - `.pushStyleVar(varID, value)`, `.popStyleVar()`
  - `.pushStyleColor(varID, color)`, `.popStyleColor(count)`
  - `.pushStyleVarAlpha(alpha)`, `.popStyleVar()`
  - `.pushAlignment(vertical, alignment)`, `.popAlignment()`
- ウィジェット
  - `.header(text)`: 見出し
  - `.labelText(label, text)`
  - `.copyable(label)`
  - `.selectable(label, selected, flags, size)`
  - `.button(label, size, flags)`
  - `.smallButton(label)`
  - `.checkbox(label, checked)`: チェックボックス
  - `.radioButton(label, checked)`: ラジオボタン
  - `.slider(label, value, min, max, format, power)`: スライダー
  - `.progressBar(fraction, size, overlay)`: プログレスバー
  - `.menuItem(label, selected, flags, shortcut)`
  - `.separator()`: 区切り線を引く
  - `.image(imageSource, size, color, borderColor, uv1, uv2, mode)`
  - `.imageButton(imageSource, size, bgColor, color, uv1, uv2, framePadding, mode)`
  - `.iconButton(iconID, size, color, bgColor, framePadding, uv1, uv2, keepAspectRatio, flags)`
  - `.dummy(size)`
- ウィジェットのグルーピング
  - `.tabBar(id, content)`
  - `.tabItem(label, content)`
    - Tabの使い方: 以下のようにcontentの関数内で内容を描画させる。他も同様。
    ```lua
    ui.tabBar("tabBar1", function()
      ui.tabItem("Tab 1", function()
        ui.text("content")
      end)
    end)
    ```
  - `.treeNode(label, content)`: 上と同様
  - `.combo(label, previousValue, content)`: コンボボックス
  - `.childWindow(id, size, border, content)`
  - `.popup(content)`
  - `.setTooltip(tooltip)`
  - `.tooltip(content)`
  - `.setDriverTooltip(carIndex)`
  - `.setDriverPopup(id, carIndex)`
- クリップボード
  - `.getClipboardText()`
  - `.setClipboardText(text)`
<!--
- `.modalPopup(title, msg, okText, cancelText, okIconID, cancelIconID, callback)`
- `.modalDialog(title, callback, autoclose, closeCallback)`
- `.modalPrompt(title, msg, defaultValue, okText, cancelText, okIconID, cancelIconID, callback)`
- `.projectPoint(pos, considerUiScale)`
- `.mentionDriverInChat(carIndex, autofocus)`
- コールバック
  - `.onUIFinale(callback)`
  - `.onChat(callback, settingsCallback)`
  - `.onExclusiveHUD(callback)`
- `.setScrollFromPosX(localX, centerXRatio)`
- `.setScrollFromPosY(localY, centerYRatio)`
- `.time()`
- `.frameCount()`
- `.fontSize()`
- `.fontWhitePixelUV()`
- `.frameHeight()`
- `.frameHeightWithSpacing()`
- `.textLineHeight()`
- `.textLineHeightWithSpacing()`
- `.alignTextToFramePadding()`
- `.pushAllowKeyboardFocus(allowKeyboardFocus)`, `.popAllowKeyboardFocus()`
- `.pushButtonRepeat(repeatValue)`, `.popButtonRepeat()`
- `.setAsynchronousImagesLoading(value)`
- `.setForcedImagesCaching(value)`
- `.setExtraContentMark(active)`
- `.setTitleBarContentHint(marginLeft, marginRight)`
- `.notificationCounter(counter, pos, noclip)`
- アイテム
  - `.itemRectSize()`
  - `.itemRectMin()`
  - `.itemRectMax()`
  - `.setNextItemWidth(width)`
  - `.setNextItemIcon(iconID, color, relativePadding)`
  - `.modernMenuItem(label, iconID, selected, flags, childItem)`
  - `.itemHovered(flags)`
  - `.itemClicked(mouseButton, buttonBehaviour)`
  - `.itemActive()`
  - `.itemFocused()`
  - `.itemVisible()`
  - `.itemEdited()`
  - `.itemActivated()`
  - `.itemDeactivated()`
  - `.itemDeactivatedAfterEdit()`
  - `.anyItemHovered()`
  - `.anyItemActive()`
  - `.anyItemFocused()`
  - `.getItemRectMin()`
  - `.getItemRectMax()`
  - `.getItemRectSize()`
  - `.setItemAllowOverlap()`
  - `.itemToggledSelection()`
  - `.calcItemWidth()`
  - `.itemHyperlink(hyperlinkColor)`
  - `.pushItemWidth(itemWidth)`, `.popItemWidth()`
  - `.setItemDefaultFocus()`
- ウィジェット
  - `.bullet()`
  - `.arrowButton(strID, dir, size, flags)`
  - `.invisibleButton(label, size)`
  - `.configureStyle(accentColor, brightTheme, roundedCorners, bgAlpha)`
  - `.thinScrollbarBegin(appearOnHover)`, `.thinScrollbarEnd()`
  - `.modernButton(label, size, flags, icon, iconSize, iconBg)`
  - `.itemPopup()`
- ウィジェットのグルーピング
  - `.beginPopupContextItem(id, mouseButton)`
  - `.beginTreeNode(label, flags)`, `.endTreeNode()`
  - `.beginMenu(id, selected, enabled, shortcut)`, `.endMenu()`
  - `.openPopup(id)`, `.closePopup()`
  - `.beginPopup(id, flags, padding, opened)`, `.endPopup()`
  - `.beginTooltip(padding)`, `.endTooltip()`
  - `.beginCombo(label, previewValue, flags)`, `.endCombo()`
  - `.beginChild(id, size, border, flags)`, `.endChild()`
  - `.beginGroup(width)`, `.endGroup()`
- キー入力
  - `.keyboardButtonDown(keyIndex)`
  - `.keyboardButtonPressed(keyIndex, withRepeat)`
  - `.keyboardButtonReleased(keyIndex)`
  - `.setKeyboardButtonDown(keyIndex)`
  - `.keyPressed(keyCode)`
  - `.keyPressedAmount(keyIndex, repeatDelay, rate)`
  - `.getKeyIndex(keyCode)`
  - `.hotkeyCtrl()`
  - `.hotkeyAlt()`
  - `.hotkeyShift()`
- マウス状態
  - `.mousePos()`
  - `.mouseLocalPos()`
  - `.mouseDelta()`
  - `.mouseWheel()`
  - `.mouseClicked(mouseButton)`
  - `.mouseDoubleClicked(mouseButton)`
  - `.mouseReleased(mouseButton)`
  - `.mouseDown(mouseButton)`
  - `.mouseBusy()`
  - `.isAnyMouseDown()`
  - `.isMouseReleased(mouseButton)`
  - `.isMouseDragging(mouseButton, lockThreshold)`
  - `.mousePosOnOpeningCurrentPopup()`
  - `.mouseDragDelta(mouseButton, lockThreshold)`
  - `.resetMouseDragDelta(mouseButton)`
  - `.mouseCursor()`
  - `.setMouseCursor(type)`
  - `.captureMouse(wantCaptureMouseValue)`
- ID
  - `.popID()`
  - `.getLastID()`
  - `.getActiveID()`
  - `.getFocusID()`
  - `.getHoveredID()`
  - `.clearActiveID()`
  - `.activateItem(id)`
  - `.loadStoredNumber(id, defaultValue)`
  - `.loadStoredBool(id, defaultValue)`
  - `.storeNumber(id, value)`
  - `.storeBool(id, value)`
- カラム
  - `.columns(columns, border, id)`
  - `.nextColumn()`
  - `.setColumnWidth(columnIndex, width)`
  - `.getColumnWidth(columnIndex)`
  - `.pushColumnsBackground()`, `.popColumnsBackground()`
  - `.columnSortingHeader(title, orderDirection, alignRight)`
- `.pushDisabled()`, `.popDisabled()`
- `.setShadingOffset(brightness, offset, alphaMult, alphaOffset)`
- `.resetShadingOffset()`
- 情報
  - `.availableSpaceX()`
  - `.availableSpaceY()`
  - `.availableSpace()`
- スクロール状態
  - `.getScrollX()`
  - `.getScrollY()`
  - `.getScrollMaxX()`
  - `.getScrollMaxY()`
  - `.setScrollX(scrollX, relative, smooth)`
  - `.setScrollY(scrollY, relative, smooth)`
  - `.setScrollHereX(centerXRatio)`
  - `.setScrollHereY(centerYRatio)`
- ウィンドウ状態
  - `.windowHovered(flags)`
  - `.windowFocused(flags)`
  - `.windowResizing()`
  - `.windowScrolling()`
  - `.windowPinned()`
  - `.windowPos()`
  - `.windowContentSize()`
  - `.windowContentExplicitSize()`
  - `.isWindowAppearing()`
  - `.isWindowCollapsed()`
  - `.isWindowFocused(flags)`
  - `.setNextWindowPosition(pos, pivot)`
  - `.setNextWindowSize(size)`
  - `.setNextWindowSizeConstraints(sizeMin, sizeMax)`
  - `.setNextWindowContentSize(size)`
  - `.beginToolWindow(windowID, pos, size, noPadding, inputs)`, `.endToolWindow()`
  - `.beginTransparentWindow(windowID, pos, size, noPadding, inputs)`, `.endTransparentWindow()`
  - `.bringWindowToFront()`
  - `.applyTransformationToWindows(active)`
- ウィンドウ状態
  - `.windowSize()`
  - `.windowWidth()`
  - `.windowHeight()`
- `.setKeyboardFocusHere(offset)`
- `.deltaTime()`
- `.addInputCharacter(keyIndex)`
- `.clearInputCharacters()`
- `.areaVisible(size)`
- `.areaVisibleY(height)`
- `.rectVisible(p1, p2)`
- `.rectHovered(p1, p2, clip)`
- `.pushTextWrapPosition(wrapPos)`, `.popTextWrapPosition()`
- `.styleColor(varID, styleSet)`
- `.glowRectFilled(p1, p2, color, noClip)`
- `.glowCircleFilled(p1, radius, color, noClip)`
- `.glowEllipseFilled(p1, radius, color, noClip)`
- `.getDrawCommandsCount()`
- プロパティ
  - `.mouseWheel`
  - `.isMouseLeftKeyClicked`
  - `.isMouseMiddleKeyClicked`
  - `.isMouseRightKeyClicked`
  - `.isMouseLeftKeyDoubleClicked`
  - `.isMouseMiddleKeyDoubleClicked`
  - `.isMouseRightKeyDoubleClicked`
  - `.isMouseLeftKeyDown`
  - `.isMouseMiddleKeyDown`
  - `.isMouseRightKeyDown`
  - `.metricsRenderVertices`
  - `.metricsRenderIndices`
  - `.metricsRenderWindows`
  - `.metricsActiveWindows`
  - `.metricsRenderCommands`
  - `.wantCaptureMouse`
  - `.wantCaptureKeyboard`
  - `.vrController`
  - `.appsHidden`
  - `.uiHidden`
  - `.framerate`
  - `.mouseDelta`
  - `.uiScale`
  - `.accentColor`
  - `.currentDesktop`
  - `.ctrlDown`
  - `.shiftDown`
  - `.altDown`
  - `.superDown`
- 描画されるイメージの加工
  - `.beginSharpening()`, `.endSharpening(sharpening)`
  - `.beginMIPBias()`, `.endMIPBias(bias, useBicubic)`
  - `.beginBlurring()`, `.endBlurring(blurring)`
  - `.beginSubtraction()`, `.endSubtraction()`
  - `.beginTonemapping()`, `.endTonemapping(gamma, whitePoint, lcsAware)`
  - `.beginTextureSaturationAdjustment()`, `.endTextureSaturationAdjustment(value)`
  - `.beginPremultipliedAlphaTexture()`, `.endPremultipliedAlphaTexture()`
-->

<!--
---

### math

---

### string

---

### table

- `table.isArray(t)`
- `table.clear(t)`
- `table.nkeys(t)`
- `table.clone(t, deep)`
- `table.removeItem(t, item)`
- `table.getOrCreate(t, key, callback, callbackData)`
- `table.contains(t, item)`
- `table.random(t, filteringCallback, filteringCallbackData, randomDevice)`
- `table.indexOf(t, item)`
- `table.same(t1, t2, deep)`
- `table.join(t, itemsJoin, keyValueJoin, toStringCallback, toStringCallbackData)`
- `table.slice(t, from, to, step)`
- `table.reverse(t)`
- `table.flatten(t, maxLevel)`
- map系
  - `table.map(t, callback, callbackData)`
  - `table.reduce(t, startingValue, callback, callbackData)`
  - `table.filter(t, callback, callbackData)`
  - `table.every(t, callback, callbackData)`
  - `table.some(t, callback, callbackData)`
  - `table.count(t, callback, callbackData)`
  - `table.sum(t, callback, callbackData)`
  - `table.findFirst(t, callback, callbackData)`
  - `table.maxEntry(t, callback, callbackData)`
  - `table.minEntry(t, callback, callbackData)`
  - `table.forEach(t, callback, callbackData)`
  - `table.distinct(t, callback, callbackData)`
  - `table.findLeftOfIndex(t, testCallback, testCallbackData)`
  - `table.range(endingIndex, startingIndex, step, callback, callbackData)`
- `table.new(arrayElements, mapElements)`
- `table.findByProperty(t, key, value)`
- `table.assign(target, ...)`
- `table.build(iterator, k, v)`
- `table.chain(table, ...)`
-->