Repository navigation
HUD Shared Core
HUD style 是可替換的視覺層;資料接收、單位整理、frame pacing、生命週期和跨 iframe 傳送則由 shared core 統一處理。本頁說明這些共用模組的維護邊界。樣式實作請看 HUD 開發指引,共用卡片請看 HUD Telemetry Cards。
| 模組 | 主要責任 | 維護時的重點 |
|---|---|---|
shared/ws.js |
連接 /ws/telemetry 與 /ws/overlay、重連、轉發事件 |
不要讓每個 HUD iframe 各自連線 |
shared/coordinator.js |
整理 canonical telemetry、單位、紅線、session maxima、lockup | 任何欄位改動都要同步所有 consumer |
shared/frame-interpolator.js |
以 timestamp 在渲染時間點插值連續/角度/陣列資料 | 只對適合插值的欄位使用,離散狀態不可誤插值 |
shared/hud-core.js |
style registry、config/elements/frame/audio/media dispatch、scale、destroy | Core 是 iframe 內唯一的 style lifecycle authority |
shared/overlay-forwarding.js |
將高頻 audio/media 更新排程後送入 HUD | 控制轉送頻率,避免 postMessage 風暴 |
shared/overlay-dedupe.js |
以序號或 media fingerprint 去除重複事件 | 不可吞掉真正變更的媒體狀態 |
shared/hud-base.css |
root wrapper、字型、透明視窗與共用佈局 | 不要在 style 內破壞外層定位契約 |
shared/telemetry-cards.js |
對外 re-export manager、template、cards、utils | 詳細資料契約見獨立卡片頁 |
sequenceDiagram
participant B as Backend
participant W as shared/ws.js
participant C as coordinator
participant H as launcher host
participant I as HUD iframe
participant K as HUDCore
B->>W: /ws/telemetry
W->>C: telemetry event
C->>H: hud:frame
H->>I: postMessage(hud:frame)
I->>K: handleMessage
K->>I: activeStyle.onFrame(data, payload)
B->>W: /ws/overlay
W->>H: hud:config/audio/media/animate
H->>I: postMessage(event)
K->>I: dispatch corresponding hook
hud_overlay/index.html 是 host。它初始化共用卡片、接收 BroadcastChannel horizon_tuner_hud_channel 的控制訊息、依 /api/hud/styles 建立 style URL,然後把事件送到目前的 iframe。一般 style 不應直接改這個 host;需要新增共用協定時才修改,並先確認所有樣式仍可載入。
coordinator 將原始 UDP packet 保留在輸出物件中,同時提供 style 可直接使用的語意欄位:
| 類別 | 欄位例子 | 說明 |
|---|---|---|
| 時間/車輛 |
timestamp_ms、carOrdinal、isRaceOn
|
frame 時間與車輛切換判斷 |
| 引擎/速度 |
rpm、maxRpm、idleRpm、redlineRpm、speed、speed_kmh、speed_mph、gear
|
由 raw 欄位整理,紅線基準為 maxRpm - 1000
|
| 動力 |
power、power_hp、power_kw、power_ps、torque、torque_nm、torque_ftlbs
|
依 displayUnits 提供顯示值與原始換算值 |
| 增壓 |
boost、boost_psi、boost_bar、boost_kpa、boost_unit
|
非負值並依設定選擇顯示單位 |
| 輸入 |
throttle、brake、clutch、hand_brake、steer
|
油門/煞車/離合器為 0 到 1,方向盤保留輸入語意 |
| 四輪 |
TireTemp、tire_temp_f、slip_fl 等、slip_angle_fl 等、susp_fl 等 |
固定 FL/FR/RL/RR 順序 |
| 動態 |
accel_x/y/z、vel_x/y/z、heading_deg、pos_x/y/z
|
G-force、漂移、Live Map 等使用 |
| 衍生狀態 |
sessionMaxima、lockup、lcState
|
coordinator 統一計算,style 不要另做第二版本 |
coordinator 讀取 window._currentHudConfig.effectiveUnits,再依 speed、power、torque、boostPressure 決定顯示值。樣式應使用 data.displayUnits、對應的 *_unit 和已轉換欄位,不要看到 raw PowerWatts 就在每個頁面各自換算。胎溫的共用 raw 顯示基準是華氏;要顯示攝氏時使用共用 helper 或明確的單位轉換。
-
redlineRpm由EngineMaxRpm減去 1000 得到;視覺上的弧線、分段或 sprite mapping 可以不同,但基準應相同。 -
sessionMaxima追蹤 power、torque、boost;換車時會重置 baseline,避免新車沿用舊車峰值。 -
lockup以煞車比例與各輪 slip ratio 判斷,提供fl、fr、rl、rrboolean;Advanced 等 HUD 可直接使用。
coordinator 會把收到的 telemetry sample 推入 FrameInterpolator,再在 render loop 以 performance.now() 取出當下 frame。連續數值可 lerp,角度使用 degree-aware interpolation,陣列依欄位規則處理;檔位、race state 等離散資料不可當作連續數值平滑。
控制面板的 enableSmoothing 會切換 coordinator 的 frame smoothing。style 若要做自己的視覺平滑,應保存小型 state,在 render loop 中 lerp,並於 hud:destroy 清理;不要深拷貝整個 telemetry 或把每個 hook 都變成一個獨立 timer。
HUDCore.registerStyle('my_style', {
containerId: 'myStyleContainer',
scaleMultiplier: 1.0,
onInit: function (payload) {},
onElementsChange: function (elements) {},
onFrame: function (data, payload) {},
onAudio: function (data) {},
onMedia: function (data) {},
onAnimate: function () {},
onScale: function (scale) {}
});
HUDCore.init('my_style');收到訊息後,Core 的責任是:
-
hud:config更新window._currentFullConfig、色彩/glow CSS variables 和 elements; -
hud:elements呼叫onElementsChange; -
hud:frame將data和共用payload傳給onFrame; -
hud:audio、hud:media分別傳給選填 hook; -
hud:init呼叫onInit,hud:animate呼叫onAnimate; -
hud:set-scale計算scaleBaseline * scaleMultiplier * userScale,一般情況只更新containerId的 zoom; -
hud:reload/hud:destroy清理 style 與 TelemetryCardsManager,避免 listener/animation loop 殘留。
style 只有在內部 Canvas、字型或 layout 需要跟著最終 scale 做額外處理時才提供 onScale。外層定位由 .hud-root-wrapper 控制,不要把 scale 和螢幕座標分散在各樣式。
| 訊息 | 方向 | 資料 | 典型用途 |
|---|---|---|---|
hud:frame |
coordinator → host → iframe |
data + redlineRpm、sessionMaxima、lockup 等 |
60Hz 車況 |
hud:config |
control/backend → host → iframe | 完整 overlay config | style、色彩、單位、卡片設定 |
hud:elements |
control → iframe | elements map | 顯示開關 |
hud:audio |
overlay WS → host → iframe | 32-band spectrum、VU、success | VFD/音訊視覺化 |
hud:media |
overlay WS → host → iframe | title、artist、status、success | 媒體文字/狀態 |
hud:animate |
control → host → iframe | 無或少量 payload | 啟動 sweep |
hud:set-scale |
control → iframe | user scale | 動態 zoom |
hud:reload / hud:destroy
|
host → iframe | style lifecycle | 切換或關閉 |
增加訊息時,至少同步更新 sender、host relay、Core handler、型別/測試與本頁。高頻事件應經 overlay-forwarding 排程,能以 sequence/fingerprint 去重時先去重;不可為了方便在每個 style 直接輪詢 API。
遇到所有 HUD 同時停止,先查 backend WebSocket、ws.js 與 coordinator;只有單一 style 異常才查該 style 的 hook、Canvas、asset 和 DOM。遇到畫面持續累積或 CPU 上升,檢查:
- style 切換後是否仍有舊的
messagelistener; -
requestAnimationFrame是否重複啟動; - audio/media 是否有第二條 WebSocket 或未去重的轉送;
- card history 是否在 disconnect/paused 後清理;
-
onFrame是否執行 deep copy、建立 DOM 或呼叫昂貴 API。
修改 shared core 後,至少做 syntax/test、連線中斷重連、切換 style、切換單位、Launch/Reload/Destroy 多次、10 個內建 HUD 的 smoke test。若改動 canonical 欄位,還要更新 HUD Telemetry Cards 與 HUD 樣式參考 的相關欄位說明。
shared/ws.jsshared/coordinator.jsshared/frame-interpolator.jsshared/hud-core.jsshared/overlay-forwarding.jsshared/overlay-dedupe.jshud_overlay/index.html
Shared Core owns transport, canonical telemetry, interpolation, iframe messaging, style lifecycle, and cleanup. Styles should consume hud:frame and common config rather than opening their own WebSocket or recalculating units, redline, maxima, or lockup. Changes to a shared event or canonical field require checking the host, HUDCore, all built-in styles, tests, and the related Wiki pages.
Shared Core は通信、canonical telemetry、補間、iframe メッセージ、スタイルのライフサイクル、後片付けを担当します。各スタイルは独自 WebSocket を開いたり、単位・レッドライン・最大値・ロックアップを再計算したりせず、hud:frame と共通設定を使用してください。共通イベントや canonical field を変更した場合は host、HUDCore、全内蔵スタイル、テスト、関連 Wiki を確認します。
FH6-HorizonTuner Wiki · v1.6.1 已發布 Rust backend / MCP Beta · PR #443(Rust hardening、Agent CLI、Python runtime retirement)尚未合併或發布 · Repository · Releases