Integrating up through commit 90f050496
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "System.h"
|
||||
#include "IStreamEngine.h"
|
||||
#include <AzFramework/Archive/Archive.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include "ResourceManager.h"
|
||||
|
||||
#define MEGA_BYTE 1024* 1024
|
||||
@@ -360,20 +361,37 @@ void CAsyncPakManager::StreamAsyncOnComplete(
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// ugly hack - depending on the pak file pak may need special root info / open flags
|
||||
//
|
||||
if (pLayerPak->layername.find("level.pak") != string::npos)
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels,
|
||||
&AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
|
||||
if (usePrefabSystemForLevels)
|
||||
{
|
||||
gEnv->pCryPak->OpenPack({ pLayerPak->filename.c_str(), pLayerPak->filename.size() }, AZ::IO::IArchive::FLAGS_FILENAMES_AS_CRC32, NULL);
|
||||
}
|
||||
else if (pLayerPak->layername.find("levelshadercache.pak") != string::npos)
|
||||
{
|
||||
gEnv->pCryPak->OpenPack("@assets@", { pLayerPak->filename.c_str(), pLayerPak->filename.size() }, AZ::IO::IArchive::FLAGS_PATH_REAL, NULL);
|
||||
gEnv->pCryPak->OpenPack(
|
||||
"@assets@", {pLayerPak->filename.c_str(), pLayerPak->filename.size()}, AZ::IO::IArchive::FLAGS_FILENAMES_AS_CRC32, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gEnv->pCryPak->OpenPack("@assets@", { pLayerPak->filename.c_str(), pLayerPak->filename.size() }, AZ::IO::IArchive::FLAGS_FILENAMES_AS_CRC32, NULL);
|
||||
//
|
||||
// ugly hack - depending on the pak file pak may need special root info / open flags
|
||||
//
|
||||
if (pLayerPak->layername.find("level.pak") != string::npos)
|
||||
{
|
||||
gEnv->pCryPak->OpenPack(
|
||||
{pLayerPak->filename.c_str(), pLayerPak->filename.size()}, AZ::IO::IArchive::FLAGS_FILENAMES_AS_CRC32, NULL);
|
||||
}
|
||||
else if (pLayerPak->layername.find("levelshadercache.pak") != string::npos)
|
||||
{
|
||||
gEnv->pCryPak->OpenPack(
|
||||
"@assets@", {pLayerPak->filename.c_str(), pLayerPak->filename.size()}, AZ::IO::IArchive::FLAGS_PATH_REAL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gEnv->pCryPak->OpenPack(
|
||||
"@assets@", {pLayerPak->filename.c_str(), pLayerPak->filename.size()}, AZ::IO::IArchive::FLAGS_FILENAMES_AS_CRC32,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
gEnv->pCryPak->LoadPakToMemory(pLayerPak->filename.c_str(), AZ::IO::IArchive::eInMemoryPakLocale_GPU, pLayerPak->pData);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,8 @@
|
||||
#include "ILevelSystem.h"
|
||||
#include <AzFramework/Archive/IArchive.h>
|
||||
|
||||
// [LYN-2376] Remove the entire file once legacy slice support is removed
|
||||
|
||||
namespace LegacyLevelSystem
|
||||
{
|
||||
|
||||
@@ -24,75 +26,38 @@ class CLevelInfo
|
||||
{
|
||||
friend class CLevelSystem;
|
||||
public:
|
||||
CLevelInfo()
|
||||
: m_heightmapSize(0)
|
||||
, m_bMetaDataRead(false)
|
||||
, m_isModLevel(false)
|
||||
, m_scanTag(ILevelSystem::TAG_UNKNOWN)
|
||||
, m_levelTag(ILevelSystem::TAG_UNKNOWN)
|
||||
{
|
||||
SwapEndian(m_scanTag, eBigEndian);
|
||||
SwapEndian(m_levelTag, eBigEndian);
|
||||
};
|
||||
CLevelInfo() = default;
|
||||
|
||||
// ILevelInfo
|
||||
virtual const char* GetName() const { return m_levelName.c_str(); };
|
||||
virtual const bool IsOfType(const char* sType) const;
|
||||
virtual const char* GetPath() const { return m_levelPath.c_str(); };
|
||||
virtual const char* GetPaks() const { return m_levelPaks.c_str(); };
|
||||
virtual bool GetIsModLevel() const { return m_isModLevel; }
|
||||
virtual const uint32 GetScanTag() const { return m_scanTag; }
|
||||
virtual const uint32 GetLevelTag() const { return m_levelTag; }
|
||||
virtual const char* GetDisplayName() const;
|
||||
virtual const char* GetPreviewImagePath() const { return m_previewImagePath.c_str(); }
|
||||
virtual const char* GetBackgroundImagePath() const { return m_backgroundImagePath.c_str(); }
|
||||
virtual const char* GetMinimapImagePath() const {return m_minimapImagePath.c_str(); }
|
||||
//virtual const ILevelInfo::TStringVec& GetMusicLibs() const { return m_musicLibs; }; // Gets reintroduced when level specific music data loading is implemented.
|
||||
virtual const bool MetadataLoaded() const { return m_bMetaDataRead; }
|
||||
|
||||
virtual int GetGameTypeCount() const { return m_gameTypes.size(); };
|
||||
virtual const ILevelInfo::TGameTypeInfo* GetGameType(int gameType) const { return &m_gameTypes[gameType]; };
|
||||
virtual bool SupportsGameType(const char* gameTypeName) const;
|
||||
virtual const ILevelInfo::TGameTypeInfo* GetDefaultGameType() const;
|
||||
virtual bool HasGameRules() const{ return !m_gamerules.empty(); }
|
||||
|
||||
virtual const ILevelInfo::SMinimapInfo& GetMinimapInfo() const { return m_minimapInfo; }
|
||||
|
||||
virtual const char* GetDefaultGameRules() const{ return m_gamerules.empty() ? NULL : m_gamerules[0].c_str(); }
|
||||
virtual ILevelInfo::TStringVec GetGameRules() const{ return m_gamerules; }
|
||||
virtual const char* GetName() const { return m_levelName.c_str(); }
|
||||
virtual const char* GetPath() const { return m_levelPath.c_str(); }
|
||||
virtual const char* GetAssetName() const { return m_levelAssetName.c_str(); }
|
||||
// ~ILevelInfo
|
||||
|
||||
|
||||
void GetMemoryUsage(ICrySizer*) const;
|
||||
|
||||
private:
|
||||
void ReadMetaData();
|
||||
bool ReadInfo();
|
||||
|
||||
bool OpenLevelPak();
|
||||
void CloseLevelPak();
|
||||
|
||||
string m_levelName;
|
||||
string m_levelPath;
|
||||
string m_levelPaks;
|
||||
string m_levelDisplayName;
|
||||
string m_previewImagePath;
|
||||
string m_backgroundImagePath;
|
||||
string m_minimapImagePath;
|
||||
AZStd::string m_defaultGameTypeName;
|
||||
AZStd::string m_levelName;
|
||||
AZStd::string m_levelPath;
|
||||
AZStd::string m_levelAssetName;
|
||||
|
||||
string m_levelPakFullPath;
|
||||
AZStd::string m_levelPakFullPath;
|
||||
|
||||
TStringVec m_gamerules;
|
||||
int m_heightmapSize;
|
||||
uint32 m_scanTag;
|
||||
uint32 m_levelTag;
|
||||
bool m_bMetaDataRead;
|
||||
std::vector<ILevelInfo::TGameTypeInfo> m_gameTypes;
|
||||
bool m_isModLevel;
|
||||
SMinimapInfo m_minimapInfo;
|
||||
bool m_isPak = false;
|
||||
};
|
||||
|
||||
DynArray<string> m_levelTypeList;
|
||||
bool m_isPak = false;
|
||||
struct ILevel
|
||||
{
|
||||
virtual ~ILevel() = default;
|
||||
virtual void Release() = 0;
|
||||
virtual ILevelInfo* GetLevelInfo() = 0;
|
||||
};
|
||||
|
||||
class CLevel
|
||||
@@ -121,10 +86,7 @@ public:
|
||||
void Release() { delete this; };
|
||||
|
||||
// ILevelSystem
|
||||
virtual DynArray<string>* GetLevelTypeList();
|
||||
virtual void Rescan(const char* levelsFolder, const uint32 tag);
|
||||
void ScanFolder(const char* subfolder, bool modFolder, const uint32 tag) override;
|
||||
void PopulateLevels(string searchPattern, string& folder, AZ::IO::IArchive* pPak, bool& modFolder, const uint32& tag, bool fromFileSystemOnly) override;
|
||||
virtual void Rescan(const char* levelsFolder);
|
||||
virtual int GetLevelCount();
|
||||
virtual ILevelInfo* GetLevelInfo(int level);
|
||||
virtual ILevelInfo* GetLevelInfo(const char* levelName);
|
||||
@@ -132,74 +94,81 @@ public:
|
||||
virtual void AddListener(ILevelSystemListener* pListener);
|
||||
virtual void RemoveListener(ILevelSystemListener* pListener);
|
||||
|
||||
virtual ILevel* GetCurrentLevel() const { return m_pCurrentLevel; }
|
||||
virtual ILevel* LoadLevel(const char* levelName);
|
||||
virtual void UnLoadLevel();
|
||||
virtual ILevel* SetEditorLoadedLevel(const char* levelName, bool bReadLevelInfoMetaData = false);
|
||||
virtual void PrepareNextLevel(const char* levelName);
|
||||
virtual float GetLastLevelLoadTime() { return m_fLastLevelLoadTime; };
|
||||
virtual bool LoadLevel(const char* levelName);
|
||||
virtual void UnloadLevel();
|
||||
virtual bool IsLevelLoaded() { return m_bLevelLoaded; }
|
||||
const char* GetCurrentLevelName() const override
|
||||
{
|
||||
if (m_pCurrentLevel && m_pCurrentLevel->GetLevelInfo())
|
||||
{
|
||||
return m_pCurrentLevel->GetLevelInfo()->GetName();
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// If the level load failed then we need to have a different shutdown procedure vs when a level is naturally unloaded
|
||||
virtual void SetLevelLoadFailed(bool loadFailed) { m_levelLoadFailed = loadFailed; }
|
||||
virtual bool GetLevelLoadFailed() { return m_levelLoadFailed; }
|
||||
|
||||
// Unsupported by legacy level system.
|
||||
virtual AZ::Data::AssetType GetLevelAssetType() const { return {}; }
|
||||
|
||||
// ~ILevelSystem
|
||||
|
||||
void GetMemoryUsage(ICrySizer* s) const;
|
||||
|
||||
void SaveOpenedFilesList();
|
||||
|
||||
private:
|
||||
|
||||
float GetLastLevelLoadTime() { return m_fLastLevelLoadTime; }
|
||||
|
||||
void ScanFolder(const char* subfolder, bool modFolder);
|
||||
void PopulateLevels(
|
||||
AZStd::string searchPattern, AZStd::string& folder, AZ::IO::IArchive* pPak, bool& modFolder, bool fromFileSystemOnly);
|
||||
void PrepareNextLevel(const char* levelName);
|
||||
ILevel* LoadLevelInternal(const char* _levelName);
|
||||
|
||||
// ILevelSystemListener events notification
|
||||
// Methods to notify ILevelSystemListener
|
||||
void OnLevelNotFound(const char* levelName);
|
||||
void OnLoadingStart(ILevelInfo* pLevel);
|
||||
void OnLoadingComplete(ILevel* pLevel);
|
||||
void OnLoadingError(ILevelInfo* pLevel, const char* error);
|
||||
void OnLoadingProgress(ILevelInfo* pLevel, int progressAmount);
|
||||
void OnUnloadComplete(ILevel* pLevel);
|
||||
void OnLoadingStart(const char* levelName);
|
||||
void OnLoadingComplete(const char* levelName);
|
||||
void OnLoadingError(const char* levelName, const char* error);
|
||||
void OnLoadingProgress(const char* levelName, int progressAmount);
|
||||
void OnUnloadComplete(const char* levelName);
|
||||
|
||||
// lowercase string and replace backslashes with forward slashes
|
||||
// TODO: move this to a more general place in CryEngine
|
||||
string& UnifyName(string& name);
|
||||
void LogLoadingTime();
|
||||
bool LoadLevelInfo(CLevelInfo& levelInfo);
|
||||
|
||||
// internal get functions for the level infos ... they preserve the type and don't
|
||||
// directly cast to the interface
|
||||
CLevelInfo* GetLevelInfoInternal(int level);
|
||||
CLevelInfo* GetLevelInfoInternal(const char* levelName);
|
||||
CLevelInfo* GetLevelInfoInternal(const AZStd::string& levelName);
|
||||
|
||||
ISystem* m_pSystem;
|
||||
std::vector<CLevelInfo> m_levelInfos;
|
||||
string m_levelsFolder;
|
||||
AZStd::vector<CLevelInfo> m_levelInfos;
|
||||
AZStd::string m_levelsFolder;
|
||||
ILevel* m_pCurrentLevel;
|
||||
ILevelInfo* m_pLoadingLevelInfo;
|
||||
|
||||
string m_lastLevelName;
|
||||
AZStd::string m_lastLevelName;
|
||||
float m_fLastLevelLoadTime;
|
||||
float m_fFilteredProgress;
|
||||
float m_fLastTime;
|
||||
|
||||
bool m_bLevelLoaded;
|
||||
bool m_bRecordingFileOpens;
|
||||
bool m_levelLoadFailed = false;
|
||||
|
||||
int m_nLoadedLevelsCount;
|
||||
|
||||
CTimeValue m_levelLoadStartTime;
|
||||
|
||||
static int s_loadCount;
|
||||
|
||||
std::vector<ILevelSystemListener*> m_listeners;
|
||||
|
||||
DynArray<string> m_levelTypeList;
|
||||
AZStd::vector<ILevelSystemListener*> m_listeners;
|
||||
|
||||
AZ::IO::IArchive::LevelPackOpenEvent::Handler m_levelPackOpenHandler;
|
||||
AZ::IO::IArchive::LevelPackCloseEvent::Handler m_levelPackCloseHandler;
|
||||
|
||||
static constexpr const char* LevelPakName = "level.pak";
|
||||
};
|
||||
|
||||
} // namespace LegacyLevelSystem
|
||||
|
||||
@@ -0,0 +1,709 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include "SpawnableLevelSystem.h"
|
||||
#include <IAudioSystem.h>
|
||||
#include "IMovieSystem.h"
|
||||
#include <IResourceManager.h>
|
||||
#include "IDeferredCollisionEvent.h"
|
||||
|
||||
#include <LoadScreenBus.h>
|
||||
|
||||
#include <AzCore/Debug/AssetTracking.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzFramework/Entity/GameEntityContextBus.h>
|
||||
#include <AzFramework/Input/Buses/Requests/InputChannelRequestBus.h>
|
||||
|
||||
#include "MainThreadRenderRequestBus.h"
|
||||
#include <LyShine/ILyShine.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <AzCore/Script/ScriptSystemBus.h>
|
||||
|
||||
namespace LegacyLevelSystem
|
||||
{
|
||||
//------------------------------------------------------------------------
|
||||
static void LoadLevel(const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
AZ_Error("SpawnableLevelSystem", arguments.empty(), "LoadLevel requires a level file name to be provided.");
|
||||
AZ_Error("SpawnableLevelSystem", arguments.size() > 1, "LoadLevel requires a single level file name to be provided.");
|
||||
|
||||
if (!arguments.empty() && gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor())
|
||||
{
|
||||
gEnv->pSystem->GetILevelSystem()->LoadLevel(arguments[0].data());
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static void UnloadLevel([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
AZ_Warning("SpawnableLevelSystem", !arguments.empty(), "UnloadLevel doesn't use any arguments.");
|
||||
|
||||
if (gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor())
|
||||
{
|
||||
gEnv->pSystem->GetILevelSystem()->UnloadLevel();
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
gEnv->p3DEngine->LoadEmptyLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZ_CONSOLEFREEFUNC(LoadLevel, AZ::ConsoleFunctorFlags::Null, "Unloads the current level and loads a new one with the given asset name");
|
||||
AZ_CONSOLEFREEFUNC(UnloadLevel, AZ::ConsoleFunctorFlags::Null, "Unloads the current level");
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
SpawnableLevelSystem::SpawnableLevelSystem(ISystem* pSystem)
|
||||
: m_pSystem(pSystem)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION;
|
||||
CRY_ASSERT(pSystem);
|
||||
|
||||
m_fLastLevelLoadTime = 0;
|
||||
m_fLastTime = 0;
|
||||
m_bLevelLoaded = false;
|
||||
|
||||
m_levelLoadStartTime.SetValue(0);
|
||||
m_nLoadedLevelsCount = 0;
|
||||
|
||||
AZ_Assert(gEnv && gEnv->pCryPak, "gEnv and CryPak must be initialized for loading levels.");
|
||||
if (!gEnv || !gEnv->pCryPak)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto pPak = gEnv->pCryPak;
|
||||
|
||||
AzFramework::RootSpawnableNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
SpawnableLevelSystem::~SpawnableLevelSystem()
|
||||
{
|
||||
AzFramework::RootSpawnableNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void SpawnableLevelSystem::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool SpawnableLevelSystem::IsLevelLoaded()
|
||||
{
|
||||
return m_bLevelLoaded;
|
||||
}
|
||||
|
||||
const char* SpawnableLevelSystem::GetCurrentLevelName() const
|
||||
{
|
||||
return m_bLevelLoaded ? m_lastLevelName.c_str() : "";
|
||||
}
|
||||
|
||||
// If the level load failed then we need to have a different shutdown procedure vs when a level is naturally unloaded
|
||||
void SpawnableLevelSystem::SetLevelLoadFailed(bool loadFailed)
|
||||
{
|
||||
m_levelLoadFailed = loadFailed;
|
||||
}
|
||||
|
||||
bool SpawnableLevelSystem::GetLevelLoadFailed()
|
||||
{
|
||||
return m_levelLoadFailed;
|
||||
}
|
||||
|
||||
AZ::Data::AssetType SpawnableLevelSystem::GetLevelAssetType() const
|
||||
{
|
||||
return azrtti_typeid<AzFramework::Spawnable>();
|
||||
}
|
||||
|
||||
// The following methods are deprecated from ILevelSystem and will be removed once slice support is removed.
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
void SpawnableLevelSystem::Rescan([[maybe_unused]] const char* levelsFolder)
|
||||
{
|
||||
AZ_Assert(false, "Rescan - No longer supported.");
|
||||
}
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
int SpawnableLevelSystem::GetLevelCount()
|
||||
{
|
||||
AZ_Assert(false, "GetLevelCount - No longer supported.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
ILevelInfo* SpawnableLevelSystem::GetLevelInfo([[maybe_unused]] int level)
|
||||
{
|
||||
AZ_Assert(false, "GetLevelInfo - No longer supported.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
ILevelInfo* SpawnableLevelSystem::GetLevelInfo([[maybe_unused]] const char* levelName)
|
||||
{
|
||||
AZ_Assert(false, "GetLevelInfo - No longer supported.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::AddListener(ILevelSystemListener* pListener)
|
||||
{
|
||||
AZStd::vector<ILevelSystemListener*>::iterator it = AZStd::find(m_listeners.begin(), m_listeners.end(), pListener);
|
||||
|
||||
if (it == m_listeners.end())
|
||||
{
|
||||
m_listeners.push_back(pListener);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::RemoveListener(ILevelSystemListener* pListener)
|
||||
{
|
||||
AZStd::vector<ILevelSystemListener*>::iterator it = AZStd::find(m_listeners.begin(), m_listeners.end(), pListener);
|
||||
|
||||
if (it != m_listeners.end())
|
||||
{
|
||||
m_listeners.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool SpawnableLevelSystem::LoadLevel(const char* levelName)
|
||||
{
|
||||
if (gEnv->IsEditor())
|
||||
{
|
||||
AZ_TracePrintf("CrySystem::CLevelSystem", "LoadLevel for %s was called in the editor - not actually loading.\n", levelName);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a level is currently loaded, unload it before loading the next one.
|
||||
if (IsLevelLoaded())
|
||||
{
|
||||
UnloadLevel();
|
||||
}
|
||||
|
||||
gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_LOAD_PREPARE, 0, 0);
|
||||
PrepareNextLevel(levelName);
|
||||
|
||||
bool result = LoadLevelInternal(levelName);
|
||||
if (result)
|
||||
{
|
||||
OnLoadingComplete(levelName);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool SpawnableLevelSystem::LoadLevelInternal(const char* levelName)
|
||||
{
|
||||
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START);
|
||||
AZ_ASSET_NAMED_SCOPE("Level: %s", levelName);
|
||||
|
||||
INDENT_LOG_DURING_SCOPE();
|
||||
|
||||
AZ::Data::AssetId rootSpawnableAssetId;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
rootSpawnableAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, levelName, nullptr, false);
|
||||
if (!rootSpawnableAssetId.IsValid())
|
||||
{
|
||||
OnLoadingError(levelName, "AssetCatalog has no entry for the requested level.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// This scope is specifically used for marking a loading time profile section
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION;
|
||||
|
||||
m_bLevelLoaded = false;
|
||||
m_lastLevelName = levelName;
|
||||
gEnv->pConsole->SetScrollMax(600);
|
||||
ICVar* con_showonload = gEnv->pConsole->GetCVar("con_showonload");
|
||||
if (con_showonload && con_showonload->GetIVal() != 0)
|
||||
{
|
||||
gEnv->pConsole->ShowConsole(true);
|
||||
ICVar* g_enableloadingscreen = gEnv->pConsole->GetCVar("g_enableloadingscreen");
|
||||
if (g_enableloadingscreen)
|
||||
{
|
||||
g_enableloadingscreen->Set(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the camera to (1,1,1) (not (0,0,0) which is the invalid/uninitialised state,
|
||||
// to avoid the hack in the renderer to not show anything if the camera is at the origin).
|
||||
CCamera defaultCam;
|
||||
defaultCam.SetPosition(Vec3(1.0f));
|
||||
m_pSystem->SetViewCamera(defaultCam);
|
||||
|
||||
OnLoadingStart(levelName);
|
||||
|
||||
auto pPak = gEnv->pCryPak;
|
||||
|
||||
m_pSystem->SetThreadState(ESubsys_Physics, false);
|
||||
|
||||
ICVar* pSpamDelay = gEnv->pConsole->GetCVar("log_SpamDelay");
|
||||
float spamDelay = 0.0f;
|
||||
if (pSpamDelay)
|
||||
{
|
||||
spamDelay = pSpamDelay->GetFVal();
|
||||
pSpamDelay->Set(0.0f);
|
||||
}
|
||||
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
AZ::IO::PathView levelPath(levelName);
|
||||
AZStd::string parentPath(levelPath.ParentPath().Native());
|
||||
|
||||
static constexpr const char* defaultGameTypeName = "Mission0";
|
||||
bool is3DEngineLoaded = gEnv->IsEditor() ? gEnv->p3DEngine->InitLevelForEditor(parentPath.c_str(), defaultGameTypeName)
|
||||
: gEnv->p3DEngine->LoadLevel(parentPath.c_str(), defaultGameTypeName);
|
||||
if (!is3DEngineLoaded)
|
||||
{
|
||||
OnLoadingError(levelName, "3DEngine failed to handle loading the level");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse level specific config data.
|
||||
AZStd::string const sLevelNameOnly(PathUtil::GetFileName(levelName));
|
||||
|
||||
if (!sLevelNameOnly.empty())
|
||||
{
|
||||
const char* controlsPath = nullptr;
|
||||
Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath);
|
||||
if (controlsPath)
|
||||
{
|
||||
AZStd::string sAudioLevelPath(controlsPath);
|
||||
sAudioLevelPath.append("levels/");
|
||||
sAudioLevelPath += sLevelNameOnly;
|
||||
|
||||
Audio::SAudioManagerRequestData<Audio::eAMRT_PARSE_CONTROLS_DATA> oAMData(
|
||||
sAudioLevelPath.c_str(), Audio::eADS_LEVEL_SPECIFIC);
|
||||
Audio::SAudioRequest oAudioRequestData;
|
||||
oAudioRequestData.nFlags =
|
||||
(Audio::eARF_PRIORITY_HIGH |
|
||||
Audio::eARF_EXECUTE_BLOCKING); // Needs to be blocking so data is available for next preloading request!
|
||||
oAudioRequestData.pData = &oAMData;
|
||||
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData);
|
||||
|
||||
Audio::SAudioManagerRequestData<Audio::eAMRT_PARSE_PRELOADS_DATA> oAMData2(
|
||||
sAudioLevelPath.c_str(), Audio::eADS_LEVEL_SPECIFIC);
|
||||
oAudioRequestData.pData = &oAMData2;
|
||||
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData);
|
||||
|
||||
Audio::TAudioPreloadRequestID nPreloadRequestID = INVALID_AUDIO_PRELOAD_REQUEST_ID;
|
||||
|
||||
Audio::AudioSystemRequestBus::BroadcastResult(
|
||||
nPreloadRequestID, &Audio::AudioSystemRequestBus::Events::GetAudioPreloadRequestID, sLevelNameOnly.c_str());
|
||||
if (nPreloadRequestID != INVALID_AUDIO_PRELOAD_REQUEST_ID)
|
||||
{
|
||||
Audio::SAudioManagerRequestData<Audio::eAMRT_PRELOAD_SINGLE_REQUEST> requestData(nPreloadRequestID, true);
|
||||
oAudioRequestData.pData = &requestData;
|
||||
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AZ::Data::Asset<AzFramework::Spawnable> rootSpawnable(
|
||||
rootSpawnableAssetId, azrtti_typeid<AzFramework::Spawnable>(), levelName);
|
||||
|
||||
m_rootSpawnableId = rootSpawnableAssetId;
|
||||
m_rootSpawnableGeneration = AzFramework::RootSpawnableInterface::Get()->AssignRootSpawnable(rootSpawnable);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Movie system must be reset after entities.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IMovieSystem* movieSys = gEnv->pMovieSystem;
|
||||
if (movieSys != NULL)
|
||||
{
|
||||
// bSeekAllToStart needs to be false here as it's only of interest in the editor
|
||||
movieSys->Reset(true, false);
|
||||
}
|
||||
|
||||
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_PRECACHE);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Notify 3D engine that loading finished
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
gEnv->p3DEngine->PostLoadLevel();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
gEnv->pConsole->SetScrollMax(600 / 2);
|
||||
|
||||
pPak->GetResourceList(AZ::IO::IArchive::RFOM_NextLevel)->Clear();
|
||||
|
||||
if (pSpamDelay)
|
||||
{
|
||||
pSpamDelay->Set(spamDelay);
|
||||
}
|
||||
|
||||
m_bLevelLoaded = true;
|
||||
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_END);
|
||||
}
|
||||
|
||||
GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_LOAD_END, 0, 0);
|
||||
|
||||
if (auto cvar = gEnv->pConsole->GetCVar("sv_map"); cvar)
|
||||
{
|
||||
cvar->Set(levelName);
|
||||
}
|
||||
|
||||
gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_PRECACHE_START, 0, 0);
|
||||
|
||||
m_pSystem->SetThreadState(ESubsys_Physics, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::PrepareNextLevel(const char* levelName)
|
||||
{
|
||||
AZ::Data::AssetId rootSpawnableAssetId;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
rootSpawnableAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, levelName, nullptr, false);
|
||||
if (!rootSpawnableAssetId.IsValid())
|
||||
{
|
||||
// alert the listener
|
||||
OnLevelNotFound(levelName);
|
||||
return;
|
||||
}
|
||||
|
||||
// This work not required in-editor.
|
||||
if (!gEnv || !gEnv->IsEditor())
|
||||
{
|
||||
m_levelLoadStartTime = gEnv->pTimer->GetAsyncTime();
|
||||
|
||||
// switched to level heap, so now imm start the loading screen (renderer will be reinitialized in the levelheap)
|
||||
gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_LOAD_START_LOADINGSCREEN, 0, 0);
|
||||
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_PREPARE);
|
||||
}
|
||||
|
||||
OnPrepareNextLevel(levelName);
|
||||
}
|
||||
|
||||
void SpawnableLevelSystem::OnPrepareNextLevel(const char* levelName)
|
||||
{
|
||||
AZ_TracePrintf("LevelSystem", "Level system is preparing to load '%s'\n", levelName);
|
||||
|
||||
for (auto& listener : m_listeners)
|
||||
{
|
||||
listener->OnPrepareNextLevel(levelName);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::OnLevelNotFound(const char* levelName)
|
||||
{
|
||||
AZ_Error("LevelSystem", false, "Requested level not found: '%s'\n", levelName);
|
||||
|
||||
for (auto& listener : m_listeners)
|
||||
{
|
||||
listener->OnLevelNotFound(levelName);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::OnLoadingStart(const char* levelName)
|
||||
{
|
||||
AZ_TracePrintf("LevelSystem", "Level system is loading '%s'\n", levelName);
|
||||
|
||||
if (gEnv->pCryPak->GetRecordFileOpenList() == AZ::IO::IArchive::RFOM_EngineStartup)
|
||||
{
|
||||
gEnv->pCryPak->RecordFileOpen(AZ::IO::IArchive::RFOM_Level);
|
||||
}
|
||||
|
||||
m_fLastTime = gEnv->pTimer->GetAsyncCurTime();
|
||||
|
||||
GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_LOAD_START, 0, 0);
|
||||
|
||||
LOADING_TIME_PROFILE_SECTION(gEnv->pSystem);
|
||||
|
||||
for (auto& listener : m_listeners)
|
||||
{
|
||||
listener->OnLoadingStart(levelName);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::OnLoadingError(const char* levelName, const char* error)
|
||||
{
|
||||
AZ_Error("LevelSystem", false, "Error loading level '%s': %s\n", levelName, error);
|
||||
|
||||
if (gEnv->pRenderer)
|
||||
{
|
||||
gEnv->pRenderer->SetTexturePrecaching(false);
|
||||
}
|
||||
|
||||
for (auto& listener : m_listeners)
|
||||
{
|
||||
listener->OnLoadingError(levelName, error);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::OnLoadingComplete(const char* levelName)
|
||||
{
|
||||
CTimeValue t = gEnv->pTimer->GetAsyncTime();
|
||||
m_fLastLevelLoadTime = (t - m_levelLoadStartTime).GetSeconds();
|
||||
|
||||
LogLoadingTime();
|
||||
|
||||
m_nLoadedLevelsCount++;
|
||||
|
||||
// Hide console after loading.
|
||||
gEnv->pConsole->ShowConsole(false);
|
||||
|
||||
for (auto& listener : m_listeners)
|
||||
{
|
||||
listener->OnLoadingComplete(levelName);
|
||||
}
|
||||
|
||||
#if AZ_LOADSCREENCOMPONENT_ENABLED
|
||||
EBUS_EVENT(LoadScreenBus, Stop);
|
||||
#endif // if AZ_LOADSCREENCOMPONENT_ENABLED
|
||||
|
||||
AZ_TracePrintf("LevelSystem", "Level load complete: '%s'\n", levelName);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::OnLoadingProgress(const char* levelName, int progressAmount)
|
||||
{
|
||||
for (auto& listener : m_listeners)
|
||||
{
|
||||
listener->OnLoadingProgress(levelName, progressAmount);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void SpawnableLevelSystem::OnUnloadComplete(const char* levelName)
|
||||
{
|
||||
for (auto& listener : m_listeners)
|
||||
{
|
||||
listener->OnUnloadComplete(levelName);
|
||||
}
|
||||
|
||||
AZ_TracePrintf("LevelSystem", "Level unload complete: '%s'\n", levelName);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SpawnableLevelSystem::LogLoadingTime()
|
||||
{
|
||||
if (gEnv->IsEditor())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetISystem()->IsDevMode())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char vers[128];
|
||||
GetISystem()->GetFileVersion().ToString(vers, sizeof(vers));
|
||||
|
||||
const char* sChain = "";
|
||||
if (m_nLoadedLevelsCount > 0)
|
||||
{
|
||||
sChain = " (Chained)";
|
||||
}
|
||||
|
||||
AZStd::string text;
|
||||
text.format(
|
||||
"Game Level Load Time: [%s] Level %s loaded in %.2f seconds%s", vers, m_lastLevelName.c_str(), m_fLastLevelLoadTime, sChain);
|
||||
gEnv->pLog->Log(text.c_str());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SpawnableLevelSystem::UnloadLevel()
|
||||
{
|
||||
if (gEnv->IsEditor())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_lastLevelName.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_TracePrintf("LevelSystem", "UnloadLevel Start\n");
|
||||
INDENT_LOG_DURING_SCOPE();
|
||||
|
||||
// Flush core buses. We're about to unload Cry modules and need to ensure we don't have module-owned functions left behind.
|
||||
AZ::Data::AssetBus::ExecuteQueuedEvents();
|
||||
AZ::TickBus::ExecuteQueuedEvents();
|
||||
AZ::MainThreadRenderRequestBus::ExecuteQueuedEvents();
|
||||
|
||||
if (gEnv && gEnv->pSystem)
|
||||
{
|
||||
// clear all error messages to prevent stalling due to runtime file access check during chainloading
|
||||
gEnv->pSystem->ClearErrorMessages();
|
||||
}
|
||||
|
||||
if (gEnv && gEnv->pCryPak)
|
||||
{
|
||||
gEnv->pCryPak->DisableRuntimeFileAccess(false);
|
||||
}
|
||||
|
||||
CTimeValue tBegin = gEnv->pTimer->GetAsyncTime();
|
||||
|
||||
I3DEngine* p3DEngine = gEnv->p3DEngine;
|
||||
if (p3DEngine)
|
||||
{
|
||||
IDeferredPhysicsEventManager* pPhysEventManager = p3DEngine->GetDeferredPhysicsEventManager();
|
||||
if (pPhysEventManager)
|
||||
{
|
||||
// clear deferred physics queues before renderer, since we could have jobs running
|
||||
// which access a rendermesh
|
||||
pPhysEventManager->ClearDeferredEvents();
|
||||
}
|
||||
}
|
||||
|
||||
// AM: Flush render thread (Flush is not exposed - using EndFrame())
|
||||
// We are about to delete resources that could be in use
|
||||
if (gEnv->pRenderer)
|
||||
{
|
||||
gEnv->pRenderer->EndFrame();
|
||||
|
||||
bool isLoadScreenPlaying = false;
|
||||
#if AZ_LOADSCREENCOMPONENT_ENABLED
|
||||
LoadScreenBus::BroadcastResult(isLoadScreenPlaying, &LoadScreenBus::Events::IsPlaying);
|
||||
#endif // if AZ_LOADSCREENCOMPONENT_ENABLED
|
||||
|
||||
// force a black screen as last render command.
|
||||
// if load screen is playing do not call this draw as it may lead to a crash due to UI loading code getting
|
||||
// pumped while loading the shaders for this draw.
|
||||
if (!isLoadScreenPlaying)
|
||||
{
|
||||
gEnv->pRenderer->BeginFrame();
|
||||
gEnv->pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
|
||||
gEnv->pRenderer->Draw2dImage(0, 0, 800, 600, -1, 0.0f, 0.0f, 1.0f, 1.0f, 0.f, 0.0f, 0.0f, 0.0f, 1.0, 0.f);
|
||||
gEnv->pRenderer->EndFrame();
|
||||
}
|
||||
|
||||
// flush any outstanding texture requests
|
||||
gEnv->pRenderer->FlushPendingTextureTasks();
|
||||
}
|
||||
|
||||
// Clear level entities and prefab instances.
|
||||
EBUS_EVENT(AzFramework::GameEntityContextRequestBus, ResetGameContext);
|
||||
|
||||
if (gEnv->pMovieSystem)
|
||||
{
|
||||
gEnv->pMovieSystem->Reset(false, false);
|
||||
gEnv->pMovieSystem->RemoveAllSequences();
|
||||
}
|
||||
|
||||
// Unload level specific audio binary data.
|
||||
Audio::SAudioManagerRequestData<Audio::eAMRT_UNLOAD_AFCM_DATA_BY_SCOPE> oAMData(Audio::eADS_LEVEL_SPECIFIC);
|
||||
Audio::SAudioRequest oAudioRequestData;
|
||||
oAudioRequestData.nFlags = (Audio::eARF_PRIORITY_HIGH | Audio::eARF_EXECUTE_BLOCKING);
|
||||
oAudioRequestData.pData = &oAMData;
|
||||
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData);
|
||||
|
||||
// Now unload level specific audio config data.
|
||||
Audio::SAudioManagerRequestData<Audio::eAMRT_CLEAR_CONTROLS_DATA> oAMData2(Audio::eADS_LEVEL_SPECIFIC);
|
||||
oAudioRequestData.pData = &oAMData2;
|
||||
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData);
|
||||
|
||||
Audio::SAudioManagerRequestData<Audio::eAMRT_CLEAR_PRELOADS_DATA> oAMData3(Audio::eADS_LEVEL_SPECIFIC);
|
||||
oAudioRequestData.pData = &oAMData3;
|
||||
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData);
|
||||
|
||||
// Reset the camera to (0,0,0) which is the invalid/uninitialised state
|
||||
CCamera defaultCam;
|
||||
m_pSystem->SetViewCamera(defaultCam);
|
||||
|
||||
OnUnloadComplete(m_lastLevelName.c_str());
|
||||
|
||||
AzFramework::RootSpawnableInterface::Get()->ReleaseRootSpawnable();
|
||||
|
||||
m_lastLevelName.clear();
|
||||
|
||||
GetISystem()->GetIResourceManager()->UnloadLevel();
|
||||
|
||||
/*
|
||||
Force Lua garbage collection before p3DEngine->UnloadLevel() and pRenderer->FreeResources(flags) are called.
|
||||
p3DEngine->UnloadLevel() will destroy particle emitters even if they're still referenced by Lua objects that are yet to be
|
||||
collected. (as per comment in 3dEngineLoad.cpp (line 501) - "Force to clean all particles that are left, even if still referenced.").
|
||||
Then, during the next GC cycle, Lua finally cleans up, the particle emitter smart pointers will be pointing to invalid memory).
|
||||
Normally the GC step is triggered at the end of this method (by the ESYSTEM_EVENT_LEVEL_POST_UNLOAD event), which is too late
|
||||
(after the render resources have been purged).
|
||||
This extra GC step takes a few ms more level unload time, which is a small price for fixing nasty crashes.
|
||||
If, however, we wanted to claim it back, we could potentially get rid of the GC step that is triggered by
|
||||
ESYSTEM_EVENT_LEVEL_POST_UNLOAD to break even.
|
||||
*/
|
||||
|
||||
EBUS_EVENT(AZ::ScriptSystemRequestBus, GarbageCollect);
|
||||
|
||||
// Delete engine resources
|
||||
if (p3DEngine)
|
||||
{
|
||||
p3DEngine->UnloadLevel();
|
||||
}
|
||||
// Force to clean render resources left after deleting all objects and materials.
|
||||
IRenderer* pRenderer = gEnv->pRenderer;
|
||||
if (pRenderer)
|
||||
{
|
||||
pRenderer->FlushRTCommands(true, true, true);
|
||||
|
||||
CryComment("Deleting Render meshes, render resources and flush texture streaming");
|
||||
// This may also release some of the materials.
|
||||
int flags = FRR_DELETED_MESHES | FRR_FLUSH_TEXTURESTREAMING | FRR_OBJECTS | FRR_RENDERELEMENTS | FRR_RP_BUFFERS | FRR_POST_EFFECTS;
|
||||
|
||||
// Always keep the system resources around in the editor.
|
||||
// If a level load fails for any reason, then do not unload the system resources, otherwise we will not have any system resources to
|
||||
// continue rendering the console and debug output text.
|
||||
if (!gEnv->IsEditor() && !GetLevelLoadFailed())
|
||||
{
|
||||
flags |= FRR_SYSTEM_RESOURCES;
|
||||
}
|
||||
|
||||
pRenderer->FreeResources(flags);
|
||||
CryComment("done");
|
||||
}
|
||||
|
||||
// Perform level unload procedures for the LyShine UI system
|
||||
if (gEnv && gEnv->pLyShine)
|
||||
{
|
||||
gEnv->pLyShine->OnLevelUnload();
|
||||
}
|
||||
|
||||
m_bLevelLoaded = false;
|
||||
|
||||
CTimeValue tUnloadTime = gEnv->pTimer->GetAsyncTime() - tBegin;
|
||||
AZ_TracePrintf("LevelSystem", "UnloadLevel End: %.1f sec\n", tUnloadTime.GetSeconds());
|
||||
|
||||
// Must be sent last.
|
||||
// Cleanup all containers
|
||||
GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_POST_UNLOAD, 0, 0);
|
||||
AzFramework::InputChannelRequestBus::Broadcast(&AzFramework::InputChannelRequests::ResetState);
|
||||
}
|
||||
|
||||
void SpawnableLevelSystem::OnRootSpawnableAssigned(
|
||||
[[maybe_unused]] AZ::Data::Asset<AzFramework::Spawnable> rootSpawnable, [[maybe_unused]] uint32_t generation)
|
||||
{
|
||||
}
|
||||
|
||||
void SpawnableLevelSystem::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace LegacyLevelSystem
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ILevelSystem.h"
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzFramework/Archive/IArchive.h>
|
||||
#include <AzFramework/Spawnable/RootSpawnableInterface.h>
|
||||
|
||||
namespace LegacyLevelSystem
|
||||
{
|
||||
|
||||
class SpawnableLevelSystem
|
||||
: public ILevelSystem
|
||||
, public AzFramework::RootSpawnableNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
explicit SpawnableLevelSystem(ISystem* pSystem);
|
||||
~SpawnableLevelSystem() override;
|
||||
|
||||
// ILevelSystem
|
||||
void Release() override;
|
||||
|
||||
void AddListener(ILevelSystemListener* pListener) override;
|
||||
void RemoveListener(ILevelSystemListener* pListener) override;
|
||||
|
||||
bool LoadLevel(const char* levelName) override;
|
||||
void UnloadLevel() override;
|
||||
bool IsLevelLoaded() override;
|
||||
const char* GetCurrentLevelName() const override;
|
||||
|
||||
// If the level load failed then we need to have a different shutdown procedure vs when a level is naturally unloaded
|
||||
void SetLevelLoadFailed(bool loadFailed) override;
|
||||
bool GetLevelLoadFailed() override;
|
||||
AZ::Data::AssetType GetLevelAssetType() const override;
|
||||
|
||||
// The following methods are deprecated from ILevelSystem and will be removed once slice support is removed.
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
void Rescan([[maybe_unused]] const char* levelsFolder) override;
|
||||
int GetLevelCount() override;
|
||||
ILevelInfo* GetLevelInfo([[maybe_unused]] int level) override;
|
||||
ILevelInfo* GetLevelInfo([[maybe_unused]] const char* levelName) override;
|
||||
|
||||
private:
|
||||
void OnRootSpawnableAssigned(AZ::Data::Asset<AzFramework::Spawnable> rootSpawnable, uint32_t generation) override;
|
||||
void OnRootSpawnableReleased(uint32_t generation) override;
|
||||
|
||||
void PrepareNextLevel(const char* levelName);
|
||||
bool LoadLevelInternal(const char* levelName);
|
||||
|
||||
// Methods to notify ILevelSystemListener
|
||||
void OnPrepareNextLevel(const char* levelName);
|
||||
void OnLevelNotFound(const char* levelName);
|
||||
void OnLoadingStart(const char* levelName);
|
||||
void OnLoadingComplete(const char* levelName);
|
||||
void OnLoadingError(const char* levelName, const char* error);
|
||||
void OnLoadingProgress(const char* levelName, int progressAmount);
|
||||
void OnUnloadComplete(const char* levelName);
|
||||
|
||||
void LogLoadingTime();
|
||||
|
||||
ISystem* m_pSystem{nullptr};
|
||||
|
||||
AZStd::string m_lastLevelName;
|
||||
float m_fLastLevelLoadTime{0.0f};
|
||||
float m_fLastTime{0.0f};
|
||||
|
||||
bool m_bLevelLoaded{false};
|
||||
bool m_levelLoadFailed{false};
|
||||
|
||||
int m_nLoadedLevelsCount{0};
|
||||
|
||||
CTimeValue m_levelLoadStartTime;
|
||||
|
||||
AZStd::vector<ILevelSystemListener*> m_listeners;
|
||||
|
||||
// Information about the currently-loaded root spawnable, used for tracking loads and unloads.
|
||||
uint64_t m_rootSpawnableGeneration{0};
|
||||
AZ::Data::AssetId m_rootSpawnableId{};
|
||||
};
|
||||
|
||||
} // namespace LegacyLevelSystem
|
||||
@@ -92,8 +92,8 @@ public:
|
||||
virtual void UnregisterConsoleVariables();
|
||||
virtual void AddCallback(ILogCallback* pCallback);
|
||||
virtual void RemoveCallback(ILogCallback* pCallback);
|
||||
virtual void LogV(const ELogType ineType, int flags, const char* szFormat, va_list args);
|
||||
virtual void LogV(const ELogType ineType, const char* szFormat, va_list args);
|
||||
virtual void LogV(ELogType ineType, int flags, const char* szFormat, va_list args);
|
||||
virtual void LogV(ELogType ineType, const char* szFormat, va_list args);
|
||||
virtual void Update();
|
||||
virtual const char* GetModuleFilter();
|
||||
virtual void FlushAndClose();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "System.h"
|
||||
#include "MaterialUtils.h"
|
||||
#include <CryPath.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzFramework/Archive/Archive.h>
|
||||
#include <AzFramework/Archive/INestedArchive.h>
|
||||
@@ -216,12 +217,20 @@ void CResourceManager::PrepareLevel(const char* sLevelFolder, const char* sLevel
|
||||
|
||||
if (g_cvars.archiveVars.nLoadCache)
|
||||
{
|
||||
CryPathString levelpak = PathUtil::Make(sLevelFolder, LEVEL_PAK_FILENAME);
|
||||
size_t nPakFileSize = gEnv->pCryPak->FGetSize(levelpak.c_str());
|
||||
if (nPakFileSize < LEVEL_PAK_INMEMORY_MAXSIZE) // 10 megs.
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
|
||||
// The prefab system doesn't use level.pak
|
||||
if (!usePrefabSystemForLevels)
|
||||
{
|
||||
// Force level.pak from this level in memory.
|
||||
gEnv->pCryPak->LoadPakToMemory(LEVEL_PAK_FILENAME, AZ::IO::IArchive::eInMemoryPakLocale_GPU);
|
||||
CryPathString levelpak = PathUtil::Make(sLevelFolder, LEVEL_PAK_FILENAME);
|
||||
size_t nPakFileSize = gEnv->pCryPak->FGetSize(levelpak.c_str());
|
||||
if (nPakFileSize < LEVEL_PAK_INMEMORY_MAXSIZE) // 10 megs.
|
||||
{
|
||||
// Force level.pak from this level in memory.
|
||||
gEnv->pCryPak->LoadPakToMemory(LEVEL_PAK_FILENAME, AZ::IO::IArchive::eInMemoryPakLocale_GPU);
|
||||
}
|
||||
}
|
||||
|
||||
gEnv->pCryPak->LoadPakToMemory(ENGINE_PAK_FILENAME, AZ::IO::IArchive::eInMemoryPakLocale_GPU);
|
||||
@@ -584,8 +593,15 @@ void CResourceManager::UnloadAllLevelCachePaks(bool bLevelLoadEnd)
|
||||
{
|
||||
gEnv->pCryPak->LoadPakToMemory(ENGINE_PAK_FILENAME, AZ::IO::IArchive::eInMemoryPakLocale_Unload);
|
||||
|
||||
// Force level.pak out of memory.
|
||||
gEnv->pCryPak->LoadPakToMemory(LEVEL_PAK_FILENAME, AZ::IO::IArchive::eInMemoryPakLocale_Unload);
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
|
||||
if (!usePrefabSystemForLevels)
|
||||
{
|
||||
// Force level.pak out of memory.
|
||||
gEnv->pCryPak->LoadPakToMemory(LEVEL_PAK_FILENAME, AZ::IO::IArchive::eInMemoryPakLocale_Unload);
|
||||
}
|
||||
}
|
||||
if (!bLevelLoadEnd)
|
||||
{
|
||||
|
||||
@@ -1501,7 +1501,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
if (maxFPS == 0 && vSync == 0)
|
||||
{
|
||||
ILevelSystem* pLvlSys = GetILevelSystem();
|
||||
const bool inLevel = pLvlSys && pLvlSys->GetCurrentLevel() != 0;
|
||||
const bool inLevel = pLvlSys && pLvlSys->IsLevelLoaded();
|
||||
maxFPS = !inLevel || IsPaused() ? 60 : 0;
|
||||
}
|
||||
|
||||
@@ -1791,23 +1791,6 @@ bool CSystem::UpdatePostTickBus(int updateFlags, int nPauseMode)
|
||||
GetIViewSystem()->Update(min(gEnv->pTimer->GetFrameTime(), 0.1f));
|
||||
}
|
||||
|
||||
if (gEnv->pLyShine)
|
||||
{
|
||||
// Tell the UI system the size of the viewport we are rendering to - this drives the
|
||||
// canvas size for full screen UI canvases. It needs to be set before either pLyShine->Update or
|
||||
// pLyShine->Render are called. It must match the viewport size that the input system is using.
|
||||
AZ::Vector2 viewportSize;
|
||||
viewportSize.SetX(static_cast<float>(gEnv->pRenderer->GetOverlayWidth()));
|
||||
viewportSize.SetY(static_cast<float>(gEnv->pRenderer->GetOverlayHeight()));
|
||||
gEnv->pLyShine->SetViewportSize(viewportSize);
|
||||
|
||||
bool isUiPaused = gEnv->pTimer->IsTimerPaused(ITimer::ETIMER_UI);
|
||||
if (!isUiPaused)
|
||||
{
|
||||
gEnv->pLyShine->Update(gEnv->pTimer->GetFrameTime(ITimer::ETIMER_UI));
|
||||
}
|
||||
}
|
||||
|
||||
// Begin occlusion job after setting the correct camera.
|
||||
gEnv->p3DEngine->PrepareOcclusion(GetViewCamera());
|
||||
|
||||
|
||||
@@ -612,7 +612,7 @@ public:
|
||||
virtual void SetConfigSpec(ESystemConfigSpec spec, ESystemConfigPlatform platform, bool bClient);
|
||||
virtual ESystemConfigSpec GetMaxConfigSpec() const;
|
||||
virtual ESystemConfigPlatform GetConfigPlatform() const;
|
||||
virtual void SetConfigPlatform(const ESystemConfigPlatform platform);
|
||||
virtual void SetConfigPlatform(ESystemConfigPlatform platform);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual int SetThreadState(ESubsystem subsys, bool bActive);
|
||||
@@ -746,7 +746,7 @@ public:
|
||||
|
||||
// interface ISystem -------------------------------------------
|
||||
virtual IDataProbe* GetIDataProbe() { return m_pDataProbe; };
|
||||
virtual void SetForceNonDevMode(const bool bValue);
|
||||
virtual void SetForceNonDevMode(bool bValue);
|
||||
virtual bool GetForceNonDevMode() const;
|
||||
virtual bool WasInDevMode() const { return m_bWasInDevMode; };
|
||||
virtual bool IsDevMode() const { return m_bInDevMode && !GetForceNonDevMode(); }
|
||||
@@ -759,7 +759,7 @@ public:
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
virtual void AutoDetectSpec(const bool detectResolution);
|
||||
virtual void AutoDetectSpec(bool detectResolution);
|
||||
|
||||
virtual void AsyncMemcpy(void* dst, const void* src, size_t size, int nFlags, volatile int* sync)
|
||||
{
|
||||
@@ -1084,7 +1084,7 @@ public:
|
||||
}
|
||||
|
||||
virtual ESystemGlobalState GetSystemGlobalState(void);
|
||||
virtual void SetSystemGlobalState(const ESystemGlobalState systemGlobalState);
|
||||
virtual void SetSystemGlobalState(ESystemGlobalState systemGlobalState);
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
virtual bool IsSavingResourceList() const { return (g_cvars.archiveVars.nSaveLevelResourceList != 0); }
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include <AzCore/IO/Streamer/Streamer.h>
|
||||
#include <AzCore/IO/Streamer/StreamerComponent.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzFramework/Asset/AssetProcessorMessages.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
@@ -131,6 +132,7 @@
|
||||
#include "ServiceNetwork.h"
|
||||
#include "RemoteCommand.h"
|
||||
#include "LevelSystem/LevelSystem.h"
|
||||
#include "LevelSystem/SpawnableLevelSystem.h"
|
||||
#include "ViewSystem/ViewSystem.h"
|
||||
#include <CrySystemBus.h>
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
@@ -310,8 +312,6 @@ namespace
|
||||
|
||||
//static int g_sysSpecChanged = false;
|
||||
|
||||
const char* g_szLvlResExt = "_LvlRes.txt";
|
||||
|
||||
struct SCVarsClientConfigSink
|
||||
: public ILoadConfigurationEntrySink
|
||||
{
|
||||
@@ -1517,27 +1517,16 @@ bool CSystem::InitFileSystem()
|
||||
m_pUserCallback->OnInitProgress("Initializing File System...");
|
||||
}
|
||||
|
||||
bool bLvlRes = false; // true: all assets since executable start are recorded, false otherwise
|
||||
|
||||
// get the DirectInstance FileIOBase which should be the AZ::LocalFileIO
|
||||
m_env.pFileIO = AZ::IO::FileIOBase::GetDirectInstance();
|
||||
m_env.pResourceCompilerHelper = nullptr;
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
const ICmdLineArg* pArg = m_pCmdLine->FindArg(eCLAT_Pre, "LvlRes"); // -LvlRes command line option
|
||||
|
||||
if (pArg)
|
||||
{
|
||||
bLvlRes = true;
|
||||
}
|
||||
#endif // !defined(_RELEASE)
|
||||
|
||||
m_env.pCryPak = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
m_env.pFileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
AZ_Assert(m_env.pCryPak, "CryPak has not been initialized on AZ::Interface");
|
||||
AZ_Assert(m_env.pFileIO, "FileIOBase has not been initialized");
|
||||
|
||||
if (m_bEditor || bLvlRes)
|
||||
if (m_bEditor)
|
||||
{
|
||||
m_env.pCryPak->RecordFileOpen(AZ::IO::IArchive::RFOM_EngineStartup);
|
||||
}
|
||||
@@ -2212,43 +2201,6 @@ public:
|
||||
|
||||
using CommandRegisteredHandler = AZ::IConsole::ConsoleCommandRegisteredEvent::Handler;
|
||||
static inline CommandRegisteredHandler s_commandRegisteredHandler = CommandRegisteredHandler([](AZ::ConsoleFunctorBase* functor) { Visit(functor); });
|
||||
|
||||
using CommandInvokedHandler = AZ::ConsoleCommandInvokedEvent::Handler;
|
||||
static inline CommandInvokedHandler s_commandInvokedHandler = CommandInvokedHandler([]
|
||||
(
|
||||
AZStd::string_view command,
|
||||
const AZ::ConsoleCommandContainer& args,
|
||||
[[maybe_unused]] AZ::ConsoleFunctorFlags flags,
|
||||
AZ::ConsoleInvokedFrom invokedFrom
|
||||
)
|
||||
{
|
||||
if (invokedFrom == AZ::ConsoleInvokedFrom::CryBinding)
|
||||
{
|
||||
// If a command originated from the cry console, do not echo it back to the cry console
|
||||
return;
|
||||
}
|
||||
AZ::CVarFixedString joinedCommand = AZ::CVarFixedString(command) + " ";
|
||||
AZ::StringFunc::Join(joinedCommand, args.begin(), args.end(), " ");
|
||||
gEnv->pConsole->ExecuteString(joinedCommand.c_str(), true);
|
||||
});
|
||||
|
||||
using CommandNotFoundHandler = AZ::DispatchCommandNotFoundEvent::Handler;
|
||||
static inline CommandNotFoundHandler s_commandNotFoundHandler = CommandNotFoundHandler([]
|
||||
(
|
||||
AZStd::string_view command,
|
||||
const AZ::ConsoleCommandContainer& args,
|
||||
AZ::ConsoleInvokedFrom invokedFrom
|
||||
)
|
||||
{
|
||||
if (invokedFrom == AZ::ConsoleInvokedFrom::CryBinding)
|
||||
{
|
||||
// If a command originated from the cry console, do not echo it back to the cry console
|
||||
return;
|
||||
}
|
||||
AZ::CVarFixedString joinedCommand = AZ::CVarFixedString(command) + " ";
|
||||
AZ::StringFunc::Join(joinedCommand, args.begin(), args.end(), " ");
|
||||
gEnv->pConsole->ExecuteString(joinedCommand.c_str(), true);
|
||||
});
|
||||
};
|
||||
|
||||
// System initialization
|
||||
@@ -3193,7 +3145,19 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// LEVEL SYSTEM
|
||||
m_pLevelSystem = new LegacyLevelSystem::CLevelSystem(this, "levels");
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
|
||||
if (usePrefabSystemForLevels)
|
||||
{
|
||||
m_pLevelSystem = new LegacyLevelSystem::SpawnableLevelSystem(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
m_pLevelSystem = new LegacyLevelSystem::CLevelSystem(this, ILevelSystem::GetLevelsDirectoryName());
|
||||
}
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init Level System");
|
||||
|
||||
@@ -3276,8 +3240,6 @@ AZ_POP_DISABLE_WARNING
|
||||
// Az to Cry console binding
|
||||
AZ::Interface<AZ::IConsole>::Get()->VisitRegisteredFunctors([](AZ::ConsoleFunctorBase* functor) { AzConsoleToCryConsoleBinder::Visit(functor); });
|
||||
AzConsoleToCryConsoleBinder::s_commandRegisteredHandler.Connect(AZ::Interface<AZ::IConsole>::Get()->GetConsoleCommandRegisteredEvent());
|
||||
AzConsoleToCryConsoleBinder::s_commandInvokedHandler.Connect(AZ::Interface<AZ::IConsole>::Get()->GetConsoleCommandInvokedEvent());
|
||||
AzConsoleToCryConsoleBinder::s_commandNotFoundHandler.Connect(AZ::Interface<AZ::IConsole>::Get()->GetDispatchCommandNotFoundEvent());
|
||||
|
||||
// final tryflush to be sure that all framework init request have been processed
|
||||
if (!startupParams.bShaderCacheGen && m_env.pRenderer)
|
||||
@@ -3384,548 +3346,6 @@ static string ConcatPath(const char* szPart1, const char* szPart2)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CLvlRes_base
|
||||
{
|
||||
public:
|
||||
|
||||
// destructor
|
||||
virtual ~CLvlRes_base()
|
||||
{
|
||||
}
|
||||
|
||||
void RegisterAllLevelPaks(const string& sPath)
|
||||
{
|
||||
string sPathPattern = ConcatPath(sPath, "*");
|
||||
|
||||
AZ::IO::ArchiveFileIterator handle = gEnv->pCryPak->FindFirst(sPathPattern.c_str());
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
gEnv->pLog->LogError("ERROR: CLvlRes_base failed '%s'", sPathPattern.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory)
|
||||
{
|
||||
if (handle.m_filename != "." && handle.m_filename != "..")
|
||||
{
|
||||
RegisterAllLevelPaks(ConcatPath(sPath, handle.m_filename.data()));
|
||||
}
|
||||
}
|
||||
else if (HasRightExtension(handle.m_filename.data())) // open only the level paks if there is a LvlRes.txt, opening all would be too slow
|
||||
{
|
||||
OnPakEntry(sPath, handle.m_filename.data());
|
||||
}
|
||||
} while (handle = gEnv->pCryPak->FindNext(handle));
|
||||
|
||||
gEnv->pCryPak->FindClose(handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Process(const string& sPath)
|
||||
{
|
||||
string sPathPattern = ConcatPath(sPath, "*");
|
||||
|
||||
AZ::IO::ArchiveFileIterator handle = gEnv->pCryPak->FindFirst(sPathPattern.c_str());
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
gEnv->pLog->LogError("ERROR: LvlRes_finalstep failed '%s'", sPathPattern.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory)
|
||||
{
|
||||
if (handle.m_filename != "." && handle.m_filename != "..")
|
||||
{
|
||||
Process(ConcatPath(sPath, handle.m_filename.data()));
|
||||
}
|
||||
}
|
||||
else if (HasRightExtension(handle.m_filename.data()))
|
||||
{
|
||||
string sFilePath = ConcatPath(sPath, handle.m_filename.data());
|
||||
|
||||
gEnv->pLog->Log("CLvlRes_base processing '%s' ...", sFilePath.c_str());
|
||||
|
||||
AZ::IO::HandleType fileHandle = gEnv->pCryPak->FOpen(sFilePath.c_str(), "rb");
|
||||
|
||||
if (fileHandle != AZ::IO::InvalidHandle)
|
||||
{
|
||||
std::vector<char> vBuffer;
|
||||
|
||||
size_t len = gEnv->pCryPak->FGetSize(fileHandle);
|
||||
vBuffer.resize(len + 1);
|
||||
|
||||
if (len)
|
||||
{
|
||||
if (gEnv->pCryPak->FReadRaw(&vBuffer[0], len, 1, fileHandle) == 1)
|
||||
{
|
||||
vBuffer[len] = 0; // end terminator
|
||||
|
||||
char* p = &vBuffer[0];
|
||||
|
||||
while (*p)
|
||||
{
|
||||
while (*p != 0 && *p <= ' ') // jump over whitespace
|
||||
{
|
||||
++p;
|
||||
}
|
||||
|
||||
char* pLineStart = p;
|
||||
|
||||
while (*p != 0 && *p != 10 && *p != 13) // goto end of line
|
||||
{
|
||||
++p;
|
||||
}
|
||||
|
||||
char* pLineEnd = p;
|
||||
|
||||
while (*p != 0 && (*p == 10 || *p == 13)) // goto next line with data
|
||||
{
|
||||
++p;
|
||||
}
|
||||
|
||||
if (*pLineStart != ';') // if it's not a commented line
|
||||
{
|
||||
*pLineEnd = 0;
|
||||
OnFileEntry(pLineStart); // add line
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gEnv->pLog->LogError("Error: LvlRes_finalstep file open '%s' failed", sFilePath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
gEnv->pCryPak->FClose(fileHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
gEnv->pLog->LogError("Error: LvlRes_finalstep file open '%s' failed", sFilePath.c_str());
|
||||
}
|
||||
}
|
||||
} while (handle = gEnv->pCryPak->FindNext(handle));
|
||||
|
||||
gEnv->pCryPak->FindClose(handle);
|
||||
}
|
||||
|
||||
bool IsFileKnown(const char* szFilePath)
|
||||
{
|
||||
string sFilePath = szFilePath;
|
||||
|
||||
return m_UniqueFileList.find(sFilePath) != m_UniqueFileList.end();
|
||||
}
|
||||
|
||||
protected: // -------------------------------------------------------------------------
|
||||
|
||||
static bool HasRightExtension(const char* szFileName)
|
||||
{
|
||||
const char* szLvlResExt = szFileName;
|
||||
|
||||
size_t lenName = strlen(szLvlResExt);
|
||||
static size_t lenLvlExt = strlen(g_szLvlResExt);
|
||||
|
||||
if (lenName >= lenLvlExt)
|
||||
{
|
||||
szLvlResExt += lenName - lenLvlExt; // "test_LvlRes.txt" -> "_LvlRes.txt"
|
||||
}
|
||||
return azstricmp(szLvlResExt, g_szLvlResExt) == 0;
|
||||
}
|
||||
|
||||
// Arguments
|
||||
// sFilePath - e.g. "game/object/vehices/car01.dds"
|
||||
void OnFileEntry(const char* szFilePath)
|
||||
{
|
||||
string sFilePath = szFilePath;
|
||||
if (m_UniqueFileList.find(sFilePath) == m_UniqueFileList.end()) // to to file processing only once per file
|
||||
{
|
||||
m_UniqueFileList.insert(sFilePath);
|
||||
|
||||
ProcessFile(sFilePath);
|
||||
|
||||
gEnv->pLog->UpdateLoadingScreen(0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ProcessFile(const string& sFilePath) = 0;
|
||||
|
||||
virtual void OnPakEntry([[maybe_unused]] const string& sPath, [[maybe_unused]] const char* szPak) {}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
std::set<string> m_UniqueFileList; // to removed duplicate files
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class CLvlRes_finalstep
|
||||
: public CLvlRes_base
|
||||
{
|
||||
public:
|
||||
|
||||
// constructor
|
||||
CLvlRes_finalstep(const char* szPath)
|
||||
: m_sPath(szPath)
|
||||
{
|
||||
assert(szPath);
|
||||
}
|
||||
|
||||
// destructor
|
||||
virtual ~CLvlRes_finalstep()
|
||||
{
|
||||
// free registered paks
|
||||
std::set<string>::iterator it, end = m_RegisteredPakFiles.end();
|
||||
|
||||
for (it = m_RegisteredPakFiles.begin(); it != end; ++it)
|
||||
{
|
||||
string sName = *it;
|
||||
|
||||
gEnv->pCryPak->ClosePack(sName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// register a pak file so all files within do not become file entries but the pak file becomes
|
||||
void RegisterPak(const string& sPath, const char* szFile)
|
||||
{
|
||||
string sPak = ConcatPath(sPath, szFile);
|
||||
AZStd::string_view pakView{ sPak.c_str(), sPak.size() };
|
||||
gEnv->pCryPak->ClosePack(pakView); // so we don't get error for paks that were already opened
|
||||
|
||||
if (!gEnv->pCryPak->OpenPack(pakView))
|
||||
{
|
||||
CryLog("RegisterPak '%s' failed - file not present?", sPak.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
nMaxPath = 0x800
|
||||
};
|
||||
char szAbsPathBuf[nMaxPath];
|
||||
|
||||
const char* szAbsPath = gEnv->pCryPak->AdjustFileName({ sPak.c_str(), sPak.size() }, szAbsPathBuf, AZ_ARRAY_SIZE(szAbsPathBuf), 0);
|
||||
|
||||
// string sAbsPath = PathUtil::RemoveSlash(PathUtil::GetPath(szAbsPath));
|
||||
|
||||
// debug
|
||||
CryLog("RegisterPak '%s'", szAbsPath);
|
||||
|
||||
m_RegisteredPakFiles.insert(string(szAbsPath));
|
||||
|
||||
OnFileEntry(sPak); // include pak as file entry
|
||||
}
|
||||
|
||||
// finds a specific file
|
||||
static AZ::IO::ArchiveFileIterator FindFile(const char* szFilePath, const char* szFile)
|
||||
{
|
||||
AZ::IO::ArchiveFileIterator handle = gEnv->pCryPak->FindFirst(szFilePath);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (azstricmp(handle.m_filename.data(), szFile) == 0)
|
||||
{
|
||||
gEnv->pCryPak->FindClose(handle);
|
||||
return handle;
|
||||
}
|
||||
} while (handle = gEnv->pCryPak->FindNext(handle));
|
||||
|
||||
gEnv->pCryPak->FindClose(handle);
|
||||
return {};
|
||||
}
|
||||
|
||||
// slow but safe (to correct path and file name upper/lower case to the existing files)
|
||||
// some code might rely on the case (e.g. CVarGroup creation) so it's better to correct the case
|
||||
static void CorrectCaseInPlace(char* szFilePath)
|
||||
{
|
||||
// required for FindFirst, TODO: investigate as this seems wrong behavior
|
||||
{
|
||||
// jump over "Game"
|
||||
while (*szFilePath != '/' && *szFilePath != '\\' && *szFilePath != 0)
|
||||
{
|
||||
++szFilePath;
|
||||
}
|
||||
// jump over "/"
|
||||
if (*szFilePath != 0)
|
||||
{
|
||||
++szFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
char* szFile = szFilePath, * p = szFilePath;
|
||||
|
||||
for (;; )
|
||||
{
|
||||
if (*p == '/' || *p == '\\' || *p == 0)
|
||||
{
|
||||
char cOldChar = *p;
|
||||
*p = 0; // create zero termination
|
||||
|
||||
auto fileIterator = FindFile(szFilePath, szFile);
|
||||
|
||||
if (fileIterator)
|
||||
{
|
||||
assert(strlen(szFile) == fileIterator.m_filename.size());
|
||||
}
|
||||
|
||||
*p = cOldChar; // get back the old separator
|
||||
|
||||
if (!fileIterator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fileIterator.m_filename.copy(szFile, fileIterator.m_filename.size());
|
||||
|
||||
if (*p == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++p;
|
||||
szFile = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ProcessFile(const string& _sFilePath)
|
||||
{
|
||||
string sFilePath = _sFilePath;
|
||||
|
||||
CorrectCaseInPlace((char*)&sFilePath[0]);
|
||||
|
||||
gEnv->pLog->LogWithType(ILog::eAlways, "LvlRes: %s", sFilePath.c_str());
|
||||
|
||||
CCryFile file;
|
||||
std::vector<char> data;
|
||||
|
||||
if (!file.Open(sFilePath.c_str(), "rb"))
|
||||
{
|
||||
gEnv->pLog->LogError("ERROR: failed to open '%s'", sFilePath.c_str()); // pak not opened ?
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsInRegisteredPak(file.GetHandle()))
|
||||
{
|
||||
return; // then don't process as we include the pak
|
||||
}
|
||||
// Save this file in target folder.
|
||||
string trgFilename = PathUtil::Make(m_sPath, sFilePath);
|
||||
int fsize = file.GetLength();
|
||||
|
||||
size_t len = file.GetLength();
|
||||
|
||||
if (fsize > (int)data.size())
|
||||
{
|
||||
data.resize(fsize + 16);
|
||||
}
|
||||
|
||||
// Read data.
|
||||
file.ReadRaw(&data[0], fsize);
|
||||
|
||||
// Save this data to target file.
|
||||
string trgFileDir = PathUtil::ToDosPath(PathUtil::RemoveSlash(PathUtil::GetPath(trgFilename)));
|
||||
|
||||
gEnv->pFileIO->CreatePath(trgFileDir); // ensure path exists
|
||||
|
||||
// Create target file
|
||||
FILE* trgFile = nullptr;
|
||||
azfopen(&trgFile, trgFilename, "wb");
|
||||
|
||||
if (trgFile)
|
||||
{
|
||||
fwrite(&data[0], fsize, 1, trgFile);
|
||||
fclose(trgFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
gEnv->pLog->LogError("ERROR: failed to write '%s' (write protected/disk full/rights)", trgFilename.c_str());
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsInRegisteredPak(AZ::IO::HandleType fileHandle)
|
||||
{
|
||||
const char* szPak = gEnv->pCryPak->GetFileArchivePath(fileHandle);
|
||||
|
||||
if (!szPak)
|
||||
{
|
||||
return false; // outside pak
|
||||
}
|
||||
bool bInsideRegisteredPak = m_RegisteredPakFiles.find(szPak) != m_RegisteredPakFiles.end();
|
||||
|
||||
return bInsideRegisteredPak;
|
||||
}
|
||||
|
||||
virtual void OnPakEntry(const string& sPath, [[maybe_unused]] const char* szPak)
|
||||
{
|
||||
RegisterPak(sPath, "level.pak");
|
||||
RegisterPak(sPath, "levelmm.pak");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
string m_sPath; // directory path to store the assets e.g. "c:\temp\Out"
|
||||
std::set<string> m_RegisteredPakFiles; // abs path to pak files we registered e.g. "c:\MasterCD\game\GameData.pak", to avoid processing files inside these pak files - the ones we anyway want to include
|
||||
};
|
||||
|
||||
|
||||
class CLvlRes_findunused
|
||||
: public CLvlRes_base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void ProcessFile([[maybe_unused]] const string& sFilePath)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void LvlRes_finalstep(IConsoleCmdArgs* pParams)
|
||||
{
|
||||
assert(pParams);
|
||||
|
||||
uint32 dwCnt = pParams->GetArgCount();
|
||||
|
||||
if (dwCnt != 2)
|
||||
{
|
||||
gEnv->pLog->LogWithType(ILog::eError, "ERROR: sys_LvlRes_finalstep requires destination path as parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* szPath = pParams->GetArg(1);
|
||||
assert(szPath);
|
||||
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, "sys_LvlRes_finalstep %s ...", szPath);
|
||||
|
||||
// open console
|
||||
gEnv->pConsole->ShowConsole(true);
|
||||
|
||||
CLvlRes_finalstep sink(szPath);
|
||||
|
||||
sink.RegisterPak("@assets@", "GameData.pak");
|
||||
sink.RegisterPak("@assets@", "Shaders.pak");
|
||||
|
||||
sink.RegisterAllLevelPaks("levels");
|
||||
sink.Process("levels");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void _LvlRes_findunused_recursive(CLvlRes_findunused& sink, const string& sPath,
|
||||
uint32& dwUnused, uint32& dwAll)
|
||||
{
|
||||
string sPathPattern = ConcatPath(sPath, "*");
|
||||
|
||||
// ignore some directories
|
||||
if (azstricmp(sPath.c_str(), "Shaders") == 0
|
||||
|| azstricmp(sPath.c_str(), "ScreenShots") == 0
|
||||
|| azstricmp(sPath.c_str(), "Scripts") == 0
|
||||
|| azstricmp(sPath.c_str(), "Config") == 0
|
||||
|| azstricmp(sPath.c_str(), "LowSpec") == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// gEnv->pLog->Log("_LvlRes_findunused_recursive '%s'",sPath.c_str());
|
||||
|
||||
AZ::IO::ArchiveFileIterator handle = gEnv->pCryPak->FindFirst(sPathPattern.c_str());
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
gEnv->pLog->LogError("ERROR: _LvlRes_findunused_recursive failed '%s'", sPathPattern.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) == AZ::IO::FileDesc::Attribute::Subdirectory)
|
||||
{
|
||||
if (handle.m_filename != "." && handle.m_filename != "..")
|
||||
{
|
||||
_LvlRes_findunused_recursive(sink, ConcatPath(sPath, handle.m_filename.data()), dwUnused, dwAll);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string sFilePath = CryStringUtils::ToLower(ConcatPath(sPath, handle.m_filename.data()));
|
||||
enum
|
||||
{
|
||||
nMaxPath = 0x800
|
||||
};
|
||||
char szAbsPathBuf[nMaxPath];
|
||||
|
||||
gEnv->pCryPak->AdjustFileName(sFilePath.c_str(), szAbsPathBuf, AZ_ARRAY_SIZE(szAbsPathBuf), 0);
|
||||
|
||||
if (!sink.IsFileKnown(szAbsPathBuf))
|
||||
{
|
||||
gEnv->pLog->LogWithType(IMiniLog::eAlways, "%d, %s", (uint32)handle.m_fileDesc.nSize, szAbsPathBuf);
|
||||
++dwUnused;
|
||||
}
|
||||
++dwAll;
|
||||
}
|
||||
} while (handle = gEnv->pCryPak->FindNext(handle));
|
||||
|
||||
gEnv->pCryPak->FindClose(handle);
|
||||
}
|
||||
|
||||
|
||||
static void LvlRes_findunused([[maybe_unused]] IConsoleCmdArgs* pParams)
|
||||
{
|
||||
assert(pParams);
|
||||
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, "sys_LvlRes_findunused ...");
|
||||
|
||||
// open console
|
||||
gEnv->pConsole->ShowConsole(true);
|
||||
|
||||
CLvlRes_findunused sink;
|
||||
|
||||
sink.RegisterAllLevelPaks("levels");
|
||||
sink.Process("levels");
|
||||
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, " ");
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, "Assets not used by the existing LvlRes data:");
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, " ");
|
||||
|
||||
char rootpath[_MAX_PATH];
|
||||
AZ::Utils::GetExecutableDirectory(rootpath, _MAX_PATH);
|
||||
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, "Folder: %s", rootpath);
|
||||
|
||||
uint32 dwUnused = 0, dwAll = 0;
|
||||
|
||||
string unused;
|
||||
_LvlRes_findunused_recursive(sink, unused, dwUnused, dwAll);
|
||||
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, " ");
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, "Unused assets: %d/%d", dwUnused, dwAll);
|
||||
gEnv->pLog->LogWithType(ILog::eInputResponse, " ");
|
||||
}
|
||||
|
||||
static void ScreenshotCmd(IConsoleCmdArgs* pParams)
|
||||
{
|
||||
assert(pParams);
|
||||
@@ -4628,15 +4048,9 @@ void CSystem::CreateSystemVars()
|
||||
|
||||
REGISTER_INT("capture_frames", 0, 0, "Enables capturing of frames. 0=off, 1=on");
|
||||
REGISTER_STRING("capture_folder", "CaptureOutput", 0, "Specifies sub folder to write captured frames.");
|
||||
REGISTER_STRING("capture_file_format", "jpg", 0, "Specifies file format of captured files (jpg, tga, tif).");
|
||||
REGISTER_INT("capture_frame_once", 0, 0, "Makes capture single frame only");
|
||||
REGISTER_STRING("capture_file_name", "", 0, "If set, specifies the path and name to use for the captured frame");
|
||||
REGISTER_STRING("capture_file_prefix", "", 0, "If set, specifies the prefix to use for the captured frame instead of the default 'Frame'.");
|
||||
REGISTER_INT("capture_buffer", 0, 0,
|
||||
"Buffer to capture when capture_frames is enabled.\n"
|
||||
"0=Color\n"
|
||||
"1=Color with Alpha (requires capture_file_format=tga)");
|
||||
|
||||
|
||||
m_gpu_particle_physics = REGISTER_INT("gpu_particle_physics", 0, VF_REQUIRE_APP_RESTART, "Enable GPU physics if available (0=off / 1=enabled).");
|
||||
assert(m_gpu_particle_physics);
|
||||
@@ -4645,7 +4059,6 @@ void CSystem::CreateSystemVars()
|
||||
"Load .cfg file from disk (from the {Game}/Config directory)\n"
|
||||
"e.g. LoadConfig lowspec.cfg\n"
|
||||
"Usage: LoadConfig <filename>");
|
||||
|
||||
assert(m_env.pConsole);
|
||||
m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F12", "Screenshot");
|
||||
m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F11", "RecordClip");
|
||||
@@ -4656,8 +4069,6 @@ void CSystem::CreateSystemVars()
|
||||
"e.g. Screenshot beach scene with shark\n"
|
||||
"Usage: Screenshot <annotation text>");
|
||||
|
||||
REGISTER_COMMAND("sys_LvlRes_finalstep", &LvlRes_finalstep, 0, "to combine all recorded level resources and create final stripped build (pass directory name as parameter)");
|
||||
REGISTER_COMMAND("sys_LvlRes_findunused", &LvlRes_findunused, 0, "find unused level resources");
|
||||
/*
|
||||
// experimental feature? - needs to be created very early
|
||||
m_sys_filecache = REGISTER_INT("sys_FileCache",0,0,
|
||||
|
||||
@@ -353,15 +353,6 @@ void CSystem::RenderEnd([[maybe_unused]] bool bRenderStats, bool bMainWindow)
|
||||
if (!gEnv->pSystem->GetILevelSystem() || !gEnv->pSystem->GetILevelSystem()->IsLevelLoaded())
|
||||
{
|
||||
IConsole* console = GetIConsole();
|
||||
ILyShine* lyShine = gEnv->pLyShine;
|
||||
|
||||
//Normally the UI is drawn as part of the scene so it can properly render once per eye in VR
|
||||
//We only want to draw here if there is no level loaded. This way the user can see loading
|
||||
// UI and other information before the level is loaded.
|
||||
if (lyShine != nullptr)
|
||||
{
|
||||
lyShine->Render();
|
||||
}
|
||||
|
||||
//Same goes for the console. When no level is loaded, it's okay to render it outside of the renderer
|
||||
//so that users can load maps or change settings.
|
||||
@@ -390,12 +381,6 @@ void CSystem::RenderEnd([[maybe_unused]] bool bRenderStats, bool bMainWindow)
|
||||
|
||||
void CSystem::OnScene3DEnd()
|
||||
{
|
||||
// Render UI Canvas
|
||||
if (m_bDrawUI && gEnv->pLyShine)
|
||||
{
|
||||
gEnv->pLyShine->Render();
|
||||
}
|
||||
|
||||
//Render Console
|
||||
if (m_bDrawConsole && gEnv->pConsole)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,11 @@ namespace UnitTest
|
||||
: public ::testing::Test
|
||||
{};
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_MATH_TESTS
|
||||
TEST_F(CryMathTestFixture, DISABLED_InverserSqrt_HasAtLeast22BitsOfAccuracy)
|
||||
#else
|
||||
TEST_F(CryMathTestFixture, InverserSqrt_HasAtLeast22BitsOfAccuracy)
|
||||
#endif
|
||||
{
|
||||
float testFloat(0.336950600);
|
||||
const float result = isqrt_safe_tpl(testFloat * testFloat);
|
||||
@@ -28,7 +32,11 @@ namespace UnitTest
|
||||
EXPECT_NEAR(2.96779, result, epsilon);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_MATH_TESTS
|
||||
TEST_F(CryMathTestFixture, DISABLED_SimdSqrt_HasAtLeast23BitsOfAccuracy)
|
||||
#else
|
||||
TEST_F(CryMathTestFixture, SimdSqrt_HasAtLeast23BitsOfAccuracy)
|
||||
#endif
|
||||
{
|
||||
float testFloat(3434.34839439);
|
||||
const float result = sqrt_tpl(testFloat);
|
||||
|
||||
@@ -55,55 +55,6 @@ namespace CryPakUnitTests
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(Integ_CryPakUnitTests, TestCryPakArchiveContainingLevels)
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance();
|
||||
ASSERT_NE(nullptr, fileIo);
|
||||
|
||||
constexpr const char* testPakPath = "@usercache@/archivecontainerlevel.pak";
|
||||
|
||||
char resolvedArchivePath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
EXPECT_TRUE(fileIo->ResolvePath(testPakPath, resolvedArchivePath, AZ_MAX_PATH_LEN));
|
||||
|
||||
AZ::IO::IArchive* pak = gEnv->pCryPak;
|
||||
|
||||
ASSERT_NE(nullptr, pak);
|
||||
|
||||
// delete test files in case they already exist
|
||||
pak->ClosePack(testPakPath);
|
||||
fileIo->Remove(testPakPath);
|
||||
|
||||
ILevelSystem* levelSystem = gEnv->pSystem->GetILevelSystem();
|
||||
EXPECT_NE(nullptr, levelSystem);
|
||||
|
||||
// ------------ Create an archive with a dummy level in it ------------
|
||||
AZStd::intrusive_ptr<AZ::IO::INestedArchive> pArchive = pak->OpenArchive(testPakPath, nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW);
|
||||
EXPECT_NE(nullptr, pArchive);
|
||||
|
||||
const char levelInfoFile[] = "levelInfo.xml";
|
||||
AZStd::string relativeLevelPakPath = AZStd::string::format("levels/dummy/%s", ILevelSystem::LevelPakName);
|
||||
AZStd::string relativeLevelInfoPath = AZStd::string::format("levels/dummy/%s", levelInfoFile);
|
||||
|
||||
EXPECT_EQ(0, pArchive->UpdateFile(relativeLevelPakPath.c_str(), const_cast<char*>("test"), 4, AZ::IO::INestedArchive::METHOD_COMPRESS, AZ::IO::INestedArchive::LEVEL_BEST));
|
||||
EXPECT_EQ(0, pArchive->UpdateFile(relativeLevelInfoPath.c_str(), const_cast<char*>("test"), 4, AZ::IO::INestedArchive::METHOD_COMPRESS, AZ::IO::INestedArchive::LEVEL_BEST));
|
||||
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(testPakPath));
|
||||
AZStd::fixed_string<AZ::IO::IArchive::MaxPath> fullLevelPakPath;
|
||||
bool addLevel = true;
|
||||
EXPECT_TRUE(pak->OpenPack("@assets@", resolvedArchivePath, AZ::IO::IArchive::FLAGS_LEVEL_PAK_INSIDE_PAK, nullptr, &fullLevelPakPath, addLevel));
|
||||
|
||||
ILevelInfo* levelInfo = nullptr;
|
||||
// Since the archive was open, we should be able to find the level "dummy"
|
||||
levelInfo = levelSystem->GetLevelInfo("dummy");
|
||||
EXPECT_NE(nullptr, levelInfo);
|
||||
EXPECT_TRUE(pak->ClosePack(resolvedArchivePath));
|
||||
|
||||
// After closing the archive we should not be able to find the level "dummy"
|
||||
levelInfo = levelSystem->GetLevelInfo("dummy");
|
||||
EXPECT_EQ(nullptr, levelInfo);
|
||||
}
|
||||
|
||||
TEST_F(Integ_CryPakUnitTests, TestCryPakModTime)
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance();
|
||||
|
||||
@@ -595,7 +595,7 @@ void CViewSystem::UpdateSoundListeners()
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
void CViewSystem::OnLoadingStart([[maybe_unused]] ILevelInfo* pLevel)
|
||||
void CViewSystem::OnLoadingStart([[maybe_unused]] const char* levelName)
|
||||
{
|
||||
//If the level is being restarted (IsSerializingFile() == 1)
|
||||
//views should not be cleared, because the main view (player one) won't be recreated in this case
|
||||
@@ -609,7 +609,7 @@ void CViewSystem::OnLoadingStart([[maybe_unused]] ILevelInfo* pLevel)
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
void CViewSystem::OnUnloadComplete([[maybe_unused]] ILevel* pLevel)
|
||||
void CViewSystem::OnUnloadComplete([[maybe_unused]] const char* levelName)
|
||||
{
|
||||
bool shouldClearViews = gEnv->pSystem ? (gEnv->pSystem->IsSerializingFile() != 1) : false;
|
||||
|
||||
|
||||
@@ -85,11 +85,11 @@ public:
|
||||
|
||||
// ILevelSystemListener
|
||||
virtual void OnLevelNotFound([[maybe_unused]] const char* levelName) {};
|
||||
virtual void OnLoadingStart(ILevelInfo* pLevel);
|
||||
virtual void OnLoadingComplete([[maybe_unused]] ILevel* pLevel) {};
|
||||
virtual void OnLoadingError([[maybe_unused]] ILevelInfo* pLevel, [[maybe_unused]] const char* error) {};
|
||||
virtual void OnLoadingProgress([[maybe_unused]] ILevelInfo* pLevel, [[maybe_unused]] int progressAmount) {};
|
||||
virtual void OnUnloadComplete(ILevel* pLevel);
|
||||
virtual void OnLoadingStart([[maybe_unused]] const char* levelName);
|
||||
virtual void OnLoadingComplete([[maybe_unused]] const char* levelName){};
|
||||
virtual void OnLoadingError([[maybe_unused]] const char* levelName, [[maybe_unused]] const char* error){};
|
||||
virtual void OnLoadingProgress([[maybe_unused]] const char* levelName, [[maybe_unused]] int progressAmount){};
|
||||
virtual void OnUnloadComplete([[maybe_unused]] const char* levelName);
|
||||
//~ILevelSystemListener
|
||||
|
||||
CViewSystem(ISystem* pSystem);
|
||||
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
virtual void SetScrollMax(int value);
|
||||
virtual void AddOutputPrintSink(IOutputPrintSink* inpSink);
|
||||
virtual void RemoveOutputPrintSink(IOutputPrintSink* inpSink);
|
||||
virtual void ShowConsole(bool show, const int iRequestScrollMax = -1);
|
||||
virtual void ShowConsole(bool show, int iRequestScrollMax = -1);
|
||||
virtual void DumpCVars(ICVarDumpSink* pCallback, unsigned int nFlagsFilter = 0);
|
||||
virtual void DumpKeyBinds(IKeyBindDumpSink* pCallback);
|
||||
virtual void CreateKeyBind(const char* sCmd, const char* sRes);
|
||||
@@ -178,7 +178,7 @@ public:
|
||||
virtual void SetImage(ITexture* pImage, bool bDeleteCurrent);
|
||||
virtual inline ITexture* GetImage() { return m_pImage; }
|
||||
virtual void StaticBackground(bool bStatic) { m_bStaticBackground = bStatic; }
|
||||
virtual bool GetLineNo(const int indwLineNo, char* outszBuffer, const int indwBufferSize) const;
|
||||
virtual bool GetLineNo(int indwLineNo, char* outszBuffer, int indwBufferSize) const;
|
||||
virtual int GetLineCount() const;
|
||||
virtual ICVar* GetCVar(const char* name);
|
||||
virtual char* GetVariable(const char* szVarName, const char* szFileName, const char* def_val);
|
||||
@@ -192,7 +192,7 @@ public:
|
||||
virtual bool AddCommand(const char* sCommand, ConsoleCommandFunc func, int nFlags = 0, const char* sHelp = NULL);
|
||||
virtual bool AddCommand(const char* sName, const char* sScriptFunc, int nFlags = 0, const char* sHelp = NULL);
|
||||
virtual void RemoveCommand(const char* sName);
|
||||
virtual void ExecuteString(const char* command, const bool bSilentMode, const bool bDeferExecution = false);
|
||||
virtual void ExecuteString(const char* command, bool bSilentMode, bool bDeferExecution = false);
|
||||
virtual void ExecuteConsoleCommand(const char* command) override;
|
||||
virtual void ResetCVarsToDefaults() override;
|
||||
virtual void Exit(const char* command, ...) PRINTF_PARAMS(2, 3);
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
virtual void SetLoadingImage(const char* szFilename);
|
||||
virtual void AddConsoleVarSink(IConsoleVarSink* pSink);
|
||||
virtual void RemoveConsoleVarSink(IConsoleVarSink* pSink);
|
||||
virtual const char* GetHistoryElement(const bool bUpOrDown);
|
||||
virtual const char* GetHistoryElement(bool bUpOrDown);
|
||||
virtual void AddCommandToHistory(const char* szCommand);
|
||||
virtual void SetInputLine(const char* szLine);
|
||||
virtual void LoadConfigVar(const char* sVariable, const char* sValue);
|
||||
|
||||
@@ -221,7 +221,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Set(const float f)
|
||||
virtual void Set(float f)
|
||||
{
|
||||
stack_string s;
|
||||
s.Format("%g", f);
|
||||
@@ -235,7 +235,7 @@ public:
|
||||
Set(s.c_str());
|
||||
}
|
||||
|
||||
virtual void Set(const int i)
|
||||
virtual void Set(int i)
|
||||
{
|
||||
stack_string s;
|
||||
s.Format("%d", i);
|
||||
@@ -289,11 +289,11 @@ public:
|
||||
|
||||
Set(nValue);
|
||||
}
|
||||
virtual void Set(const float f)
|
||||
virtual void Set(float f)
|
||||
{
|
||||
Set((int)f);
|
||||
}
|
||||
virtual void Set(const int i)
|
||||
virtual void Set(int i)
|
||||
{
|
||||
if (i == m_iValue && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
|
||||
{
|
||||
@@ -353,15 +353,15 @@ public:
|
||||
|
||||
Set(nValue);
|
||||
}
|
||||
virtual void Set(const float f)
|
||||
virtual void Set(float f)
|
||||
{
|
||||
Set((int)f);
|
||||
}
|
||||
virtual void Set(const int i)
|
||||
virtual void Set(int i)
|
||||
{
|
||||
Set((int64)i);
|
||||
}
|
||||
virtual void Set(const int64 i)
|
||||
virtual void Set(int64 i)
|
||||
{
|
||||
if (i == m_iValue && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
|
||||
{
|
||||
@@ -439,7 +439,7 @@ public:
|
||||
m_pConsole->OnAfterVarChange(this);
|
||||
}
|
||||
}
|
||||
virtual void Set(const float f)
|
||||
virtual void Set(float f)
|
||||
{
|
||||
if (f == m_fValue && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
|
||||
{
|
||||
@@ -459,7 +459,7 @@ public:
|
||||
m_pConsole->OnAfterVarChange(this);
|
||||
}
|
||||
}
|
||||
virtual void Set(const int i)
|
||||
virtual void Set(int i)
|
||||
{
|
||||
if ((float)i == m_fValue && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
|
||||
{
|
||||
@@ -542,7 +542,7 @@ public:
|
||||
m_pConsole->OnAfterVarChange(this);
|
||||
}
|
||||
}
|
||||
virtual void Set(const float f)
|
||||
virtual void Set(float f)
|
||||
{
|
||||
if ((int)f == m_iValue && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
|
||||
{
|
||||
@@ -560,7 +560,7 @@ public:
|
||||
m_pConsole->OnAfterVarChange(this);
|
||||
}
|
||||
}
|
||||
virtual void Set(const int i)
|
||||
virtual void Set(int i)
|
||||
{
|
||||
if (i == m_iValue && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
|
||||
{
|
||||
@@ -639,7 +639,7 @@ public:
|
||||
m_pConsole->OnAfterVarChange(this);
|
||||
}
|
||||
}
|
||||
virtual void Set(const float f)
|
||||
virtual void Set(float f)
|
||||
{
|
||||
if (f == m_fValue && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
|
||||
{
|
||||
@@ -657,7 +657,7 @@ public:
|
||||
m_pConsole->OnAfterVarChange(this);
|
||||
}
|
||||
}
|
||||
virtual void Set(const int i)
|
||||
virtual void Set(int i)
|
||||
{
|
||||
if ((float)i == m_fValue && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
|
||||
{
|
||||
@@ -742,13 +742,13 @@ public:
|
||||
m_pConsole->OnAfterVarChange(this);
|
||||
}
|
||||
}
|
||||
virtual void Set(const float f)
|
||||
virtual void Set(float f)
|
||||
{
|
||||
stack_string s;
|
||||
s.Format("%g", f);
|
||||
Set(s.c_str());
|
||||
}
|
||||
virtual void Set(const int i)
|
||||
virtual void Set(int i)
|
||||
{
|
||||
stack_string s;
|
||||
s.Format("%d", i);
|
||||
@@ -792,7 +792,7 @@ public:
|
||||
|
||||
virtual void DebugLog(const int iExpectedValue, const ICVar::EConsoleLogMode mode) const;
|
||||
|
||||
virtual void Set(const int i);
|
||||
virtual void Set(int i);
|
||||
|
||||
// ConsoleVarFunc ------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -178,6 +178,8 @@ set(FILES
|
||||
LZ4Decompressor.cpp
|
||||
LevelSystem/LevelSystem.cpp
|
||||
LevelSystem/LevelSystem.h
|
||||
LevelSystem/SpawnableLevelSystem.cpp
|
||||
LevelSystem/SpawnableLevelSystem.h
|
||||
ViewSystem/DebugCamera.cpp
|
||||
ViewSystem/DebugCamera.h
|
||||
ViewSystem/View.cpp
|
||||
|
||||
Reference in New Issue
Block a user