Files
mtgodot-poc/project/text_metrics.gd
T

116 lines
6.6 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# text_metrics —— §8.8 seam ⑦ / ⑩ 收口:头顶子标签 / 掉落名条排版的文本尺寸
# 从「字符数 * 约 7px」/「单行 15px」估算换成 CGraphicTextInstance::GetTextSize 的
# 真实字体度量 1:1(增量 123 换宽 w、增量 124 换高 h、增量 125 加 owner 子串独立度量)。
# ArrangeTextTailPythonTextTail.cpp:211-320 角色块、:160-190 item 块)里
# iNameWidth / iTitleWidth / iLevelWidth / guildW,以及 item 尾标框的 xSize / ySize
# (框 yEnd = ySize:749 / :809),参考端全部来自 `pTextInstance->GetTextSize(&w, &h)`。
# Godot 的 Font.get_string_size() 是 1:1 对应物——本模块把它包成纯静态查询,并在无字体
# headless / 未配主题)时回退到旧的字符数估宽 / 单行估高,保持 name_tail_layout /
# text_tail_arrange 的接口不变。
# (与 name_color.gd / text_tail.gd / chat_tail.gd / name_show.gd / damage_effect.gd /
# target_board.gd / pick_show.gd / name_tail_layout.gd / text_tail_arrange.gd 同一套
# 纯静态镜像套路,本模块是第 30 个 canonical。)
#
# REF40250 ClientVS22 source/ 为唯一基线):
# UserInterface/PythonTextTail.cpp:225 pGuildNameInstance->GetTextSize(&iWidth, &iHeight)
# UserInterface/PythonTextTail.cpp:233 pTextTail->pTextInstance->GetTextSize(&iNameWidth, &iNameHeight)
# UserInterface/PythonTextTail.cpp:240 pTitle->GetTextSize(&iTitleWidth, &iTitleHeight)
# UserInterface/PythonTextTail.cpp:267 pLevel->GetTextSize(&iLevelWidth, &iLevelHeight)(有称号分支)
# UserInterface/PythonTextTail.cpp:297 pLevel->GetTextSize(&iLevelWidth, &iLevelHeight)(只有等级分支)
# UserInterface/PythonTextTail.cpp:733 pOwnerTextInstance->GetTextSize(&xOwnerSize, &yOwnerSize)
# UserInterface/PythonTextTail.cpp:748 pTextInstance->GetTextSize(&xSize, &ySize)SetTextTailOwnerText
# UserInterface/PythonTextTail.cpp:809 pTextInstance->GetTextSize(&xSize, &ySize)SetTextTailTextitem 框尺寸)
# —— GetTextSize 由 CGraphicTextInstance 转发到字体的实际字形排版度量(含字距、非等宽),
# 不是「字符数 * 定宽」。poc 之前的 SUBTAG_CHAR_W_PX / TAG_CHAR_W_PX(7.0) 是它 w 的近似、
# TAG_LINE_H_PX(15.0) 是它 h 的近似。
#
# seam ⑦ / ⑩:本模块只负责「量文本宽 / 高」。有字体时 = get_string_size 的精确像素(1:1);
# 无字体时回退字符数估宽 / 单行估高(headless 测试、或工程未配 Label3D.font 且无
# ThemeDB.fallback_font 的极端情况)。折算成世界坐标仍由调用方按各 Label3D 的 pixel_size
# 处理(见 name_tail_layout.subtag_world_x / text_tail_arrange)。子标签竖排 vs 参考同一
# 屏幕行、无公会徽记 mark 实体这两条 seam ⑦ 遗留不在本模块范围。
extends RefCounted
# 无字体 / font_size 非法时的每字符估宽(=增量 121 之前 net_world.SUBTAG_CHAR_W_PX、
# ground_items.TAG_CHAR_W_PX 用的 7.0)。仅作兜底,有字体时不参与。
const FALLBACK_CHAR_W_PX := 7.0
# 无字体 / font_size 非法时的单行估高(=增量 124 之前 ground_items.TAG_LINE_H_PX 用的
# 15.0)。仅作兜底,有字体时走 get_string_size(...).y。
const FALLBACK_LINE_H_PX := 15.0
# GetTextSize(&w, &h) 1:1text 在 font @ font_size 下的像素尺寸。
# 空串 / font 为 null / font_size <= 0 -> Vector2.ZERO(对齐参考端未建 text instance
# 时该子标签不参与 ArrangeTextTail 的宽度计算)。
static func text_size(font: Font, text: String, font_size: int) -> Vector2:
if text == "" or font == null or font_size <= 0:
return Vector2.ZERO
return font.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size)
# ArrangeTextTail 里各 iXxxWidth 取的就是 GetTextSize 的 w。
# 有字体且量得正宽 -> 精确像素;否则(无字体 / 非法 size-> 字符数 * fallback_char_px。
# 空串恒 0(参考端无 text instance -> 该项不占宽)。
static func width_of(font: Font, text: String, font_size: int,
fallback_char_px := FALLBACK_CHAR_W_PX) -> float:
if text == "":
return 0.0
var w := text_size(font, text, font_size).x
if w > 0.0:
return w
return float(text.length()) * fallback_char_px
# Label3D 便捷入口:从节点自身取字体(Label3D.font 未设时回落 ThemeDB.fallback_font
# 和 font_size,量出该 Label3D 当前文本的像素宽。label 为 null -> 0。
static func label_width(label: Label3D, fallback_char_px := FALLBACK_CHAR_W_PX) -> float:
if label == null:
return 0.0
var f: Font = label.font
if f == null:
f = ThemeDB.fallback_font
return width_of(f, label.text, label.font_size, fallback_char_px)
# GetTextSize 的 hitem 尾标框 yEnd = ySizePythonTextTail.cpp:749 / :809)。单行文本的
# ySize ≈ 字体行高(ascent + descent),与具体字形无关。空串恒 0(参考端无 text
# instance -> 不占高);有字体量得正高 -> 精确像素;否则(无字体 / 非法 size-> fallback。
static func height_of(font: Font, text: String, font_size: int,
fallback_line_px := FALLBACK_LINE_H_PX) -> float:
if text == "":
return 0.0
var h := text_size(font, text, font_size).y
if h > 0.0:
return h
return fallback_line_px
# Label3D 便捷入口:同 label_width,量该 Label3D 当前文本的像素高。label 为 null -> 0。
static func label_height(label: Label3D, fallback_line_px := FALLBACK_LINE_H_PX) -> float:
if label == null:
return 0.0
var f: Font = label.font
if f == null:
f = ThemeDB.fallback_font
return height_of(f, label.text, label.font_size, fallback_line_px)
# 增量 125seam ⑩ 末尾 SetItemTextTailOwner):owner 后缀在参考端是与名字分开的
# pOwnerTextInstance,单独 GetTextSize。poc 只有一个合并 Label3D,故提供「用某 Label3D 的
# 字体 / 字号量任意子串」入口,让 ground_items 把名字子串、owner 子串分别度量。
# label 为 null -> 回退(宽 = 字符数 * fallback_char_px;高 = 空串 0 / 非空 fallback_line_px)。
static func string_width_like(label: Label3D, text: String,
fallback_char_px := FALLBACK_CHAR_W_PX) -> float:
if label == null:
return float(text.length()) * fallback_char_px
var f: Font = label.font
if f == null:
f = ThemeDB.fallback_font
return width_of(f, text, label.font_size, fallback_char_px)
static func string_height_like(label: Label3D, text: String,
fallback_line_px := FALLBACK_LINE_H_PX) -> float:
if text == "":
return 0.0
if label == null:
return fallback_line_px
var f: Font = label.font
if f == null:
f = ThemeDB.fallback_font
return height_of(f, text, label.font_size, fallback_line_px)