Integrating latest from github/staging

Integrating up through commit 5e1bdae
This commit is contained in:
alexpete
2021-03-26 14:31:50 -07:00
parent 9c54341af8
commit 36c4e827bd
764 changed files with 11453 additions and 20251 deletions
@@ -14,6 +14,8 @@
#include "AssetDatabaseLocationListener.h"
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
// AzToolsFramework
#include <AzToolsFramework/AssetDatabase/AssetDatabaseConnection.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
@@ -44,16 +46,20 @@ namespace AssetDatabase
return m_assetDatabaseConnection;
}
bool AssetDatabaseLocationListener::GetAssetDatabaseLocation( AZStd::string& result )
bool AssetDatabaseLocationListener::GetAssetDatabaseLocation(AZStd::string& result)
{
result = gEnv->pFileIO->GetAlias( "@devroot@" );
result += "/Cache/";
ICVar * pCvar = gEnv->pConsole->GetCVar( "sys_game_folder" );
if( pCvar && pCvar->GetString() )
if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
{
result += pCvar->GetString();
AZ::SettingsRegistryInterface::FixedValueString projectCacheRootValue;
if (registry->Get(projectCacheRootValue, AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder);
!projectCacheRootValue.empty())
{
result = projectCacheRootValue;
result += "/assetdb.sqlite";
return true;
}
}
result += "/assetdb.sqlite";
return true;
return false;
}
}//namespace AssetDatabase
@@ -25,6 +25,9 @@
#include <QtGui/private/qhighdpiscaling_p.h>
#endif
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
// AzFramework
#if defined(AZ_PLATFORM_WINDOWS)
# include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
@@ -267,7 +270,14 @@ namespace Editor
QLoggingCategory::setFilterRules(QStringLiteral("lumberyard.editor.input.*=false"));
// Initialize our stylesheet here to allow Gems to register stylesheets when their system components activate.
m_stylesheet->initialize(this);
AZ::IO::FixedMaxPath engineRootPath;
{
// Create a ComponentApplication to initialize the AZ::SystemAllocator and initialize the SettingsRegistry
AZ::ComponentApplication application(argc, argv);
auto settingsRegistry = AZ::SettingsRegistry::Get();
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
}
m_stylesheet->initialize(this, engineRootPath);
}
void EditorQtApplication::Initialize()
+26 -14
View File
@@ -52,6 +52,7 @@ AZ_POP_DISABLE_WARNING
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
// AzFramework
#include <AzFramework/Components/CameraBus.h>
@@ -81,7 +82,6 @@ AZ_POP_DISABLE_WARNING
#include <CryCommon/ITimer.h>
#include <CryCommon/IPhysics.h>
#include <CryCommon/ILevelSystem.h>
#include <CryCommon/ParseEngineConfig.h>
// Editor
#include "Settings.h"
@@ -683,7 +683,6 @@ public:
QString dummyString;
const std::vector<std::pair<CommandLineStringOption, QString&> > stringOptions = {
{{"app-root", "Application Root path override", "app-root"}, m_appRoot},
{{"logfile", "File name of the log file to write out to.", "logfile"}, m_logFile},
{{"runpythonargs", "Command-line argument string to pass to the python script if --runpython or --runpythontest was used.", "runpythonargs"}, m_pythonArgs},
{{"exec", "cfg file to run on startup, used for systems like automation", "exec"}, m_execFile},
@@ -691,7 +690,11 @@ public:
{{"rhi-device-validation", "Command-line argument to configure rhi validation", "dummyString"}, dummyString },
{{"exec_line", "command to run on startup, used for systems like automation", "exec_line"}, m_execLineCmd},
{{"regset", "Command-line argument to override settings registry values", "regset"}, dummyString},
{{"regdump", "Sets a value within the global settings registry at the JSON pointer path @key with value of @value)", "regdump"}, dummyString}
{{"regremove", "Deletes a value within the global settings registry at the JSON pointer path @key", "regremove"}, dummyString},
{{"regdump", "Sets a value within the global settings registry at the JSON pointer path @key with value of @value", "regdump"}, dummyString},
{{"project-path", "Supplies the path to the project that the Editor should use", "project-path"}, dummyString},
{{"engine-path", "Supplies the path to the engine", "engine-path"}, dummyString},
{{"project-cache-path", "Path to the project cache", "project-cache-path"}, dummyString},
// add dummy entries here to prevent QCommandLineParser error-ing out on cmd line args that will be parsed later
};
@@ -719,7 +722,11 @@ public:
}
#endif
parser.process(args);
if (!parser.parse(args))
{
AZ_TracePrintf("QT CommandLine Parser", "QT command line parsing warned with message %s."
" Has the QCommandLineParser had these options added to it", parser.errorText().toUtf8().constData());
}
// Get boolean options
const int numOptions = options.size();
@@ -1217,11 +1224,10 @@ bool CCryEditApp::InitGame()
{
if (!m_bPreviewMode && !GetIEditor()->IsInMatEditMode())
{
ICVar* pVar = gEnv->pConsole->GetCVar("sys_game_folder");
const char* sGameFolder = pVar ? pVar->GetString() : nullptr;
Log((QString("sys_game_folder = ") + (sGameFolder && sGameFolder[0] ? sGameFolder : "<not set>")).toUtf8().data());
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
Log((QString("project_path = %1").arg(!projectPath.empty() ? projectPath.c_str() : "<not set>")).toUtf8().data());
pVar = gEnv->pConsole->GetCVar("sys_localization_folder");
ICVar* pVar = gEnv->pConsole->GetCVar("sys_localization_folder");
const char* sLocalizationFolder = pVar ? pVar->GetString() : nullptr;
Log((QString("sys_localization_folder = ") + (sLocalizationFolder && sLocalizationFolder[0] ? sLocalizationFolder : "<not set>")).toUtf8().data());
@@ -1740,11 +1746,17 @@ BOOL CCryEditApp::InitInstance()
mainWindowWrapper->setGuest(mainWindow);
HWND mainWindowWrapperHwnd = (HWND)mainWindowWrapper->winId();
QDir engineRoot = AzQtComponents::FindEngineRootDir(qApp);
AZ::IO::FixedMaxPath engineRootPath;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
}
QDir engineRoot = QString::fromUtf8(engineRootPath.c_str(), aznumeric_cast<int>(engineRootPath.Native().size()));
AzQtComponents::StyleManager::addSearchPaths(
QStringLiteral("style"),
engineRoot.filePath(QStringLiteral("Code/Sandbox/Editor/Style")),
QStringLiteral(":/Editor/Style"));
QStringLiteral(":/Editor/Style"),
engineRootPath);
AzQtComponents::StyleManager::setStyleSheet(mainWindow, QStringLiteral("style:Editor.qss"));
// Note: we should use getNativeHandle to get the HWND from the widget, but
@@ -5496,9 +5508,9 @@ void CCryEditApp::OpenLUAEditor(const char* files)
}
}
const char* appRoot = nullptr;
AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot);
AZ_Assert(appRoot != nullptr, "Unable to communicate to AzFramework::ApplicationRequests::Bus");
const char* engineRoot = nullptr;
AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
AZ_Assert(engineRoot != nullptr, "Unable to communicate to AzFramework::ApplicationRequests::Bus");
AZStd::string_view exePath;
AZ::ComponentApplicationBus::BroadcastResult(exePath, &AZ::ComponentApplicationRequests::GetExecutableFolder);
@@ -5509,7 +5521,7 @@ void CCryEditApp::OpenLUAEditor(const char* files)
#endif
"\"", aznumeric_cast<int>(exePath.size()), exePath.data());
AZStd::string processArgs = AZStd::string::format("%s -app-root \"%s\"", args.c_str(), appRoot);
AZStd::string processArgs = AZStd::string::format("%s -engine-path \"%s\"", args.c_str(), engineRoot);
StartProcessDetached(process.c_str(), processArgs.c_str());
}
@@ -19,6 +19,8 @@
#include <AzCore/Module/Module.h> // for AZ::ModuleData
#include <AzCore/Module/ModuleManagerBus.h> // for AZ::ModuleManagerRequestBus
#include <AzCore/Module/DynamicModuleHandle.h> // for AZ::DynamicModuleHandle
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
// AzToolsFramework
#include <AzToolsFramework/API/ViewPaneOptions.h> // for AzToolsFramework::ViewPaneOptions
@@ -88,26 +90,64 @@ CPythonScriptsDialog::CPythonScriptsDialog(QWidget* parent)
}
}
ScanFolderForScripts(QString("@devroot@/%1/Editor/Scripts").arg(GetIEditor()->GetProjectName()), scriptFolders);
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
ScanFolderForScripts(QString("%1/Editor/Scripts").arg(projectPath.c_str()), scriptFolders);
auto moduleCallback = [this, &scriptFolders](const AZ::ModuleData& moduleData) -> bool
struct GetGemSourcePathsVisitor
: AZ::SettingsRegistryInterface::Visitor
{
if (moduleData.GetDynamicModuleHandle())
GetGemSourcePathsVisitor(AZ::SettingsRegistryInterface& settingsRegistry)
: m_settingsRegistry(settingsRegistry)
{}
void Visit(AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type,
AZStd::string_view value) override
{
const AZ::OSString& modulePath = moduleData.GetDynamicModuleHandle()->GetFilename();
AZStd::string fileName;
AzFramework::StringFunc::Path::GetFileName(modulePath.c_str(), fileName);
AZStd::vector<AZStd::string> tokens;
AzFramework::StringFunc::Tokenize(fileName.c_str(), tokens, '.');
if (tokens.size() > 2 && tokens[0] == "Gem")
AZStd::string_view jsonSourcePathPointer{ path };
// Remove the array index from the path and check if the JSON path ends with "/SourcePaths"
AZ::StringFunc::TokenizeLast(jsonSourcePathPointer, "/");
if (jsonSourcePathPointer.ends_with("/SourcePaths"))
{
ScanFolderForScripts(QString("@engroot@/Gems/%1/Editor/Scripts").arg(tokens[1].c_str()), scriptFolders);
AZ::IO::Path newSourcePath = jsonSourcePathPointer;
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
// any relative path is underneath the @assets@ alias
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
{
AZ::IO::FixedMaxPath replacedAliasPath;
if (fileIoBase->ReplaceAlias(replacedAliasPath, value))
{
newSourcePath = AZ::IO::PathView(replacedAliasPath);
}
}
// The current assumption is that the gem source path is the relative to the engine root
AZ::IO::Path engineRootPath;
m_settingsRegistry.Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
newSourcePath = (engineRootPath / newSourcePath).LexicallyNormal();
if (auto gemSourcePathIter = AZStd::find(m_gemSourcePaths.begin(), m_gemSourcePaths.end(), newSourcePath);
gemSourcePathIter == m_gemSourcePaths.end())
{
m_gemSourcePaths.emplace_back(AZStd::move(newSourcePath));
}
}
}
return true;
AZStd::vector<AZ::IO::Path> m_gemSourcePaths;
private:
AZ::SettingsRegistryInterface& m_settingsRegistry;
};
AZ::ModuleManagerRequestBus::Broadcast(&AZ::ModuleManagerRequestBus::Events::EnumerateModules, moduleCallback);
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
GetGemSourcePathsVisitor visitor{ *settingsRegistry };
constexpr auto gemListKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::OrganizationRootKey)
+ "/Gems";
settingsRegistry->Visit(visitor, gemListKey);
for (const AZ::IO::Path& gemSourcePath : visitor.m_gemSourcePaths)
{
ScanFolderForScripts(QString("%1/Editor/Scripts").arg(gemSourcePath.c_str()), scriptFolders);
}
}
ui->treeView->init(scriptFolders, s_kPythonFileNameSpec, s_kRootElementName, false, false);
QObject::connect(ui->treeView, &CFolderTreeCtrl::ItemDoubleClicked, this, &CPythonScriptsDialog::OnExecute);
@@ -23,9 +23,6 @@
#include <AzToolsFramework/AssetBrowser/AssetBrowserComponent.h>
#include <AzToolsFramework/MaterialBrowser/MaterialBrowserComponent.h>
// CryCommon
#include <CryCommon/ParseEngineConfig.h>
// Editor
#include "MainWindow.h"
#include "CryEdit.h"
@@ -109,15 +106,6 @@ namespace EditorInternal
{
AzFramework::Application::StartupParameters params;
AZStd::string appRootOverride;
const size_t appRootSwitches = m_commandLine.GetNumSwitchValues("app-root");
if (appRootSwitches != 0)
{
// Use the last --app-root parameter specified on the command line
appRootOverride = m_commandLine.GetSwitchValue("app-root", appRootSwitches - 1);
params.m_appRootOverride = appRootOverride.c_str();
}
// Must be done before creating QApplication, otherwise asserts when we alloc
AzToolsFramework::ToolsApplication::Start({}, params);
if (IsStartupAborted() || !m_systemEntity)
+5 -49
View File
@@ -44,7 +44,6 @@
#include <CryCommon/IDeferredCollisionEvent.h>
#include <CryCommon/ITimeOfDay.h>
#include <CryCommon/LyShine/ILyShine.h>
#include <CryCommon/ParseEngineConfig.h>
#include <CryCommon/MainThreadRenderRequestBus.h>
// Editor
@@ -415,24 +414,7 @@ AZ::Outcome<void, AZStd::string> CGameEngine::Init(
(PFNCREATESYSTEMINTERFACE)CryGetProcAddress(m_hSystemHandle, "CreateSystemInterface");
// Locate the root path
const char* calcRootPath = nullptr;
EBUS_EVENT_RESULT(calcRootPath, AZ::ComponentApplicationBus, GetAppRoot);
if (calcRootPath == nullptr)
{
// If the app root isnt available, default to the engine root
EBUS_EVENT_RESULT(calcRootPath, AzToolsFramework::ToolsApplicationRequestBus, GetEngineRootPath);
}
const char* searchPath[] = { calcRootPath };
CEngineConfig engineConfig(searchPath,AZ_ARRAY_SIZE(searchPath)); // read the engine config also to see what game is running, and what folder(s) there are.
SSystemInitParams sip;
engineConfig.CopyToStartupParams(sip);
sip.connectToRemote = true; // editor always connects
sip.waitForConnection = true; // editor REQUIRES connect.
const char localIP[10] = "127.0.0.1";
azstrncpy(sip.remoteIP, AZ_ARRAY_SIZE(sip.remoteIP), localIP, AZ_ARRAY_SIZE(localIP)); // editor ONLY connects to the local asset processor
sip.bEditor = true;
sip.bDedicatedServer = false;
@@ -457,15 +439,6 @@ AZ::Outcome<void, AZStd::string> CGameEngine::Init(
sip.pUserCallback = m_pSystemUserCallback;
sip.pValidator = GetIEditor()->GetErrorReport(); // Assign validator from Editor.
// Calculate the branch token first based on the app root path if possible
if (calcRootPath!=nullptr)
{
AZStd::string appRoot(calcRootPath);
AZStd::string branchToken;
AzFramework::StringFunc::AssetPath::CalculateBranchToken(appRoot, branchToken);
azstrncpy(sip.branchToken, AZ_ARRAY_SIZE(sip.branchToken), branchToken.c_str(), branchToken.length());
}
if (sInCmdLine)
{
azstrncpy(sip.szSystemCmdLine, AZ_COMMAND_LINE_LEN, sInCmdLine, AZ_COMMAND_LINE_LEN);
@@ -484,7 +457,7 @@ AZ::Outcome<void, AZStd::string> CGameEngine::Init(
{
sip.bSkipFont = true;
}
AssetProcessConnectionStatus apConnectionStatus;
AssetProcessConnectionStatus apConnectionStatus;
m_pISystem = pfnCreateSystemInterface(sip);
@@ -512,33 +485,16 @@ AZ::Outcome<void, AZStd::string> CGameEngine::Init(
if (apConnectionStatus.CheckConnectionFailed())
{
AzFramework::AssetSystem::ConnectionSettings connectionSettings;
AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings);
auto errorMessage = AZStd::string::format("Unable to connect to the local Asset Processor.\n\n"
"The Asset Processor is either not running locally or not accepting connections on port %d. "
"The Asset Processor is either not running locally or not accepting connections on port %hu. "
"Check your remote_port settings in bootstrap.cfg or view the Asset Processor's \"Logs\" tab "
"for any errors.", sip.remotePort);
"for any errors.", connectionSettings.m_assetProcessorPort);
gEnv = nullptr;
return AZ::Failure(errorMessage);
}
// because we're the editor here, we also give tool aliases to the original, unaltered roots:
string devAssetsFolder = engineConfig.m_rootFolder + "/" + engineConfig.m_gameFolder;
if (gEnv && gEnv->pFileIO)
{
const char* engineRoot = nullptr;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath);
if (engineRoot != nullptr)
{
gEnv->pFileIO->SetAlias("@engroot@", engineRoot);
}
else
{
gEnv->pFileIO->SetAlias("@engroot@", engineConfig.m_rootFolder.c_str());
}
gEnv->pFileIO->SetAlias("@devroot@", engineConfig.m_rootFolder.c_str());
gEnv->pFileIO->SetAlias("@devassets@", devAssetsFolder.c_str());
}
SetEditorCoreEnvironment(gEnv);
if (gEnv
@@ -28,6 +28,8 @@
#include <QFontMetrics>
#include <QSettings>
#include <AzCore/Utils/Utils.h>
// AzFramework
#include <AzFramework/IO/LocalFileIO.h>
#include <AzQtComponents/Components/Widgets/PushButton.h>
@@ -975,8 +977,9 @@ void GraphicsSettingsDialog::accept()
void GraphicsSettingsDialog::OpenCustomSpecDialog()
{
QString projectName = GetIEditor()->GetProjectName();
QString settingsPath = projectName + "/" + SETTINGS_FILE_PATH;
AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
projectPath /= SETTINGS_FILE_PATH.toUtf8().constData();
QString settingsPath = QString::fromUtf8(projectPath.c_str(), aznumeric_cast<int>(projectPath.Native().size()));
CAutoDirectoryRestoreFileDialog importCustomSpecDialog(QFileDialog::AcceptOpen, QFileDialog::ExistingFile, ".cfg", settingsPath, CFG_FILEFILTER, {}, {}, this);
@@ -1189,8 +1192,9 @@ void GraphicsSettingsDialog::SaveSystemSettings()
// Adding the project name to the path so that the file is created there if it doesn't already exist
// as we don't want to modify the version in Engine/config.
QString projectName = GetIEditor()->GetProjectName();
QString settingsPath = projectName + "/" + SETTINGS_FILE_PATH;
AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
projectPath /= SETTINGS_FILE_PATH.toUtf8().constData();
QString settingsPath = QString::fromUtf8(projectPath.c_str(), aznumeric_cast<int>(projectPath.Native().size()));
QString settingsFile = settingsPath + m_cfgFiles[m_currentPlatform][cfgFileIndex].c_str();
-2
View File
@@ -516,8 +516,6 @@ struct IEditor
virtual QString GetSearchPath(EEditorPathName path) = 0;
//! This folder is supposed to store Sandbox user settings and state
virtual QString GetResolvedUserFolder() = 0;
//! Returns the name of the sys_game_folder
virtual QString GetProjectName() = 0;
//! Execute application and get console output.
virtual bool ExecuteConsoleApp(
const QString& CommandLine,
-11
View File
@@ -655,17 +655,6 @@ QString CEditorImpl::GetResolvedUserFolder()
return m_userFolder;
}
QString CEditorImpl::GetProjectName()
{
ICVar* pCVar = (gEnv && gEnv->pConsole) ? gEnv->pConsole->GetCVar("sys_game_folder") : nullptr;
if (pCVar && pCVar->GetString())
{
return QString(pCVar->GetString());
}
return tr("unknown");
}
void CEditorImpl::SetDataModified()
{
GetDocument()->SetModifiedFlag(TRUE);
-1
View File
@@ -146,7 +146,6 @@ public:
QString GetLevelDataFolder();
QString GetSearchPath(EEditorPathName path);
QString GetResolvedUserFolder();
QString GetProjectName() override;
bool ExecuteConsoleApp(const QString& CommandLine, QString& OutputText, bool bNoTimeOut = false, bool bShowWindow = false);
virtual bool IsInGameMode() override;
virtual void SetInGameMode(bool inGame) override;
@@ -61,7 +61,6 @@ public:
MOCK_METHOD0(GetLevelDataFolder, QString());
MOCK_METHOD1(GetPrimaryCDFolder, QString(EEditorPathName));
MOCK_METHOD0(GetResolvedUserFolder, QString());
MOCK_METHOD0(GetProjectName, QString());
MOCK_METHOD4(ExecuteConsoleApp, bool(const QString&,QString&,bool,bool));
MOCK_METHOD0(SetDataModified, void());
MOCK_CONST_METHOD0(IsInitialized, bool());
+5 -12
View File
@@ -15,6 +15,7 @@
#include "MainStatusBar.h"
#include <AzCore/Utils/Utils.h>
// AzQtComponents
#include <AzQtComponents/Components/Widgets/CheckBox.h>
#include <AzQtComponents/Components/Style.h>
@@ -220,24 +221,16 @@ MainStatusBar::MainStatusBar(QWidget* parent)
void MainStatusBar::Init()
{
//called on mainwindow initialization
const int statusbarTimerUpdateInterval {
const int statusbarTimerUpdateInterval{
500
}; //in ms, so 2 FPS
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
QString strGameInfo;
ICVar* pCVar = gEnv->pConsole->GetCVar("sys_game_folder");
if (pCVar)
{
strGameInfo = tr("GameFolder: '%1'").arg(QtUtil::ToQString(pCVar->GetString()));
}
pCVar = gEnv->pConsole->GetCVar("sys_dll_game");
if (pCVar)
{
strGameInfo += QLatin1String(" - ") + tr("GameDLL: '%1'").arg(QtUtil::ToQString(pCVar->GetString()));
}
strGameInfo = tr("GameFolder: '%1'").arg(projectPath.c_str());
SetItem(QStringLiteral("game_info"), strGameInfo, tr("Game Info"), QPixmap());
//ask for updates for items regulary. This is basically what MFC does
//ask for updates for items regularly. This is basically what MFC does
auto timer = new QTimer(this);
timer->setInterval(statusbarTimerUpdateInterval);
connect(timer, &QTimer::timeout, this, &MainStatusBar::requestStatusUpdate);
+17 -24
View File
@@ -24,9 +24,8 @@
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
// AzFramework
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Utils/Utils.h>
// AzToolsFramework
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
@@ -997,7 +996,7 @@ void SEditorSettings::LoadDefaultGamePaths()
}
AZStd::string iconsPath;
AzFramework::StringFunc::Path::Join(Path::GetEditingRootFolder().c_str(), "Editor/UI/Icons", iconsPath);
AZ::StringFunc::Path::Join(Path::GetEditingRootFolder().c_str(), "Editor/UI/Icons", iconsPath);
searchPaths[EDITOR_PATH_UI_ICONS].push_back(iconsPath.c_str());
}
@@ -1166,34 +1165,28 @@ AzToolsFramework::EditorSettingsAPIRequests::SettingOutcome SEditorSettings::Set
void SEditorSettings::SaveSettingsRegistryFile()
{
auto fileIo = AZ::IO::FileIOBase::GetInstance();
// Resolve path to editorpreferences.setreg
AZ::IO::FixedMaxPath editorPreferencesFilePath = "user/Registry/editorpreferences.setreg";
if (fileIo == nullptr || !fileIo->ResolvePath(editorPreferencesFilePath, "@devroot@/user/Registry/editorpreferences.setreg"))
auto registry = AZ::SettingsRegistry::Get();
if (registry == nullptr)
{
AZ_Warning("SEditorSettings", false, R"(Unable to resolve path "%s" to the Editor Preferences registry file\n)",
editorPreferencesFilePath.c_str());
AZ_Warning("SEditorSettings", false, "Unable to access global settings registry. Editor Preferences cannot be saved");
return;
}
// Resolve path to editorpreferences.setreg
AZ::IO::FixedMaxPath editorPreferencesFilePath = AZ::Utils::GetProjectPath();
editorPreferencesFilePath /= "user/Registry/editorpreferences.setreg";
AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings;
dumperSettings.m_prettifyOutput = true;
dumperSettings.m_includeFilter = [](AZStd::string_view path)
{
AZStd::string_view prefixPath("/Amazon/Editor/Preferences");
return prefixPath.starts_with(path.substr(0, prefixPath.size()));
};
dumperSettings.m_jsonPointerPrefix = "/Amazon/Editor/Preferences";
AZStd::string stringBuffer;
if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
AZ::IO::ByteContainerStream stringStream(&stringBuffer);
if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "/Amazon/Editor/Preferences", stringStream, dumperSettings))
{
AZ::IO::ByteContainerStream stringStream(&stringBuffer);
if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "", stringStream, dumperSettings))
{
AZ_Warning("SEditorSettings", false, R"(Unable to save changes to the Editor Preferences registry file at "%s"\n)",
editorPreferencesFilePath.c_str());
return;
}
AZ_Warning("SEditorSettings", false, R"(Unable to save changes to the Editor Preferences registry file at "%s"\n)",
editorPreferencesFilePath.c_str());
return;
}
bool saved{};
@@ -0,0 +1,124 @@
/*
* 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 "AtomOutputFrameCapture.h"
#include <Atom/RPI.Public/Pass/Specific/RenderToTexturePass.h>
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Reflect/System/RenderPipelineDescriptor.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Name/Name.h>
#include <AzFramework/Entity/GameEntityContextBus.h>
#include <AzFramework/Scene/Scene.h>
#include <AzFramework/Scene/SceneSystemBus.h>
namespace TrackView
{
void AtomOutputFrameCapture::CreatePipeline(
AZ::RPI::Scene& scene, const AZStd::string& pipelineName, const uint32_t width, const uint32_t height)
{
AZ::RPI::RenderPipelineDescriptor pipelineDesc;
pipelineDesc.m_mainViewTagName = "MainCamera"; // must be "MainCamera"
pipelineDesc.m_name = pipelineName;
pipelineDesc.m_rootPassTemplate = "MainPipelineRenderToTexture";
pipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4;
m_renderPipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc);
if (auto renderToTexturePass = azrtti_cast<AZ::RPI::RenderToTexturePass*>(m_renderPipeline->GetRootPass().get()))
{
renderToTexturePass->ResizeOutput(width, height);
}
scene.AddRenderPipeline(m_renderPipeline);
// rendering pipeline has a tree structure
m_passHierarchy.push_back(pipelineName);
m_passHierarchy.push_back("CopyToSwapChain");
// retrieve View from the camera that's animating
AZ::Name viewName = AZ::Name("MainCamera");
m_view = AZ::RPI::View::CreateView(viewName, AZ::RPI::View::UsageCamera);
m_renderPipeline->SetDefaultView(m_view);
}
void AtomOutputFrameCapture::DestroyPipeline(AZ::RPI::Scene& scene)
{
scene.RemoveRenderPipeline(m_renderPipeline->GetId());
m_passHierarchy.clear();
m_renderPipeline.reset();
m_view.reset();
}
void AtomOutputFrameCapture::UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection)
{
m_view->SetCameraTransform(cameraTransform);
m_view->SetViewToClipMatrix(cameraProjection);
}
bool AtomOutputFrameCapture::BeginCapture(
const AZ::RPI::AttachmentReadback::CallbackFunction& attachmentReadbackCallback, CaptureFinishedCallback captureFinishedCallback)
{
AZ::Render::FrameCaptureNotificationBus::Handler::BusConnect();
m_captureFinishedCallback = AZStd::move(captureFinishedCallback);
// note: "Output" (slot name) maps to MainPipeline.pass CopyToSwapChain
bool startedCapture = false;
AZ::Render::FrameCaptureRequestBus::BroadcastResult(
startedCapture, &AZ::Render::FrameCaptureRequestBus::Events::CapturePassAttachmentWithCallback, m_passHierarchy,
AZStd::string("Output"), attachmentReadbackCallback);
return startedCapture;
}
void AtomOutputFrameCapture::OnCaptureFinished(
[[maybe_unused]] AZ::Render::FrameCaptureResult result, [[maybe_unused]] const AZStd::string& info)
{
m_captureFinishedCallback();
AZ::Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
}
AZ::Matrix3x4 TransformFromEntityId(const AZ::EntityId entityId)
{
AZ::Transform cameraTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(cameraTransform, entityId, &AZ::TransformBus::Events::GetWorldTM);
return AZ::Matrix3x4::CreateFromTransform(cameraTransform);
}
AZ::Matrix4x4 ProjectionFromCameraEntityId(const AZ::EntityId entityId, const float outputWidth, const float outputHeight)
{
float nearDist = 0.0f;
Camera::CameraRequestBus::EventResult(nearDist, entityId, &Camera::CameraRequestBus::Events::GetNearClipDistance);
float farDist = 0.0f;
Camera::CameraRequestBus::EventResult(farDist, entityId, &Camera::CameraRequestBus::Events::GetFarClipDistance);
float fovRad = 0.0f;
Camera::CameraRequestBus::EventResult(fovRad, entityId, &Camera::CameraRequestBus::Events::GetFovRadians);
const float aspectRatio = outputWidth / outputHeight;
AZ::Matrix4x4 viewToClipMatrix;
AZ::MakePerspectiveFovMatrixRH(viewToClipMatrix, fovRad, aspectRatio, nearDist, farDist, /*reverseDepth=*/true);
return viewToClipMatrix;
}
AZ::RPI::Scene* SceneFromGameEntityContext()
{
AzFramework::EntityContextId entityContextId;
AzFramework::GameEntityContextRequestBus::BroadcastResult(
entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId);
return AZ::RPI::Scene::GetSceneForEntityContextId(entityContextId);
}
} // namespace TrackView
@@ -0,0 +1,74 @@
/*
* 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 <Atom/Feature/Utils/FrameCaptureBus.h>
#include <AzFramework/Components/CameraBus.h>
namespace TrackView
{
//! Provides functionality to capture frames from the "MainCamera".
//! A new pipeline is created (and associated with the scene provided), a callback can be
//! provided to handle the attachment readback (what to do with the captured frame) and also
//! what to do after an individual capture fully completes (called in OnCaptureFinished).
class AtomOutputFrameCapture : private AZ::Render::FrameCaptureNotificationBus::Handler
{
public:
AtomOutputFrameCapture() = default;
using CaptureFinishedCallback = AZStd::function<void()>;
//! Create a new pipeline associated with a given scene.
//! @note "MainCamera" is the view that is captured.
void CreatePipeline(AZ::RPI::Scene& scene, const AZStd::string& pipelineName, uint32_t width, uint32_t height);
//! Removes the pipeline from the scene provided and then destroys it.
//! @note scene must be the same scene used to create the pipeline.
void DestroyPipeline(AZ::RPI::Scene& scene);
//! Request a capture to start.
//! @param attachmentReadbackCallback Handles the returned attachment (image data returned by the renderer).
//! @param captureFinishedCallback Logic to run once the capture has completed fully.
bool BeginCapture(
const AZ::RPI::AttachmentReadback::CallbackFunction& attachmentReadbackCallback,
CaptureFinishedCallback captureFinishedCallback);
//! Update the internal view that is associated with the created pipeline.
void UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection);
private:
AZ::RPI::RenderPipelinePtr m_renderPipeline; //!< The internal render pipeline.
AZ::RPI::ViewPtr m_view; //!< The view associated with the render pipeline.
AZStd::vector<AZStd::string> m_passHierarchy; //!< Pass hierarchy (includes pipelineName and CopyToSwapChain).
CaptureFinishedCallback m_captureFinishedCallback; //!< Stored callback called from OnCaptureFinished.
// FrameCaptureNotificationBus overrides ...
void OnCaptureFinished(AZ::Render::FrameCaptureResult result, const AZStd::string& info) override;
};
inline AZ::EntityId ActiveCameraEntityId()
{
AZ::EntityId activeCameraId;
Camera::CameraSystemRequestBus::BroadcastResult(activeCameraId, &Camera::CameraSystemRequests::GetActiveCamera);
return activeCameraId;
}
//! Returns the transform for the given EntityId.
AZ::Matrix3x4 TransformFromEntityId(AZ::EntityId entityId);
//! Returns the projection matrix for the given camera EntityId.
//! @note Must provide a valid camera entity.
AZ::Matrix4x4 ProjectionFromCameraEntityId(AZ::EntityId entityId, float outputWidth, float outputHeight);
//! Helper to return the GameEntityContext scene.
AZ::RPI::Scene* SceneFromGameEntityContext();
} // namespace TrackView
@@ -43,7 +43,6 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <TrackView/ui_SequenceBatchRenderDialog.h>
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
namespace
{
const int g_useActiveViewportResolution = -1; // reserved value to indicate the use of the active viewport resolution
@@ -92,6 +91,14 @@ namespace
}
}
static void UpdateAtomOutputFrameCaptureView(TrackView::AtomOutputFrameCapture& atomOutputFrameCapture, const int width, const int height)
{
const AZ::EntityId activeCameraEntityId = TrackView::ActiveCameraEntityId();
atomOutputFrameCapture.UpdateView(
TrackView::TransformFromEntityId(activeCameraEntityId),
TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, width, height));
}
CSequenceBatchRenderDialog::CSequenceBatchRenderDialog(float fps, QWidget* pParent /* = nullptr */)
: QDialog(pParent)
, m_fpsForTimeToFrameConversion(fps)
@@ -874,8 +881,6 @@ void CSequenceBatchRenderDialog::InitializeContext()
void CSequenceBatchRenderDialog::CaptureItemStart()
{
AZ::Render::FrameCaptureNotificationBus::Handler::BusConnect();
// Disable most of the UI in group chunks.
// (Leave the start/cancel button and feedback elements).
m_ui->BATCH_RENDER_LIST_GROUP_BOX->setEnabled(false);
@@ -976,20 +981,11 @@ void CSequenceBatchRenderDialog::CaptureItemStart()
m_renderContext.cvarCustomResHeightBU = pCVarCustomResHeight->GetIVal();
pCVarCustomResWidth->Set(renderWidth);
pCVarCustomResHeight->Set(renderHeight);
// awaiting ATOM-14859
// AzFramework::NativeWindowHandle windowHandle = nullptr;
// AzFramework::WindowSystemRequestBus::BroadcastResult(
// windowHandle, &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
// AzFramework::WindowRequestBus::Event(
// windowHandle, &AzFramework::WindowRequestBus::Events::ResizeClientArea,
// AzFramework::WindowSize(renderWidth, renderHeight));
}
else
{
// Otherwise, try to adjust the viewport resolution accordingly.
CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView();
if (viewPane)
if (CLayoutViewPane* viewPane = MainWindow::instance()->GetActiveView())
{
viewPane->ResizeViewport(renderWidth, renderHeight);
}
@@ -1008,6 +1004,11 @@ void CSequenceBatchRenderDialog::CaptureItemStart()
}
}
// create a new atom pipeline to capture the frames of the current sequence
m_atomOutputFrameCapture.CreatePipeline(
*TrackView::SceneFromGameEntityContext(), "TrackViewSequencePipeline", renderItem.resW, renderItem.resH);
UpdateAtomOutputFrameCaptureView(m_atomOutputFrameCapture, renderItem.resW, renderItem.resH);
GetIEditor()->GetMovieSystem()->EnableFixedStepForCapture(m_renderContext.captureOptions.timeStep);
// The capturing doesn't actually start here. It just flags the warming-up and
@@ -1205,7 +1206,7 @@ void CSequenceBatchRenderDialog::OnUpdateFinalize()
m_renderContext.frameNumber = 0;
m_renderContext.capturingFrame = false;
AZ::Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
m_atomOutputFrameCapture.DestroyPipeline(*TrackView::SceneFromGameEntityContext());
// Check to see if there is more items to process
bool done = m_renderContext.currentItemIndex == m_renderItems.size() - 1;
@@ -1330,6 +1331,9 @@ void CSequenceBatchRenderDialog::OnKickIdle()
// being captured, it's safe to move to the next step of the main update
if (!capturing() || !m_renderContext.capturingFrame)
{
const auto& renderItem = m_renderItems[m_renderContext.currentItemIndex];
// update the view given the current camera transform and projection
UpdateAtomOutputFrameCaptureView(m_atomOutputFrameCapture, renderItem.resW, renderItem.resH);
GetIEditor()->GetGameEngine()->Update(); // step update (original frame capture)
}
@@ -1341,14 +1345,24 @@ void CSequenceBatchRenderDialog::OnKickIdle()
m_renderContext.captureOptions.folder.c_str(), fileName.c_str(), filePath, /*caseInsensitive=*/true,
/*normalize=*/false);
bool capturedScreenshot = false;
AZ::Render::FrameCaptureRequestBus::BroadcastResult(
capturedScreenshot, &AZ::Render::FrameCaptureRequestBus::Events::CaptureScreenshot, filePath);
// track view callback after each frame is captured
const auto captureFinishedCallback = [this]() {
m_renderContext.capturingFrame = false;
GetIEditor()->GetMovieSystem()->EndCapture();
GetIEditor()->GetMovieSystem()->ControlCapture();
};
if (capturedScreenshot)
{
m_renderContext.capturingFrame = true;
}
// readback result callback (how the image should be captured)
// currently only .dds
const auto readbackCallback = [filePath](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult) {
if (const AZ::Render::FrameCaptureOutputResult result = AZ::Render::DdsFrameCaptureOutput(filePath, readbackResult);
result.m_errorMessage.has_value())
{
AZ_Printf("TrackView", "Frame capture failed: %s", result.m_errorMessage.value().c_str());
}
};
m_renderContext.capturingFrame = m_atomOutputFrameCapture.BeginCapture(readbackCallback, captureFinishedCallback);
}
}
else
@@ -1358,14 +1372,6 @@ void CSequenceBatchRenderDialog::OnKickIdle()
}
}
void CSequenceBatchRenderDialog::OnCaptureFinished(
[[maybe_unused]] AZ::Render::FrameCaptureResult result, [[maybe_unused]] const AZStd::string& info)
{
m_renderContext.capturingFrame = false;
GetIEditor()->GetMovieSystem()->EndCapture();
GetIEditor()->GetMovieSystem()->ControlCapture();
}
void CSequenceBatchRenderDialog::OnCancelRender()
{
if (m_renderContext.captureState == CaptureState::Capturing)
@@ -15,8 +15,9 @@
#pragma once
#include "AtomOutputFrameCapture.h"
#include <AzFramework/StringFunc/StringFunc.h>
#include <Atom/Feature/Utils/FrameCaptureBus.h>
#include <QDialog>
#include <QTimer>
@@ -33,7 +34,6 @@ namespace Ui
class CSequenceBatchRenderDialog
: public QDialog
, public IMovieListener
, private AZ::Render::FrameCaptureNotificationBus::Handler
{
public:
CSequenceBatchRenderDialog(float fps, QWidget* pParent = nullptr);
@@ -219,9 +219,6 @@ protected slots:
bool GetResolutionFromCustomResText(const char* customResText, int& retCustomWidth, int& retCustomHeight) const;
private:
// FrameCaptureNotificationBus overrides ...
void OnCaptureFinished(AZ::Render::FrameCaptureResult result, const AZStd::string& info) override;
void CheckForEnableUpdateButton();
void stashActiveViewportResolution();
void UpdateSpinnerProgressMessage(const char* description);
@@ -234,4 +231,6 @@ private:
bool m_editorIdleProcessingEnabled;
int32 CV_TrackViewRenderOutputCapturing;
QScopedPointer<CPrefixValidator> m_prefixValidator;
TrackView::AtomOutputFrameCapture m_atomOutputFrameCapture;
};
+7 -3
View File
@@ -26,6 +26,7 @@
// AzCore
#include <AzCore/Component/TickBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
// AzFramework
#include <AzFramework/API/ApplicationAPI.h>
@@ -751,10 +752,13 @@ bool CFileUtil::ScanDirectory(const QString& path, const QString& file, IFileUti
void CFileUtil::ShowInExplorer([[maybe_unused]] const QString& path)
{
const char* assetRoot;
EBUS_EVENT_RESULT(assetRoot, AzFramework::ApplicationRequests::Bus, GetAssetRoot);
AZStd::string assetRoot;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
settingsRegistry->Get(assetRoot, AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder);
}
QString fullpath(assetRoot);
auto fullpath = QString::fromUtf8(assetRoot.c_str(), aznumeric_cast<int>(assetRoot.size()));
AzQtComponents::ShowFileOnDesktop(fullpath);
}
@@ -25,6 +25,8 @@
#include <QDesktopWidget>
#include <QTimer>
#include <AzCore/Utils/Utils.h>
// AzFramework
#include <AzFramework/API/ApplicationAPI.h>
@@ -93,7 +95,8 @@ WelcomeScreenDialog::WelcomeScreenDialog(QWidget* pParent)
auto currentProjectButtonMenu = new QMenu();
ui->currentProjectButton->setMenu(currentProjectButtonMenu);
ui->currentProjectButton->setText(gEnv->pConsole->GetCVar("sys_game_folder")->GetString());
auto projectName = AZ::Utils::GetProjectName();
ui->currentProjectButton->setText(projectName.c_str());
ui->currentProjectButton->adjustSize();
ui->currentProjectButton->setMinimumWidth(ui->currentProjectButton->width() + 40);
@@ -193,10 +196,9 @@ void WelcomeScreenDialog::SetRecentFileList(RecentFileList* pList)
const char* engineRoot;
EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
AZStd::string gamePathString;
AZ::StringFunc::Path::Join(engineRoot, gEnv->pConsole->GetCVar("sys_game_folder")->GetString(), gamePathString);
QString gamePath = QString(gamePathString.c_str());
auto projectPath = AZ::Utils::GetProjectPath();
QString gamePath{projectPath.c_str()};
Path::ConvertSlashToBackSlash(gamePath);
gamePath = Path::ToUnixPath(gamePath.toLower());
gamePath = Path::AddSlash(gamePath);
@@ -807,6 +807,8 @@ set(FILES
EnvironmentPanel.cpp
EnvironmentPanel.h
EnvironmentPanel.ui
TrackView/AtomOutputFrameCapture.cpp
TrackView/AtomOutputFrameCapture.h
TrackView/TrackViewDialog.qrc
TrackView/TrackViewDialog.cpp
TrackView/TrackViewDialog.h