feat: add pauzing of the running game
This commit is contained in:
+46
-4
@@ -188,6 +188,10 @@ if (!isRunning) break;
|
||||
{
|
||||
playModeToggleRequested = true;
|
||||
}
|
||||
if (playing && InputManager::GetInstance().WasKeyPressed(SDL_SCANCODE_F7))
|
||||
{
|
||||
setPaused(!paused);
|
||||
}
|
||||
|
||||
// Consume SDL events before updating the base camera so held and
|
||||
// newly pressed inputs are applied in the same frame.
|
||||
@@ -431,21 +435,57 @@ void App::drawWindowsMenu()
|
||||
|
||||
void App::drawPlayControls()
|
||||
{
|
||||
const char* state = playing ? "PLAYING" : "EDIT";
|
||||
const char* state = !playing ? "EDIT" : paused ? "PAUSED" : "PLAYING";
|
||||
const char* action = playing ? "Stop (F5)" : "Play (F5)";
|
||||
const char* pauseAction = paused ? "Resume (F7)" : "Pause (F7)";
|
||||
const ImGuiStyle& style = ImGui::GetStyle();
|
||||
const float width = ImGui::CalcTextSize(state).x + ImGui::CalcTextSize(action).x +
|
||||
style.ItemSpacing.x * 2.0f + style.FramePadding.x * 2.0f;
|
||||
float width = ImGui::CalcTextSize(state).x + ImGui::CalcTextSize(action).x +
|
||||
style.ItemSpacing.x * 2.0f + style.FramePadding.x * 2.0f;
|
||||
if (playing)
|
||||
{
|
||||
width += ImGui::CalcTextSize(pauseAction).x + style.ItemSpacing.x + style.FramePadding.x * 2.0f;
|
||||
}
|
||||
|
||||
// Centered like Godot's run buttons, unless the menus already reach past the middle
|
||||
ImGui::SetCursorPosX(std::max(ImGui::GetCursorPosX(), (ImGui::GetWindowWidth() - width) * 0.5f));
|
||||
ImGui::TextColored(playing ? ImVec4{0.4f, 0.9f, 0.4f, 1.0f} : ImVec4{0.7f, 0.7f, 0.7f, 1.0f}, "%s", state);
|
||||
const ImVec4 stateColor = !playing ? ImVec4{0.7f, 0.7f, 0.7f, 1.0f}
|
||||
: paused ? ImVec4{0.95f, 0.75f, 0.3f, 1.0f}
|
||||
: ImVec4{0.4f, 0.9f, 0.4f, 1.0f};
|
||||
ImGui::TextColored(stateColor, "%s", state);
|
||||
if (playing && ImGui::MenuItem(pauseAction))
|
||||
{
|
||||
setPaused(!paused);
|
||||
}
|
||||
if (ImGui::MenuItem(action))
|
||||
{
|
||||
playModeToggleRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
void App::setPaused(bool pause)
|
||||
{
|
||||
if (!playing || pause == paused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
paused = pause;
|
||||
SceneManager::GetInstance().SetPaused(paused);
|
||||
|
||||
// Hand the mouse to the editor while paused, give it back to the game on resume
|
||||
auto& input = InputManager::GetInstance();
|
||||
if (paused)
|
||||
{
|
||||
mouseCapturedBeforePause = input.IsMouseCaptured();
|
||||
input.SetMouseCaptured(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
input.SetMouseCaptured(mouseCapturedBeforePause);
|
||||
}
|
||||
spdlog::info(paused ? "Paused play mode" : "Resumed play mode");
|
||||
}
|
||||
|
||||
void App::applyPlayModeToggle()
|
||||
{
|
||||
if (playing)
|
||||
@@ -500,7 +540,9 @@ void App::exitPlayMode()
|
||||
{
|
||||
auto& sceneManager = SceneManager::GetInstance();
|
||||
playing = false;
|
||||
paused = false;
|
||||
sceneManager.SetPlaying(false);
|
||||
sceneManager.SetPaused(false);
|
||||
InputManager::GetInstance().SetMouseCaptured(false);
|
||||
|
||||
const std::shared_ptr<Scene> scene = editScene.lock();
|
||||
|
||||
@@ -16,7 +16,7 @@ Scene& SceneManager::GetCurrentScene() const {
|
||||
|
||||
void SceneManager::Update(float dt) {
|
||||
for (const auto& scene : m_activeScenes) {
|
||||
if (m_playing) {
|
||||
if (IsTicking()) {
|
||||
scene->Update(dt);
|
||||
} else {
|
||||
scene->CommitPendingAdditions();
|
||||
@@ -25,7 +25,7 @@ void SceneManager::Update(float dt) {
|
||||
}
|
||||
|
||||
void SceneManager::FixedUpdate(float dt) {
|
||||
if (!m_playing) {
|
||||
if (!IsTicking()) {
|
||||
return;
|
||||
}
|
||||
for (const auto& scene : m_activeScenes) {
|
||||
@@ -34,7 +34,7 @@ void SceneManager::FixedUpdate(float dt) {
|
||||
}
|
||||
|
||||
void SceneManager::LateUpdate(float dt) {
|
||||
if (!m_playing) {
|
||||
if (!IsTicking()) {
|
||||
return;
|
||||
}
|
||||
for (const auto& scene : m_activeScenes) {
|
||||
|
||||
Reference in New Issue
Block a user