#include "Core/PlaySessionController.h" #include "Core/EditorEvents.h" #include "Core/EventBus.h" #include "Core/IEditorContext.h" #include "Core/ISceneManager.h" #include "Core/IUndoManager.h" namespace XCEngine { namespace Editor { void PlaySessionController::Attach(IEditorContext& context) { if (m_playStartRequestedHandlerId == 0) { m_playStartRequestedHandlerId = context.GetEventBus().Subscribe( [this, &context](const PlayModeStartRequestedEvent&) { StartPlay(context); }); } if (m_playStopRequestedHandlerId == 0) { m_playStopRequestedHandlerId = context.GetEventBus().Subscribe( [this, &context](const PlayModeStopRequestedEvent&) { StopPlay(context); }); } if (m_playPauseRequestedHandlerId == 0) { m_playPauseRequestedHandlerId = context.GetEventBus().Subscribe( [this, &context](const PlayModePauseRequestedEvent&) { PausePlay(context); }); } if (m_playResumeRequestedHandlerId == 0) { m_playResumeRequestedHandlerId = context.GetEventBus().Subscribe( [this, &context](const PlayModeResumeRequestedEvent&) { ResumePlay(context); }); } if (m_playStepRequestedHandlerId == 0) { m_playStepRequestedHandlerId = context.GetEventBus().Subscribe( [this, &context](const PlayModeStepRequestedEvent&) { StepPlay(context); }); } } void PlaySessionController::Detach(IEditorContext& context) { StopPlay(context); if (m_playStartRequestedHandlerId != 0) { context.GetEventBus().Unsubscribe(m_playStartRequestedHandlerId); m_playStartRequestedHandlerId = 0; } if (m_playStopRequestedHandlerId != 0) { context.GetEventBus().Unsubscribe(m_playStopRequestedHandlerId); m_playStopRequestedHandlerId = 0; } if (m_playPauseRequestedHandlerId != 0) { context.GetEventBus().Unsubscribe(m_playPauseRequestedHandlerId); m_playPauseRequestedHandlerId = 0; } if (m_playResumeRequestedHandlerId != 0) { context.GetEventBus().Unsubscribe(m_playResumeRequestedHandlerId); m_playResumeRequestedHandlerId = 0; } if (m_playStepRequestedHandlerId != 0) { context.GetEventBus().Unsubscribe(m_playStepRequestedHandlerId); m_playStepRequestedHandlerId = 0; } } void PlaySessionController::Update(IEditorContext& context, float deltaTime) { (void)context; if (!m_runtimeLoop.IsRunning()) { return; } m_runtimeLoop.Tick(deltaTime); } bool PlaySessionController::StartPlay(IEditorContext& context) { if (context.GetRuntimeMode() != EditorRuntimeMode::Edit) { return false; } auto& sceneManager = context.GetSceneManager(); if (!sceneManager.HasActiveScene()) { return false; } m_editorSnapshot = sceneManager.CaptureSceneSnapshot(); if (!m_editorSnapshot.hasScene) { return false; } if (!sceneManager.RestoreSceneSnapshot(m_editorSnapshot)) { return false; } sceneManager.SetSceneDocumentDirtyTrackingEnabled(false); m_runtimeLoop.Start(sceneManager.GetScene()); context.GetUndoManager().ClearHistory(); context.SetRuntimeMode(EditorRuntimeMode::Play); context.GetEventBus().Publish(PlayModeStartedEvent{}); return true; } bool PlaySessionController::StopPlay(IEditorContext& context) { if (!IsEditorRuntimeActive(context.GetRuntimeMode())) { return false; } auto& sceneManager = context.GetSceneManager(); m_runtimeLoop.Stop(); sceneManager.SetSceneDocumentDirtyTrackingEnabled(true); if (!sceneManager.RestoreSceneSnapshot(m_editorSnapshot)) { return false; } context.GetUndoManager().ClearHistory(); context.SetRuntimeMode(EditorRuntimeMode::Edit); context.GetEventBus().Publish(PlayModeStoppedEvent{}); m_editorSnapshot = {}; return true; } bool PlaySessionController::PausePlay(IEditorContext& context) { if (context.GetRuntimeMode() != EditorRuntimeMode::Play || !m_runtimeLoop.IsRunning()) { return false; } m_runtimeLoop.Pause(); context.SetRuntimeMode(EditorRuntimeMode::Paused); context.GetEventBus().Publish(PlayModePausedEvent{}); return true; } bool PlaySessionController::ResumePlay(IEditorContext& context) { if (context.GetRuntimeMode() != EditorRuntimeMode::Paused || !m_runtimeLoop.IsRunning()) { return false; } m_runtimeLoop.Resume(); context.SetRuntimeMode(EditorRuntimeMode::Play); context.GetEventBus().Publish(PlayModeResumedEvent{}); return true; } bool PlaySessionController::StepPlay(IEditorContext& context) { if (context.GetRuntimeMode() != EditorRuntimeMode::Paused || !m_runtimeLoop.IsRunning()) { return false; } m_runtimeLoop.StepFrame(); return true; } } // namespace Editor } // namespace XCEngine