Files
benilla-octo/crates/benilla-app/assets/ui/CinematicFrame.xml
T
SamandClaude Fable 5 d7fb26713c cinematics play, and a lit particle stops brightening as you turn
- cinematics play: `SMSG_TRIGGER_CINEMATIC` resolves through `CinematicSequences.dbc` → `CinematicCamera.dbc` → a `Cameras\*.m2` whose camera record is an eye path, a look-at path and a roll — cubic tracks with the full step / linear / Bézier / Hermite dispatch the bone loops collapse to step-or-linear (every shipped fly-by is Bézier), planted at the row's origin and facing (`Rz(+facing)`, checked against vmangos's own waypoint table: 8.5 yd mean on the human path, 154 with the other sign); FOV is per shot (the Undead intro authors 90°, the rest 45°), roll is authored around whole turns, the flight ends at the sequence band's end, a trigger arriving before the loading cover lifts is latched and started when it does, ESC skips through `CinematicFrame`'s own `OnKeyDown` (`StopCinematic` has zero native callers), and every path acks — natural end, ESC, or an unresolvable trigger immediately, as before; `.debug play cinematic <id>` replays any of them
- a cinematic hides the HUD — `UIParent:Hide()` reaches nothing here because the HUD frames are not its children, so the ALT-Z draw-level hide is used and the letterbox moves out of FrameXML onto Bevy UI nodes where that hide cannot reach it, recomputed per frame (bars only wider than 4:3, the picture cropped to 2:1) — and the restore only un-hides a UI this module hid
- a lit particle's normal is world up, one constant per draw, not camera-facing: Onyxia's always-on floor haze read about four times brighter from a level camera than from above because the shader dotted a to-eye normal against a fixed light; the reference uploads row 2 of the view matrix — world +Z carried into eye space — on every vertex and carries the light into the same frame, so the rotation cancels; 400 lit emitters (the waterfalls, chimney and campfire smoke, Westfall dust, Dun Morogh snow) stop brightening and dimming as you turn
- the `play` profile drops ThinLTO — rustc #86049 was intermittently poisoning the incremental link with `_anon.<hash>.llvm.<id>` symbols promoted by an earlier compile (48 unresolved across 7 codegen units; 1065 such symbols → 0 after) — and `benilla-formats` stops taking `image` with default features, which had been compiling a complete AV1 encoder into a crate that writes two PNGs: 499 → 466 workspace crates

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-29 17:24:50 +07:00

64 lines
3.0 KiB
XML

<Ui>
<!--
The cinematic frame — what makes InCinematic() true, and the ESC that skips a fly-by.
Transcribed from the reference's Interface\FrameXML\CinematicFrame.xml + .lua (decision
1602 permits it); the engine half is crate::cinematic.
This frame is load-bearing for exactly one thing, and it is not a picture: it is the WHOLE
skip path. In the reference, StopCinematic (0x48b970) has zero native callers and no
Bindings.xml row — the only thing that ever calls it is the OnKeyDown below, reached
because this fullscreen frame is keyboard-enabled and showing. No frame on screen means no
way out of a 102-second Night Elf intro.
THE BLACK BARS ARE NOT HERE, deliberately. The reference draws them as two textures on this
frame; we draw them as Bevy UI nodes in crate::cinematic instead, because a cinematic hides
the HUD through UiHidden — which kills both of ui_pass's quad lanes wholesale, and the
FrameXML layer is one of them. Bars declared here would go dark along with the action bars
they exist to replace. The bar LAW is unchanged and still the reference's (only a screen
wider than 4:3 gets bars; the picture is cropped to 2:1, the remainder split evenly) — it
just lives where it can be drawn. See `drive_letterbox`.
So this frame draws nothing at all. It is kept rather than replaced with an engine-side key
handler because the skip path IS a frame in the reference: keeping it means ESC works for
the same reason it works there, and an addon that hooks CinematicFrame still finds it.
RunBinding("SCREENSHOT") is kept as the reference has it: while this frame eats the
keyboard, the screenshot key is the one binding that still has to get through.
-->
<Script><![CDATA[
function CinematicFrame_OnLoad()
this:RegisterEvent("CINEMATIC_START");
this:RegisterEvent("CINEMATIC_STOP");
end
function CinematicFrame_OnEvent()
if ( event == "CINEMATIC_START" ) then
ShowUIPanel(this, 1);
return;
end
if ( event == "CINEMATIC_STOP" ) then
HideUIPanel(this);
return;
end
end
]]></Script>
<Frame name="CinematicFrame" setAllPoints="true" hidden="true" enableKeyboard="true" enableMouse="true">
<Scripts>
<OnLoad>
CinematicFrame_OnLoad();
</OnLoad>
<OnEvent>
CinematicFrame_OnEvent();
</OnEvent>
<OnKeyDown>
local screenshotKey = GetBindingKey("SCREENSHOT");
if ( arg1 == "ESCAPE" ) then
StopCinematic();
elseif ( screenshotKey and (arg1 == screenshotKey) ) then
RunBinding("SCREENSHOT");
end
</OnKeyDown>
</Scripts>
</Frame>
</Ui>