SMassBattleDebuggerPanel
Source/MassBattleEditor/Public/SMassBattleDebuggerPanel.h
概述 Overview
MassBattle 调试器面板(Slate 复合控件):实体/池统计表、Niagara 式 fragment 属性 watch(实体头顶数值叠加)、直连 fragment 的调试绘制,外加网络与模拟控制段(暂停/恢复、resync 注入、网络模拟旋钮)。全部逻辑由 Slate Tick 驱动——游戏线程、world tick 未运行时执行,对模拟只读。数据与绘制后端全部委托给 FMassBattleDebuggerCore 的静态函数,本类只负责 UI 与节流调度。
The MassBattle debugger panel (Slate compound widget): an entity/pool stats table, Niagara-style fragment property watching (on-entity value overlays), direct fragment-based debug drawing, plus a network & simulation control section (pause/resume, resync injection, net-emulation knobs). Everything is driven from Slate Tick — executed on the game thread while the world tick is not running — and is read-only against the simulation. The data and drawing backend is entirely delegated to the static functions of FMassBattleDebuggerCore; this class only provides UI and throttled scheduling.
面板结构:顶栏(世界下拉 + 统计暂停 + 刷新率下拉)→「Entity & Pool Stats」分区(单表含 Total/Active/Pooled/Hosted Obj/FromPool-Fresh 列)→「Network & Simulation」分区 →「Value Overlays」分区(类别/fragment/属性三级级联下拉,逐行增删)。各分区用 Details 风格可折叠头(SExpandableArea)包裹。
Panel layout: a top bar (world combo + pause-stats checkbox + refresh-rate combo) → the "Entity & Pool Stats" section (a single table with Total/Active/Pooled/Hosted Obj/FromPool-Fresh columns) → the "Network & Simulation" section → the "Value Overlays" section (a category/fragment/property cascade of combos, add/remove per row). Each section is wrapped in a collapsible details-style header (SExpandableArea).
继承 Inheritance
结构体 Structs
UI 侧叠加行:共享数据项(TSharedRef<FMBOverlayEntry>)+ Slate 下拉框所需的逐行选项列表与控件句柄。Data 绝不能默认构造(TSharedRef 仅热重载内部用的默认构造会断言)——必须带 MakeShared<FMBOverlayEntry>() 初始化。
UI-side overlay row: the shared data entry (TSharedRef<FMBOverlayEntry>) plus the per-row option lists and widget handles the Slate combo boxes need. Data must never be default-constructed (the hot-reload-only TSharedRef default constructor asserts) — always initialize with MakeShared<FMBOverlayEntry>().
成员变量 Members
| 名称 Name | 类型 Type | 默认值 | 说明 Description |
|---|---|---|---|
Data | TSharedRef<FMBOverlayEntry> | MakeShared<FMBOverlayEntry>() | 叠加数据本体(类别/fragment/属性名),绘制时解引用提交给核心。The overlay payload itself (category/fragment/property names); dereferenced and submitted to the core at draw time. |
FragmentOptions | TArray<TSharedPtr<FName>> | 空 | 按类别过滤的 fragment 选项(经 GetCategoryFragmentNames 重建)。Category-filtered fragment options (rebuilt via GetCategoryFragmentNames). |
PropertyOptions | TArray<TSharedPtr<FName>> | 空 | 属性选项(经 GetWatchablePropertyNames 重建)。Property options (rebuilt via GetWatchablePropertyNames). |
FragmentCombo / PropertyCombo | TSharedPtr<SComboBox<TSharedPtr<FName>>> | 空 | 两个下拉框的控件句柄——类别变更使级联失效时,需要主动调它们的 RefreshOptions。Handles to the two combo boxes — when a category change invalidates the cascade, their RefreshOptions must be called explicitly. |
公开方法 Public Methods
Slate 构造入口。先建一次性下拉源:CategoryOptions 按枚举序遍历 EMBDebugCategory 生成(选项索引 == 枚举值);RefreshOptions 为 {"0.1s", "0.25s", "0.5s", "1s"}(映射到 StatsInterval,默认选 0.25s)。随后装配整体 UI(滚动盒):顶栏(世界下拉 + "Pause stats" 复选框 + 刷新率下拉)、「Entity & Pool Stats」表(列头 + SListView,最大高 460)、「Network & Simulation」段、「Value Overlays」段(过滤行:Enable/MaxCount/MaxDist/Spacing/UID Filter + 叠加行容器 + "+ Add Overlay" 按钮)。调试形状绘制分区当前未挂载(见补充说明)。最后 AddOverlay() 预置一行默认叠加:Agent 类别的 Health.Current。
Slate construction entry. Builds the one-time combo sources first: CategoryOptions enumerates EMBDebugCategory in order (option index == enum value); RefreshOptions is {"0.1s", "0.25s", "0.5s", "1s"} (mapped to StatsInterval, defaulting to 0.25s). Then assembles the whole UI (scroll box): top bar (world combo + "Pause stats" checkbox + refresh-rate combo), the "Entity & Pool Stats" table (column header + SListView, max height 460), the "Network & Simulation" section, and the "Value Overlays" section (filter row: Enable/MaxCount/MaxDist/Spacing/UID Filter + the overlay row container + an "+ Add Overlay" button). The debug-shape draw section is currently unmounted (see Notes). Finally AddOverlay() pre-seeds one default overlay: Health.Current over the Agent category.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
InArgs | const FArguments& | Slate 参数(SLATE_BEGIN_ARGS/END_ARGS 内无自定义参数)。Slate arguments (no custom args between SLATE_BEGIN_ARGS/END_ARGS). |
Output
无返回值。副作用:构建全部子控件;填好 CategoryOptions / RefreshOptions;追加一行默认叠加并生成其选项。
No return value. Side effects: builds all child widgets; fills CategoryOptions / RefreshOptions; appends one default overlay row and generates its options.
面板的心跳(每编辑器帧,游戏线程,world tick 未运行——此时读取 Mass 数据结构稳定)。先调父类;然后按固定节奏驱动四件事:① 世界列表每 0.5s 经 GetGameWorlds 刷新一次(保留先前选择);② 所选世界无效则直接返回,否则按 StatsInterval 节流(未被 "Pause stats" 暂停时)调用 CollectStats 刷新统计表;③ DrawSettings.bEnable 时每帧调用 DrawWorld(Duration=0 单帧绘制,PIE 暂停时依然可见);④ OverlaySettings.bEnable 且有叠加行时每帧调用 DrawTextOverlays(独立于形状绘制的开关与过滤)。
The panel's heartbeat (every editor frame, game thread, world tick not running — reading Mass data is structurally stable then). Calls the parent first; then drives four things on fixed cadences: ① the world list refreshes via GetGameWorlds every 0.5s (preserving the previous selection); ② returns immediately with no valid selected world, otherwise refreshes the stats table via CollectStats throttled by StatsInterval (unless paused by "Pause stats"); ③ calls DrawWorld every frame while DrawSettings.bEnable is on (Duration=0 one-frame draws stay visible even when PIE is paused); ④ calls DrawTextOverlays every frame while OverlaySettings.bEnable is on and rows exist (independent switch and filters from shape drawing).
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
AllottedGeometry | const FGeometry& | 分配几何(Slate 传入,仅转发父类)。Allotted geometry (provided by Slate; forwarded to the parent only). |
InCurrentTime | double | 当前时间(仅转发父类)。Current time (forwarded to the parent only). |
InDeltaTime | float | 本帧步长(秒),累加进各节流计时器。Frame delta in seconds; accumulated into the throttle timers. |
Output
无返回值。副作用:按节奏刷新世界列表与统计表,并触发调试绘制/叠加(见上)。对实体/池状态零写入。
No return value. Side effects: refreshes the world list and stats table on cadence and triggers debug draw/overlays (above). Zero writes to entity/pool state.
成员变量 Members
| 名称 Name | 类型 Type | 默认值 | 说明 Description |
|---|---|---|---|
Worlds | TArray<TWeakObjectPtr<UWorld>> (private) | 空 | 世界下拉的数据源(PIE/Game 世界),每 0.5s 刷新。Data source of the world combo (PIE/Game worlds); refreshed every 0.5s. |
SelectedWorldIndex | int32 (private) | INDEX_NONE | 所选世界下标;刷新时若先前选择仍存在则保留。Index of the selected world; the previous selection is kept across refreshes when still present. |
WorldListAccum | float (private) | 0.f | 世界列表刷新计时器(阈值 0.5s)。World-list refresh timer (0.5s threshold). |
StatRows / StatListView | TArray<TSharedRef<FMBDebuggerRow>> / TSharedPtr<SListView<...>> (private) | 空 | 统计表的行数据与列表控件;刷新后调 RequestListRefresh。Row data and list widget of the stats table; RequestListRefresh after each refresh. |
DrawSettings | FMBDebugDrawSettings (private) | 见核心页 | 绘制设置(结构体定义见 MassBattleDebuggerCore.h);其 UI 分区当前未挂载。Draw settings (struct defined in MassBattleDebuggerCore.h); its UI section is currently unmounted. |
OverlayUI / OverlayBox | TArray<FMBOverlayUIEntry> / TSharedPtr<SVerticalBox> (private) | 空 | 叠加行的 UI 数据与行容器;行集合变化时整体重建。UI data of overlay rows and their container; rebuilt wholesale on row-set changes. |
CategoryOptions | TArray<TSharedPtr<FName>> (private) | 空 | 类别下拉选项;选项下标 == (int32)EMBDebugCategory。Category combo options; option index == (int32)EMBDebugCategory. |
OverlaySettings | FMBOverlaySettings (private) | 见核心页 | 叠加过滤(MaxCount/MaxDist/LineStepScale/UidFilter——结构体见核心页)。Overlay filters (MaxCount/MaxDist/LineStepScale/UidFilter — struct documented on the core page). |
UidFilterText | FString (private) | 空 | UID 过滤的原始文本(如 "1,5,100"),变更时解析成 UidFilter 集合。Raw UID-filter text (e.g. "1,5,100"); parsed into the UidFilter set on change. |
RefreshOptions / SelectedRefreshIndex | TArray<TSharedPtr<FString>> / int32 (private) | {"0.1s","0.25s","0.5s","1s"} / 1 | 刷新率选项与所选下标;下标映射到 0.1/0.25/0.5/1s 的 StatsInterval。Refresh-rate options and selected index; the index maps to the 0.1/0.25/0.5/1s StatsInterval. |
StatsInterval / StatsAccum | float / float (private) | 0.25f / 0.f | 统计刷新间隔(秒)与累计计时器;切换世界时把累计器顶到阈值以立即刷新。Stats refresh interval (seconds) and its accumulator; switching worlds forces the accumulator to the threshold for an immediate refresh. |
bPauseStats | bool (private) | false | "Pause stats" 复选框状态——冻结统计刷新(绘制不受影响)。State of the "Pause stats" checkbox — freezes stats refresh (drawing unaffected). |
私有方法分组 Private Method Groups
| 分组 Group | 方法 Methods | 说明 Description |
|---|---|---|
| 世界选择World selection | RefreshWorldList / GetSelectedWorld / OnGenerateWorldOption / GetWorldComboText / OnWorldSelected / OnRefreshRateSelected | 世界下拉的数据/显示/选择回调;选项显示 "世界名 — 网络角色"(Server/ListenServer/Client/Standalone);无游戏世界时显示 "no game world — start PIE"。Data/display/selection callbacks of the world combo; options show "WorldName — NetRole" (Server/ListenServer/Client/Standalone); shows "no game world — start PIE" with no game world. |
| 统计Stats | RefreshStats / OnGenerateStatRow | 调 CollectStats 取新行并请求列表刷新;行生成把 INDEX_NONE 列渲染为 "—",池流转列渲染为 "FromPool / Fresh"。Fetches new rows via CollectStats and requests a list refresh; row generation renders INDEX_NONE columns as "—" and the churn column as "FromPool / Fresh". |
| 数值叠加Value overlays | RebuildOverlayRows / AddOverlay / RemoveOverlay / OnOverlayCategorySelected / OnOverlayFragmentSelected / OnOverlayPropertyChanged / RebuildOverlayFragmentOptions / RebuildOverlayPropertyOptions / OnUidFilterChanged | 叠加行的增删改:类别变更使 fragment/属性级联失效并重置两个选择器;UID 过滤按逗号分词解析(空项/非数字跳过,留空 = 不过滤)。Add/remove/edit overlay rows: a category change invalidates the fragment/property cascade and resets both pickers; the UID filter parses comma-separated tokens (blank/non-numeric tokens skipped; empty = no filter). |
| 网络与模拟控制Network & simulation | MakeNetworkSection / OnTogglePause / OnInjectResync / OnResetNetEmu / FindNetEmuCVar / MakeCVarIntSpin / MakeCVarFloatSpin / MakeCVarToggle | 暂停按钮走 UMassBattleSubsystem::PauseGame/ResumeGame(主用户暂停,边沿广播网络事件);两个 resync 注入按钮仅对 NM_Client 世界生效,走 TriggerLocalResync/TriggerServerResync;网络模拟旋钮直接读写 MassBattle.NetEmulation.* CVar(进程级——一进程一条模拟 TCP 链路)。The pause button goes through UMassBattleSubsystem::PauseGame/ResumeGame (master user pause; broadcasts a network event on the edge); the two resync-injection buttons act on NM_Client worlds only via TriggerLocalResync/TriggerServerResync; net-emulation knobs read/write the MassBattle.NetEmulation.* CVars directly (process-wide — one process = one simulated TCP link). |
| 分区外观Section chrome | MakeSection | 用 SExpandableArea 包出 Details 风格可折叠分区头(强化视觉分组、可折叠省空间)。Wraps content in an SExpandableArea details-style collapsible header (stronger visual grouping, collapsible to save space). |
| 绘制设置 UIDraw settings UI | MakeToggle / MakeDrawSection | 复选框工厂(直连 bool 指针)与绘制设置分区构建器;该分区当前未挂载(见补充说明)。Checkbox factory (binding straight to a bool pointer) and the draw-settings section builder; the section is currently unmounted (see Notes). |
管线角色 Pipeline Role
面板由 FMassBattleEditorModule::OnSpawnDebuggerTab(MassBattleEditor.cpp)创建:工具栏调试按钮经 FGlobalTabmanager::TryInvokeTab 打开一个 SDockTab(NomadTab 角色——与 Niagara Debugger 等引擎工具面板一致,可拖入主窗口 tab 井停靠且位置跨会话记忆),其内容即 SNew(SMassBattleDebuggerPanel)。运行期本面板是 MassBattleDebuggerCore.h 的唯一 UI 入口:Tick 按节流节奏调用 CollectStats / DrawWorld / DrawTextOverlays,世界列表走 GetGameWorlds,叠加行级联走 GetCategoryFragmentNames / GetWatchablePropertyNames / GetCategoryDisplayName。网络控制段则写入模拟侧状态:UMassBattleSubsystem 的 PauseGame / ResumeGame / IsUserPaused / IsGamePaused / GetTickCount(状态行显示)、UMassBattleNetworkSubsystem 的 TriggerLocalResync / TriggerServerResync(仅限所选 client 世界)、以及 MassBattle.NetEmulation.* 网络模拟 CVar。
The panel is created by FMassBattleEditorModule::OnSpawnDebuggerTab (MassBattleEditor.cpp): the toolbar debugger button opens an SDockTab via FGlobalTabmanager::TryInvokeTab (NomadTab role — matching engine tool panels like the Niagara Debugger, dockable into the main frame's tab wells with the dock position persisting across sessions) whose content is SNew(SMassBattleDebuggerPanel). At runtime this panel is the sole UI entry into MassBattleDebuggerCore.h: Tick calls CollectStats / DrawWorld / DrawTextOverlays on throttled cadences, the world list uses GetGameWorlds, and the overlay cascade uses GetCategoryFragmentNames / GetWatchablePropertyNames / GetCategoryDisplayName. The network section writes simulation-side state: UMassBattleSubsystem's PauseGame / ResumeGame / IsUserPaused / IsGamePaused / GetTickCount (shown on the status line), UMassBattleNetworkSubsystem's TriggerLocalResync / TriggerServerResync (selected client worlds only), and the MassBattle.NetEmulation.* net-emulation CVars.
补充说明 Notes
① 调试形状绘制分区「暂以下线」:Construct 中不再挂载 MakeDrawSection()(注释标注尚不成熟),但后端(FMassBattleDebuggerCore::DrawWorld + FMBDebugDrawSettings)完整保留,Tick 依然响应 DrawSettings.bEnable;需要时重新挂载该分区即可。② 网络模拟 CVar 一组:LagMs / JitterMs / DropPercent / BandwidthLimitKBs / RetransmitDelayMs / RandomSeed / PermanentLoss;"Reset Emulation" 按钮还原传输层默认值(除 RetransmitDelayMs 回到 200 外全部归零)。③ 统计刷新率与 "Pause stats" 只影响统计表;绘制与叠加始终逐编辑器帧执行(Drawn Duration=0)。④ 世界下拉选项带网络角色后缀,便于多 PIE 窗口(服务器 + 多客户端)间区分。
① The debug-shape draw section is "parked": Construct no longer mounts MakeDrawSection() (commented as immature), but the backend (FMassBattleDebuggerCore::DrawWorld + FMBDebugDrawSettings) stays intact and Tick still honors DrawSettings.bEnable; re-enabling is just mounting that section again. ② The net-emulation CVar set: LagMs / JitterMs / DropPercent / BandwidthLimitKBs / RetransmitDelayMs / RandomSeed / PermanentLoss; the "Reset Emulation" button restores transport defaults (all zero except RetransmitDelayMs back to 200). ③ The stats refresh rate and "Pause stats" affect only the stats table; drawing and overlays run every editor frame regardless (Duration=0 draws). ④ World combo options carry a net-role suffix, distinguishing multi-PIE setups (server + clients).