2026-05-03 20:37:58 +08:00
|
|
|
|
---
|
|
|
|
|
|
title: UI
|
|
|
|
|
|
date: 2026-05-03 00:00:00
|
2026-05-03 21:38:46 +08:00
|
|
|
|
excerpt: ARC 引擎 UI/Slate/UMG 扩展合集:垂直对齐、独立透明度、文本溢出、富文本图片、几何缓存、平台本地化、简单元素着色器扩展
|
2026-05-03 20:37:58 +08:00
|
|
|
|
tags:
|
|
|
|
|
|
- ARC
|
|
|
|
|
|
- UI
|
|
|
|
|
|
rating: ⭐
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# UI — UI/Slate/UMG 扩展
|
|
|
|
|
|
|
|
|
|
|
|
返回 [[ARC引擎修改总览]]
|
|
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
|
|
|
|
|
ARC 引擎对 UE4 的 UI 系统(Slate + UMG)进行了大量扩展,主要服务于格斗游戏的文本显示需求(多语言、竖排文字)和控制器管理。修改涉及约 38 个文件。
|
|
|
|
|
|
|
|
|
|
|
|
## 控制器管理
|
|
|
|
|
|
|
|
|
|
|
|
新增 `FUEISlateApplication`(继承 `FSlateApplication`):
|
|
|
|
|
|
- User/Controller ID 映射表(`UserIndexMap`)
|
|
|
|
|
|
- 格斗游戏多手柄的输入分配
|
|
|
|
|
|
- 参见 [[UEI事件系统]]
|
2026-05-03 21:38:46 +08:00
|
|
|
|
|
|
|
|
|
|
## Slate 扩展
|
|
|
|
|
|
|
|
|
|
|
|
### 概述
|
|
|
|
|
|
|
|
|
|
|
|
ARC 引擎对 Slate 框架进行了多项扩展,主要围绕文本渲染和 Widget 性能优化。
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 垂直文本对齐
|
|
|
|
|
|
|
|
|
|
|
|
新增 `ETextJustifyV::Type` 枚举,为 `STextBlock` 和 `SRichTextBlock` 添加垂直对齐支持:
|
|
|
|
|
|
|
|
|
|
|
|
- `Top` — 顶部对齐
|
|
|
|
|
|
- `Center` — 垂直居中
|
|
|
|
|
|
- `Bottom` — 底部对齐
|
|
|
|
|
|
|
|
|
|
|
|
格斗游戏 UI 中常需要文本在固定高度区域内垂直居中。
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 独立阴影/描边透明度
|
|
|
|
|
|
|
|
|
|
|
|
Shadow 和 Outline 的颜色不受父 Widget 透明度影响:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
标准 UE4:文字透明度 50% → Shadow 也跟着变为 50%
|
|
|
|
|
|
ARC 修改:文字透明度 50% → Shadow 保持自身设定的透明度
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
用于格斗游戏中文字淡入淡出时保持描边清晰可见。
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 文本溢出省略
|
|
|
|
|
|
|
|
|
|
|
|
按高度截断文本并添加省略号(`...`)。标准 UE4 只支持按宽度截断。
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 富文本图片运行
|
|
|
|
|
|
|
|
|
|
|
|
`SRichTextBlock` 扩展了图片嵌入能力:
|
|
|
|
|
|
- 动态 Brush 支持(运行时更换图标)
|
|
|
|
|
|
- 范围创建(基于文本范围插入图片)
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 几何缓存
|
|
|
|
|
|
|
|
|
|
|
|
在 `SWidget` 上新增几何缓存机制:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
void SetCachedGeometry();
|
|
|
|
|
|
void UpdateGeometryAllChildren();
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
减少每帧的 Layout 计算开销,对格斗游戏 60fps 的帧预算至关重要。
|
|
|
|
|
|
|
|
|
|
|
|
### 代码修改情况
|
|
|
|
|
|
|
|
|
|
|
|
| 文件路径 | 修改类型 | 修改内容 |
|
|
|
|
|
|
|---------|---------|---------|
|
|
|
|
|
|
| `Source/Runtime/Slate/Public/Widgets/Text/STextBlock.h` | 修改 | 新增 `ETextJustifyV` 垂直对齐属性 |
|
|
|
|
|
|
| `Source/Runtime/Slate/Private/Widgets/Text/STextBlock.cpp` | 修改 | 垂直对齐布局计算 |
|
|
|
|
|
|
| `Source/Runtime/Slate/Public/Widgets/Text/SRichTextBlock.h` | 修改 | 富文本图片运行 + 动态 Brush |
|
|
|
|
|
|
| `Source/Runtime/Slate/Private/Widgets/Text/SRichTextBlock.cpp` | 修改 | 富文本图片运行实现 |
|
|
|
|
|
|
| `Source/Runtime/SlateCore/Public/Widgets/SWidget.h` | 修改 | 新增 `SetCachedGeometry`、`UpdateGeometryAllChildren` |
|
|
|
|
|
|
| `Source/Runtime/SlateCore/Private/Widgets/SWidget.cpp` | 修改 | 几何缓存实现 |
|
|
|
|
|
|
| `Source/Runtime/SlateCore/Private/Fonts/FontCache*.cpp` | 修改 | 文本阴影/描边独立透明度 |
|
|
|
|
|
|
| `Source/Runtime/Slate/` 其他文件 (~26个) | 修改 | 文本溢出省略、范围创建等 |
|
|
|
|
|
|
|
|
|
|
|
|
## UMG 本地化
|
|
|
|
|
|
|
|
|
|
|
|
### 概述
|
|
|
|
|
|
|
|
|
|
|
|
ARC 引擎为 UMG 文本系统添加了平台感知的本地化机制,允许同一文本 ID 在不同平台上显示不同内容(例如按钮提示文本因平台不同而变化)。
|
|
|
|
|
|
|
|
|
|
|
|
### 平台后缀系统
|
|
|
|
|
|
|
|
|
|
|
|
文本 ID 查找时自动追加平台后缀:
|
|
|
|
|
|
|
|
|
|
|
|
| 平台 | 后缀 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| PS5 | `_PS5` |
|
|
|
|
|
|
| Xbox Series X | `_XSX` |
|
|
|
|
|
|
| 其他 | 无后缀(使用默认文本) |
|
|
|
|
|
|
|
|
|
|
|
|
查找顺序:
|
|
|
|
|
|
1. 先查 `TextID_PS5`(或 `_XSX`)
|
|
|
|
|
|
2. 找不到则回退到 `TextID`
|
|
|
|
|
|
|
|
|
|
|
|
### 语言 ID
|
|
|
|
|
|
|
|
|
|
|
|
新增 CVar `sg_REDLanguageID`,允许运行时切换语言而不依赖系统语言设置:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
static TAutoConsoleVariable<int32> CVarREDLanguageID(
|
|
|
|
|
|
TEXT("sg.REDLanguageID"),
|
|
|
|
|
|
0,
|
|
|
|
|
|
TEXT("Override language ID for RED localization"));
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 自定义 L10N 加载
|
|
|
|
|
|
|
|
|
|
|
|
`Source/Runtime/Core/` 中的本地化文件加载逻辑支持自定义 L10N 目录。
|
|
|
|
|
|
|
|
|
|
|
|
### 兼容性
|
|
|
|
|
|
|
|
|
|
|
|
`UOldRichTextBlockDecorator` 兼容层确保旧版富文本格式在新系统中正常工作。
|
|
|
|
|
|
|
|
|
|
|
|
### 代码修改情况
|
|
|
|
|
|
|
|
|
|
|
|
| 文件路径 | 修改类型 | 修改内容 |
|
|
|
|
|
|
|---------|---------|---------|
|
|
|
|
|
|
| `Source/Runtime/UMG/Private/Components/TextBlock.cpp` | 修改 | 平台后缀 `_PS5`/`_XSX` 文本查找逻辑 |
|
|
|
|
|
|
| `Source/Runtime/UMG/Public/Components/TextWidgetTypes.h` | 修改 | 垂直文本对齐支持 |
|
|
|
|
|
|
| `Source/Runtime/UMG/Private/Components/RichTextBlockDecorator.cpp` | 修改 | `UOldRichTextBlockDecorator` 兼容层 |
|
|
|
|
|
|
| `Source/Runtime/UMG/Private/Components/WidgetComponent.cpp` | 修改 | Widget 组件修改 |
|
|
|
|
|
|
| `Source/Runtime/Core/` | 修改 | `sg_REDLanguageID` CVar + 自定义 L10N 加载 |
|
|
|
|
|
|
|
|
|
|
|
|
## 简单元素渲染扩展
|
|
|
|
|
|
|
|
|
|
|
|
### 概述
|
|
|
|
|
|
|
|
|
|
|
|
扩展了 UE4 的 SimpleElement Pixel Shader(用于 2D UI 元素、线条、Debug 绘制等),新增颜色叠加、灰度转换和 Multiply 混合模式。
|
|
|
|
|
|
|
|
|
|
|
|
### 新增着色器入口
|
|
|
|
|
|
|
|
|
|
|
|
#### REDMain / GammaREDMain
|
|
|
|
|
|
|
|
|
|
|
|
```hlsl
|
|
|
|
|
|
void REDMain(... out float4 OutColor : SV_Target0)
|
|
|
|
|
|
{
|
|
|
|
|
|
OutColor = CalcREDColor(InColor, InTexCoord);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float4 CalcREDColor(float4 VertexColor, float2 UV)
|
|
|
|
|
|
{
|
|
|
|
|
|
float4 TexColor = Texture2DSample(InTexture, InTextureSampler, UV);
|
|
|
|
|
|
float4 Result = TexColor * VertexColor;
|
|
|
|
|
|
|
|
|
|
|
|
// 叠加色
|
|
|
|
|
|
Result.rgb += AddColor.rgb;
|
|
|
|
|
|
|
|
|
|
|
|
// 灰度转换
|
|
|
|
|
|
float Gray = dot(Result.rgb, float3(0.299, 0.587, 0.114));
|
|
|
|
|
|
Result.rgb = lerp(float3(Gray, Gray, Gray), Result.rgb, Grayscale);
|
|
|
|
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
参数:
|
|
|
|
|
|
- `AddColor` — 加法颜色叠加(uniform float3)
|
|
|
|
|
|
- `Grayscale` — 饱和度系数(uniform float,0=灰度,1=原色)
|
|
|
|
|
|
|
|
|
|
|
|
#### MainMult
|
|
|
|
|
|
|
|
|
|
|
|
Multiply 混合模式的 Simple Element 渲染:
|
|
|
|
|
|
|
|
|
|
|
|
```hlsl
|
|
|
|
|
|
void MainMult(... out float4 OutColor : SV_Target0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 用于 Multiply 混合的 UI 元素
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 使用场景
|
|
|
|
|
|
|
|
|
|
|
|
- 格斗游戏 UI 的动态颜色变化(血条变色、技能冷却灰度化)
|
|
|
|
|
|
- 受击时的 HUD 闪烁效果(AddColor 叠加红色)
|
|
|
|
|
|
- 菜单界面的 Multiply 叠加装饰
|
|
|
|
|
|
|
|
|
|
|
|
### 完整代码解析
|
|
|
|
|
|
|
|
|
|
|
|
#### SimpleElementPixelShader.usf — RED 扩展
|
|
|
|
|
|
|
|
|
|
|
|
```hlsl
|
|
|
|
|
|
// ASW Change : 2013/10/01 10:08:00 Takeshi.N
|
|
|
|
|
|
// RED 扩展的 Simple Element 着色器
|
|
|
|
|
|
|
|
|
|
|
|
// 全局参数
|
|
|
|
|
|
half Grayscale; // 饱和度控制 (0=灰度, 1=原色)
|
|
|
|
|
|
float4 AddColor; // 加法叠加颜色
|
|
|
|
|
|
|
|
|
|
|
|
// 通用颜色计算函数
|
|
|
|
|
|
float4 CalcREDColor( float4 BaseColor, float4 VertexColor, float4 AddColor, bool bGamma )
|
|
|
|
|
|
{
|
|
|
|
|
|
// 基色 × 顶点色 + 叠加色
|
|
|
|
|
|
BaseColor = BaseColor * VertexColor + AddColor;
|
|
|
|
|
|
|
|
|
|
|
|
// 可选 Gamma 校正
|
|
|
|
|
|
if( bGamma && ( Gamma != 1.0 ) )
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseColor.rgb = pow(saturate(BaseColor.rgb), Gamma);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 灰度混合:根据 Grayscale 参数在灰度和原色之间过渡
|
|
|
|
|
|
float luma = dot( float3( 0.299f, 0.587f, 0.114f ), BaseColor.rgb );
|
|
|
|
|
|
return lerp( BaseColor, float4( luma.xxx, BaseColor.a ), Grayscale );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 标准 RED 入口(不带 Gamma 校正)
|
|
|
|
|
|
void REDMain(..., out float4 OutColor : SV_Target0, ...)
|
|
|
|
|
|
{
|
|
|
|
|
|
float4 BaseColor = ColourTexture2DSample(InTexture, InTextureSampler, TextureCoordinate);
|
|
|
|
|
|
ReplicateChannelSimpleElementShader(BaseColor);
|
|
|
|
|
|
BaseColor = CalcREDColor( BaseColor, Color, AddColor, false );
|
|
|
|
|
|
OutColor = RETURN_COLOR( BaseColor );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Gamma 校正版本
|
|
|
|
|
|
void GammaREDMain(..., out float4 OutColor : SV_Target0, ...)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 与 REDMain 相同,但 bGamma=true
|
|
|
|
|
|
BaseColor = CalcREDColor( BaseColor, Color, AddColor, true );
|
|
|
|
|
|
OutColor = RETURN_COLOR( BaseColor );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Multiply 混合模式入口
|
|
|
|
|
|
void MainMult(..., out float4 OutColor : SV_Target0, ...)
|
|
|
|
|
|
{
|
|
|
|
|
|
float4 BaseColor = ColourTexture2DSample(InTexture, InTextureSampler, TextureCoordinate);
|
|
|
|
|
|
ReplicateChannelSimpleElementShader(BaseColor);
|
|
|
|
|
|
BaseColor *= Color;
|
|
|
|
|
|
// Premultiplied alpha multiply blend:
|
|
|
|
|
|
// 输出 = 基色 + (1-基色) × (1-Alpha)
|
|
|
|
|
|
// Alpha=1 时输出基色(纯乘法),Alpha=0 时输出白色(无效果)
|
|
|
|
|
|
OutColor = RETURN_COLOR(BaseColor + (1.0f - BaseColor) * (1.0f - BaseColor.a));
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 代码修改情况
|
|
|
|
|
|
|
|
|
|
|
|
| 文件路径 | 行号 | 修改类型 | 修改内容 |
|
|
|
|
|
|
|---------|------|---------|---------|
|
|
|
|
|
|
| `Shaders/Private/SimpleElementPixelShader.usf` | L432~L434 | 新增 | `Grayscale` 和 `AddColor` uniform 声明 |
|
|
|
|
|
|
| `Shaders/Private/SimpleElementPixelShader.usf` | L436~L455 | 新增 | `CalcREDColor` 通用颜色计算函数 |
|
|
|
|
|
|
| `Shaders/Private/SimpleElementPixelShader.usf` | L457~L487 | 新增 | `REDMain` 标准 RED 入口(不带 Gamma) |
|
|
|
|
|
|
| `Shaders/Private/SimpleElementPixelShader.usf` | L489~L518 | 新增 | `GammaREDMain` Gamma 校正版本 |
|
|
|
|
|
|
| `Shaders/Private/SimpleElementPixelShader.usf` | L522~L542 | 新增 | `MainMult` Multiply 混合模式入口 |
|