You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
10 KiB
C++
225 lines
10 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <GameState/GameStateRequestBus.h>
|
|
#include <GameStateSamples/GameStateLevelLoading.h>
|
|
#include <GameStateSamples/GameStateLevelPaused.h>
|
|
#include <GameStateSamples/GameStateLevelRunning.h>
|
|
#include <GameStateSamples/GameStatePrimaryControllerDisconnected.h>
|
|
#include <GameStateSamples/GameStatePrimaryUserMonitor.h>
|
|
#include <GameStateSamples/GameStatePrimaryUserSignedOut.h>
|
|
|
|
#include <LocalUser/LocalUserRequestBus.h>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
namespace GameStateSamples
|
|
{
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::OnPushed()
|
|
{
|
|
m_primaryControllerDisconnectedWhileLevelLoading = false;
|
|
m_primaryUserSignedOutWhileLevelLoading = false;
|
|
|
|
GameState::GameStateNotificationBus::Handler::BusConnect();
|
|
AzFramework::InputDeviceNotificationBus::Handler::BusConnect();
|
|
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
|
|
LocalUser::LocalUserNotificationBus::Handler::BusConnect();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::OnPopped()
|
|
{
|
|
LocalUser::LocalUserNotificationBus::Handler::BusDisconnect();
|
|
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
|
|
AzFramework::InputDeviceNotificationBus::Handler::BusDisconnect();
|
|
GameState::GameStateNotificationBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::OnActiveGameStateChanged(AZStd::shared_ptr<IGameState> oldGameState,
|
|
AZStd::shared_ptr<IGameState> newGameState)
|
|
{
|
|
if (m_primaryUserSignedOutWhileLevelLoading &&
|
|
azrtti_istypeof<GameStateLevelLoading>(oldGameState.get()))
|
|
{
|
|
// The primary user signed out while a level was loading,
|
|
// we had to wait until the level finished loading before
|
|
// transitioning to the primary user signed out game state.
|
|
m_primaryUserSignedOutWhileLevelLoading = false;
|
|
m_primaryControllerDisconnectedWhileLevelLoading = false;
|
|
PushPrimaryUserSignedOutGameState();
|
|
return;
|
|
}
|
|
|
|
if (m_primaryControllerDisconnectedWhileLevelLoading &&
|
|
azrtti_istypeof<GameStateLevelLoading>(oldGameState.get()))
|
|
{
|
|
// The controller disconnected while a level was loading,
|
|
// we had to wait until the level finished loading before
|
|
// transitioning to the controller disconnected game state.
|
|
m_primaryControllerDisconnectedWhileLevelLoading = false;
|
|
PushPrimaryControllerDisconnectedGameState();
|
|
return;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::OnInputDeviceConnectedEvent(const AzFramework::InputDevice& inputDevice)
|
|
{
|
|
const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
|
|
if (m_primaryControllerDisconnectedWhileLevelLoading &&
|
|
primaryLocalUserId == inputDevice.GetAssignedLocalUserId())
|
|
{
|
|
// The controller disconnected while a level was loading,
|
|
// but was reconnected before the level finished loading.
|
|
m_primaryControllerDisconnectedWhileLevelLoading = false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::OnInputDeviceDisconnectedEvent(const AzFramework::InputDevice& inputDevice)
|
|
{
|
|
const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
|
|
if (primaryLocalUserId != inputDevice.GetAssignedLocalUserId() ||
|
|
primaryLocalUserId == AzFramework::LocalUserIdNone)
|
|
{
|
|
// The disconnected controller does not belong to the primary user,
|
|
// or the primary user has not yet been set.
|
|
return;
|
|
}
|
|
|
|
if (GameState::GameStateRequests::IsActiveGameStateOfType<GameStateLevelLoading>())
|
|
{
|
|
// The controller disconnected while a level is loading;
|
|
// we have to wait until the level has finished loading.
|
|
m_primaryControllerDisconnectedWhileLevelLoading = true;
|
|
return;
|
|
}
|
|
|
|
PushPrimaryControllerDisconnectedGameState();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::OnApplicationUnconstrained(AzFramework::ApplicationLifecycleEvents::Event /*lastEvent*/)
|
|
{
|
|
const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
|
|
if (primaryLocalUserId == AzFramework::LocalUserIdNone)
|
|
{
|
|
// The primary user has yet to be set
|
|
m_primaryUserSignedOutWhileLevelLoading = false;
|
|
return;
|
|
}
|
|
|
|
bool isPrimaryLocalUserSignedIn = false;
|
|
LocalUser::LocalUserRequestBus::BroadcastResult(isPrimaryLocalUserSignedIn,
|
|
&LocalUser::LocalUserRequests::IsLocalUserSignedIn,
|
|
primaryLocalUserId);
|
|
if (isPrimaryLocalUserSignedIn)
|
|
{
|
|
// The primary user is still signed in
|
|
m_primaryUserSignedOutWhileLevelLoading = false;
|
|
return;
|
|
}
|
|
|
|
if (GameState::GameStateRequests::IsActiveGameStateOfType<GameStateLevelLoading>())
|
|
{
|
|
// The primary user signed out while a level is loading;
|
|
// we have to wait until the level has finished loading.
|
|
m_primaryUserSignedOutWhileLevelLoading = true;
|
|
return;
|
|
}
|
|
|
|
PushPrimaryUserSignedOutGameState();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::OnLocalUserSignedIn(AzFramework::LocalUserId localUserId)
|
|
{
|
|
const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
|
|
if (m_primaryUserSignedOutWhileLevelLoading &&
|
|
primaryLocalUserId == localUserId)
|
|
{
|
|
// The primary user signed out while a level was loading,
|
|
// but signed in again before the level finished loading.
|
|
m_primaryUserSignedOutWhileLevelLoading = false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::OnLocalUserSignedOut(AzFramework::LocalUserId localUserId)
|
|
{
|
|
const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
|
|
if (primaryLocalUserId != localUserId ||
|
|
primaryLocalUserId == AzFramework::LocalUserIdNone)
|
|
{
|
|
// The user that signed out is not the primary user,
|
|
// or the primary user has not yet been set.
|
|
return;
|
|
}
|
|
|
|
if (GameState::GameStateRequests::IsActiveGameStateOfType<GameStateLevelLoading>())
|
|
{
|
|
// The primary user signed out while a level is loading;
|
|
// we have to wait until the level has finished loading.
|
|
m_primaryUserSignedOutWhileLevelLoading = true;
|
|
return;
|
|
}
|
|
|
|
PushPrimaryUserSignedOutGameState();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::PushPrimaryControllerDisconnectedGameState()
|
|
{
|
|
if (GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStatePrimaryControllerDisconnected>() ||
|
|
GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStatePrimaryUserSignedOut>())
|
|
{
|
|
// The controller disconnection has already been detected,
|
|
// or the primary user signed out (which takes precedence).
|
|
return;
|
|
}
|
|
|
|
// Ensure the game is paused if needed before pushing the controller disconnected game state
|
|
TryPushLevelPausedGameState();
|
|
GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<GameStatePrimaryControllerDisconnected>();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::PushPrimaryUserSignedOutGameState()
|
|
{
|
|
if (GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStatePrimaryUserSignedOut>())
|
|
{
|
|
// The primary user sign out has already been detected
|
|
return;
|
|
}
|
|
|
|
if (GameState::GameStateRequests::IsActiveGameStateOfType<GameStatePrimaryControllerDisconnected>())
|
|
{
|
|
// The primary user signing out takes precedence over their controller being disconnected
|
|
GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
|
|
}
|
|
|
|
// Ensure the game is paused if needed before pushing the primary user signed out game state
|
|
TryPushLevelPausedGameState();
|
|
GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<GameStatePrimaryUserSignedOut>();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline void GameStatePrimaryUserMonitor::TryPushLevelPausedGameState()
|
|
{
|
|
if (GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStateLevelPaused>() ||
|
|
!GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStateLevelRunning>())
|
|
{
|
|
// The game has already been paused or is not actively running yet
|
|
return;
|
|
}
|
|
|
|
GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<GameStateLevelPaused>();
|
|
}
|
|
}
|