a chat link is one token now, and tooltips print true costs
- a chat link edits as one atomic token: the caret can't land inside it, its colors survive, one keypress removes it whole - spell tooltips print the resolved mana cost through the reference's own table walk, and the "% of base mana" line dies - the spirit healer's confirm comes back after a cancel and wears its warning icon - the dressing room's pane is a live animating model, and a tried-on bow lands in the hand Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -58,8 +58,10 @@ pub(super) fn drive_script(
|
||||
world_assets: Option<ResMut<WorldAssets>>,
|
||||
mut images: ResMut<Assets<Image>>,
|
||||
mut font_atlas: Option<ResMut<UiFontAtlas>>,
|
||||
// The token -> off-screen-baked-face bridge a `SetPortraitTexture`-bound region samples.
|
||||
portraits: Res<crate::portrait::PortraitImages>,
|
||||
// Both directions of the booth seam: the token -> off-screen-baked-face bridge a
|
||||
// `SetPortraitTexture`-bound region samples, and the pane geometry this pass publishes back
|
||||
// for the booths' projection aspect + render gate (decision 1069).
|
||||
mut booths: crate::portrait::BoothBridge,
|
||||
// Gates the held-cursor icon quad (decision 0216 §5): CAPTURE-ONLY, the same presence check
|
||||
// every other capture-only system uses (`ui_script::capture_ui_active`'s sibling pattern).
|
||||
capture: Option<Res<crate::capture::CaptureMode>>,
|
||||
@@ -324,7 +326,7 @@ pub(super) fn drive_script(
|
||||
let settled = capture.is_none()
|
||||
&& prev.dims == Some(dims)
|
||||
&& text_ui == prev.text_ui
|
||||
&& portraits.0 == prev.portraits
|
||||
&& booths.images.0 == prev.portraits
|
||||
&& extracted == prev.extracted;
|
||||
if settled {
|
||||
drop(extract_span);
|
||||
@@ -358,8 +360,13 @@ pub(super) fn drive_script(
|
||||
}
|
||||
prev.dims = Some(dims);
|
||||
prev.text_ui = text_ui.clone();
|
||||
prev.portraits = portraits.0.clone();
|
||||
prev.portraits = booths.images.0.clone();
|
||||
prev.extracted = extracted.clone();
|
||||
// This frame's booth panes, refilled by the loop below (decision 1069). Cleared only HERE, on
|
||||
// the un-skipped path: a settled frame draws exactly what the last one did, so the map it left
|
||||
// is still this frame's truth — clearing it above the gate would make every quiet frame put the
|
||||
// body panes' cameras to sleep and freeze their animation.
|
||||
booths.panes.0.clear();
|
||||
for eq in extracted {
|
||||
let Some(r) = eq.rect else { continue };
|
||||
// WoW UI space is y-up from the bottom-left in 768-virtual units; the quad pass is
|
||||
@@ -419,7 +426,20 @@ pub(super) fn drive_script(
|
||||
// booth yet) draws nothing rather than the run-splitter's white default.
|
||||
if let Some(token) = &portrait_unit {
|
||||
use crate::portrait::PortraitSource;
|
||||
let handle = match portraits.0.get(token) {
|
||||
// A **square** binding is a booth pane (`BenillaSetBoothTexture`, decision
|
||||
// 0208 §5), not a round unit portrait: publish the rect's aspect so the booth
|
||||
// can bake at the shape it will be stretched into, and know it is on screen at
|
||||
// all (decision 1069). Recorded before the readiness `continue` below — a pane
|
||||
// whose bake hasn't landed yet is still a pane being drawn. The region's rect
|
||||
// is the whole answer because no pane crops its bake; a pane that grew
|
||||
// `<TexCoords>` would have to fold that UV window in here too.
|
||||
if !circular && rect.height() > 0.0 {
|
||||
booths
|
||||
.panes
|
||||
.0
|
||||
.insert(token.clone(), rect.width() / rect.height());
|
||||
}
|
||||
let handle = match booths.images.0.get(token) {
|
||||
Some(PortraitSource::Live(h)) => Some(h.clone()),
|
||||
Some(PortraitSource::File(p)) => assets
|
||||
.as_mut()
|
||||
@@ -820,6 +840,7 @@ mod clip_plumb_tests {
|
||||
app.init_resource::<UiQuads>();
|
||||
app.init_resource::<Assets<Image>>();
|
||||
app.init_resource::<PortraitImages>();
|
||||
app.init_resource::<crate::portrait::BoothPanes>();
|
||||
app.init_resource::<crate::minimap::MinimapWidget>();
|
||||
app.init_resource::<crate::hover_log::UiFrameCost>();
|
||||
app.init_resource::<Time>();
|
||||
@@ -903,6 +924,7 @@ mod clip_plumb_tests {
|
||||
app.init_resource::<UiQuads>();
|
||||
app.init_resource::<Assets<Image>>();
|
||||
app.init_resource::<PortraitImages>();
|
||||
app.init_resource::<crate::portrait::BoothPanes>();
|
||||
app.init_resource::<crate::minimap::MinimapWidget>();
|
||||
app.init_resource::<crate::hover_log::UiFrameCost>();
|
||||
app.init_resource::<Time>();
|
||||
@@ -959,6 +981,7 @@ mod extract_gate_tests {
|
||||
app.init_resource::<UiQuads>();
|
||||
app.init_resource::<Assets<Image>>();
|
||||
app.init_resource::<PortraitImages>();
|
||||
app.init_resource::<crate::portrait::BoothPanes>();
|
||||
app.init_resource::<crate::minimap::MinimapWidget>();
|
||||
app.init_resource::<crate::hover_log::UiFrameCost>();
|
||||
app.init_resource::<Time>();
|
||||
|
||||
@@ -183,14 +183,23 @@ pub(super) fn emit(
|
||||
// actually draws, which is what a truncation report needs to show.
|
||||
let probe = std::env::var("WOW_TEXT_PROBE").as_deref() == Ok("1");
|
||||
if probe {
|
||||
// For the focused edit box, also the two numbers that must agree: where the engine puts the
|
||||
// caret (`caret=`, advance-table-derived) and how wide the text this pass actually draws is
|
||||
// (`ink=`). They diverge by the width of the markup when the advance table is measured over
|
||||
// the raw buffer — the caret-out-in-space report (decision 1075) as a pair of numbers.
|
||||
let ebox_geom = ebox.map(|ui| {
|
||||
let ink = crate::ui_text::measure_text(atlas, draw_text, None, spec).0;
|
||||
format!(" caret={:.1} ink={ink:.1}", ui.caret_x * host.scale)
|
||||
});
|
||||
info!(
|
||||
"text probe: [{:.0},{:.0} {:.0}x{:.0}] h={:?} {:?}",
|
||||
"text probe: [{:.0},{:.0} {:.0}x{:.0}] h={:?}{} {:?}",
|
||||
draw_rect.min.x,
|
||||
draw_rect.min.y,
|
||||
host.rect.width(),
|
||||
host.rect.height(),
|
||||
style.font_height,
|
||||
&draw_text[..draw_text.len().min(30)]
|
||||
ebox_geom.unwrap_or_default(),
|
||||
&draw_text[..draw_text.len().min(60)]
|
||||
);
|
||||
}
|
||||
// The drop shadow (font object `<Shadow>` — MasterFont's (1,-1) black covers the whole
|
||||
|
||||
Reference in New Issue
Block a user