feat: add pause control to top run toolbar

This commit is contained in:
2026-04-02 21:21:42 +08:00
parent 8e362fc4c0
commit f7d7d08d99
2 changed files with 47 additions and 14 deletions

View File

@@ -31,11 +31,12 @@
### 阶段 D 当前收口 ### 阶段 D 当前收口
- 已在软件顶部增加独立运行栏 - 已在软件顶部增加独立运行栏
- 运行栏已接入 `Play / Stop / Step` 个图标按钮 - 运行栏已接入 `Play / Pause / Step / Stop` 个图标按钮
- 顶部按钮直接复用现有 PlayMode 请求通道,不额外分叉状态机 - 顶部按钮直接复用现有 PlayMode 请求通道,不额外分叉状态机
- `Play` 仅在 `Edit` 且存在活动场景时可用 - `Play` 仅在 `Edit` 且存在活动场景时可用
- `Pause``Play / Paused` 下可用,并沿用现有 `F6`
- `Stop``Play / Paused` 下可用 - `Stop``Play / Paused` 下可用
- `Step` 仍只在 `Paused` 下可用`Pause / Resume` 继续走 `Run` 菜单与 `F6` - `Step` 仍只在 `Paused` 下可用
## 本轮验证 ## 本轮验证

View File

@@ -33,10 +33,11 @@ std::string BuildRunToolbarIconPath(const char* fileName) {
} }
const std::string& GetRunToolbarIconPath(size_t index) { const std::string& GetRunToolbarIconPath(size_t index) {
static const std::array<const char*, 3> kFileNames = { static const std::array<const char*, 4> kFileNames = {
"play_button.png", "play_button.png",
"stop_button.png", "pause_button.png",
"step_button.png" "step_button.png",
"stop_button.png"
}; };
static std::array<std::string, kFileNames.size()> s_cachedPaths = {}; static std::array<std::string, kFileNames.size()> s_cachedPaths = {};
@@ -53,7 +54,8 @@ bool DrawRunToolbarIconButton(
const char* id, const char* id,
const Actions::ActionBinding& action, const Actions::ActionBinding& action,
const std::string& iconPath, const std::string& iconPath,
const char* fallbackGlyph) { const char* fallbackGlyph,
const char* disabledHint = nullptr) {
ImGui::BeginDisabled(!action.enabled); ImGui::BeginDisabled(!action.enabled);
ImGui::PushID(id); ImGui::PushID(id);
@@ -92,8 +94,8 @@ bool DrawRunToolbarIconButton(
if (!action.shortcutLabel.empty()) { if (!action.shortcutLabel.empty()) {
ImGui::Text("Shortcut: %s", action.shortcutLabel.c_str()); ImGui::Text("Shortcut: %s", action.shortcutLabel.c_str());
} }
if (!action.enabled && action.label == "Step") { if (!action.enabled && disabledHint && disabledHint[0] != '\0') {
ImGui::TextUnformatted("Available while runtime is paused."); ImGui::TextUnformatted(disabledHint);
} }
UI::EndTitledTooltip(); UI::EndTitledTooltip();
} }
@@ -146,32 +148,62 @@ void MenuBar::RenderRunToolbar() {
if (open) { if (open) {
const Actions::ActionBinding playAction = const Actions::ActionBinding playAction =
Actions::MakeStartPlayModeAction(m_context->GetRuntimeMode(), m_context->GetSceneManager().HasActiveScene()); Actions::MakeStartPlayModeAction(m_context->GetRuntimeMode(), m_context->GetSceneManager().HasActiveScene());
const Actions::ActionBinding stopAction = Actions::MakeStopPlayModeAction(m_context->GetRuntimeMode()); const bool canPause =
m_context->GetRuntimeMode() == EditorRuntimeMode::Play ||
m_context->GetRuntimeMode() == EditorRuntimeMode::Paused;
const Actions::ActionBinding pauseAction =
Actions::MakeTogglePauseModeAction(m_context->GetRuntimeMode(), canPause);
const Actions::ActionBinding stepAction = const Actions::ActionBinding stepAction =
Actions::MakeStepPlayModeAction(m_context->GetRuntimeMode() == EditorRuntimeMode::Paused); Actions::MakeStepPlayModeAction(m_context->GetRuntimeMode() == EditorRuntimeMode::Paused);
const Actions::ActionBinding stopAction = Actions::MakeStopPlayModeAction(m_context->GetRuntimeMode());
const float totalWidth = const float totalWidth =
kRunToolbarButtonExtent * 3.0f + kRunToolbarButtonSpacing * 2.0f; kRunToolbarButtonExtent * 4.0f + kRunToolbarButtonSpacing * 3.0f;
const float startX = const float startX =
ImGui::GetCursorPosX() + (std::max)(0.0f, (ImGui::GetContentRegionAvail().x - totalWidth) * 0.5f); ImGui::GetCursorPosX() + (std::max)(0.0f, (ImGui::GetContentRegionAvail().x - totalWidth) * 0.5f);
const float startY = const float startY =
(std::max)(ImGui::GetCursorPosY(), (ImGui::GetWindowHeight() - kRunToolbarButtonExtent) * 0.5f); (std::max)(ImGui::GetCursorPosY(), (ImGui::GetWindowHeight() - kRunToolbarButtonExtent) * 0.5f);
ImGui::SetCursorPos(ImVec2(startX, startY)); ImGui::SetCursorPos(ImVec2(startX, startY));
if (DrawRunToolbarIconButton("Play", playAction, GetRunToolbarIconPath(0), "P")) { if (DrawRunToolbarIconButton(
"Play",
playAction,
GetRunToolbarIconPath(0),
"P",
"Available in Edit mode when an active scene exists.")) {
Actions::RequestStartPlayMode(*m_context); Actions::RequestStartPlayMode(*m_context);
} }
ImGui::SameLine(0.0f, kRunToolbarButtonSpacing); ImGui::SameLine(0.0f, kRunToolbarButtonSpacing);
if (DrawRunToolbarIconButton("Stop", stopAction, GetRunToolbarIconPath(1), "S")) { if (DrawRunToolbarIconButton(
Actions::RequestStopPlayMode(*m_context); "Pause",
pauseAction,
GetRunToolbarIconPath(1),
"||",
"Available while runtime is playing or paused.")) {
Actions::RequestTogglePauseMode(*m_context);
} }
ImGui::SameLine(0.0f, kRunToolbarButtonSpacing); ImGui::SameLine(0.0f, kRunToolbarButtonSpacing);
if (DrawRunToolbarIconButton("Step", stepAction, GetRunToolbarIconPath(2), ">")) { if (DrawRunToolbarIconButton(
"Step",
stepAction,
GetRunToolbarIconPath(2),
">",
"Available while runtime is paused.")) {
Actions::RequestStepPlayMode(*m_context); Actions::RequestStepPlayMode(*m_context);
} }
ImGui::SameLine(0.0f, kRunToolbarButtonSpacing);
if (DrawRunToolbarIconButton(
"Stop",
stopAction,
GetRunToolbarIconPath(3),
"S",
"Available while runtime is active.")) {
Actions::RequestStopPlayMode(*m_context);
}
UI::DrawCurrentWindowBottomBorder(); UI::DrawCurrentWindowBottomBorder();
} }