Ver Fonte

Add an error message to AP when the project path is invalid (#4801)

* Add an error message to AP when bad project path

Produce a log error or a dialog box error when the project path for AP
does not have a project.json and is invalid.

Signed-off-by: amzn-phist <[email protected]>

* Fix a failing unit test - AssetProcessorMessages

Adding a check for 'project.json' caused BeforeRun() in a test fixture
to fail.  Teardown of the fixture was also broken if the test failed to
fully startup the application manager, so added null checks there.

Added an assert to the fixture's Setup to check the status of BeforeRun().
Added additional settings registry setup to the fixture to make sure the
project path and branch token are configured before BeforeRun() is
called.

Signed-off-by: amzn-phist <[email protected]>
amzn-phist há 3 anos atrás
pai
commit
714f5357b2

+ 32 - 10
Code/Tools/AssetProcessor/native/tests/AssetProcessorMessagesTests.cpp

@@ -10,7 +10,9 @@
 #include <utilities/BatchApplicationManager.h>
 #include <utilities/ApplicationServer.h>
 #include <AzFramework/Asset/AssetSystemComponent.h>
+#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
 #include <AzCore/UnitTest/TestTypes.h>
+#include <AzCore/Utils/Utils.h>
 #include <connection/connectionManager.h>
 #include <QCoreApplication>
 #include <QTemporaryDir>
@@ -98,10 +100,26 @@ namespace AssetProcessorMessagesTests
 
             int argC = 0;
             m_batchApplicationManager = AZStd::make_unique<UnitTestBatchApplicationManager>(&argC, nullptr, nullptr);
-            m_batchApplicationManager->BeforeRun();
 
-            // Override Game Name to be "AutomatedTesting"
-            AssetUtilities::ComputeProjectName("AutomatedTesting", true);
+            auto registry = AZ::SettingsRegistry::Get();
+            EXPECT_NE(registry, nullptr);
+            constexpr AZ::SettingsRegistryInterface::FixedValueString bootstrapKey{
+                AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey
+            };
+            constexpr AZ::SettingsRegistryInterface::FixedValueString projectPathKey{ bootstrapKey + "/project_path" };
+            registry->Set(projectPathKey, "AutomatedTesting");
+            AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
+
+            // Force the branch token into settings registry before starting the application manager.
+            // This avoids writing the asset_processor.setreg file which can cause fileIO errors.
+            const AZ::IO::FixedMaxPathString enginePath = AZ::Utils::GetEnginePath();
+            constexpr AZ::SettingsRegistryInterface::FixedValueString branchTokenKey{ bootstrapKey + "/assetProcessor_branch_token" };
+            AZStd::string token;
+            AZ::StringFunc::AssetPath::CalculateBranchToken(enginePath.c_str(), token);
+            registry->Set(branchTokenKey, token.c_str());
+
+            auto status = m_batchApplicationManager->BeforeRun();
+            ASSERT_EQ(status, ApplicationManager::BeforeRunStatus::Status_Success);
 
             m_batchApplicationManager->m_platformConfiguration = new PlatformConfiguration();
             m_batchApplicationManager->InitAssetProcessorManager();
@@ -159,21 +177,25 @@ namespace AssetProcessorMessagesTests
 
                     ASSERT_TRUE(result);
                 });
-
-            
         }
 
         void TearDown() override
         {
-            QEventLoop eventLoop;
+            if (m_batchApplicationManager->m_connectionManager)
+            {
+                QEventLoop eventLoop;
 
-            QObject::connect(m_batchApplicationManager->m_connectionManager, &ConnectionManager::ReadyToQuit, &eventLoop, &QEventLoop::quit);
+                QObject::connect(m_batchApplicationManager->m_connectionManager, &ConnectionManager::ReadyToQuit, &eventLoop, &QEventLoop::quit);
 
-            m_batchApplicationManager->m_connectionManager->QuitRequested();
+                m_batchApplicationManager->m_connectionManager->QuitRequested();
 
-            eventLoop.exec();
+                eventLoop.exec();
+            }
 
-            m_assetSystemComponent->Deactivate();
+            if (m_assetSystemComponent)
+            {
+                m_assetSystemComponent->Deactivate();
+            }
             m_batchApplicationManager->Destroy();
         }
 

+ 8 - 1
Code/Tools/AssetProcessor/native/utilities/ApplicationManager.cpp

@@ -505,6 +505,14 @@ bool ApplicationManager::StartAZFramework()
     AzFramework::Application::Descriptor appDescriptor;
     AZ::ComponentApplication::StartupParameters params;
 
+    QDir projectPath{ AssetUtilities::ComputeProjectPath() };
+    if (!projectPath.exists("project.json"))
+    {
+        AZStd::string errorMsg = AZStd::string::format("Path '%s' is not a valid project path.", projectPath.path().toUtf8().constData());
+        AssetProcessor::MessageInfoBus::Broadcast(&AssetProcessor::MessageInfoBus::Events::OnErrorMessage, errorMsg.c_str());
+        return false;
+    }
+
     QString projectName = AssetUtilities::ComputeProjectName();
 
     // Prevent loading of gems in the Create method of the ComponentApplication
@@ -520,7 +528,6 @@ bool ApplicationManager::StartAZFramework()
     //Registering all the Components
     m_frameworkApp.RegisterComponentDescriptor(AzFramework::LogComponent::CreateDescriptor());
 
-
     Reflect();
 
     const AzFramework::CommandLine* commandLine = nullptr;

+ 3 - 93
Code/Tools/AssetProcessor/native/utilities/GUIApplicationManager.cpp

@@ -95,6 +95,8 @@ GUIApplicationManager::~GUIApplicationManager()
 
 ApplicationManager::BeforeRunStatus GUIApplicationManager::BeforeRun()
 {
+    AssetProcessor::MessageInfoBus::Handler::BusConnect();
+
     ApplicationManager::BeforeRunStatus status = ApplicationManagerBase::BeforeRun();
     if (status != ApplicationManager::BeforeRunStatus::Status_Success)
     {
@@ -109,7 +111,6 @@ ApplicationManager::BeforeRunStatus GUIApplicationManager::BeforeRun()
 #if defined(EXTERNAL_CRASH_REPORTING)
     CrashHandler::ToolsCrashHandler::InitCrashHandler("AssetProcessor", projectAssetRoot.absolutePath().toStdString());
 #endif
-    AssetProcessor::MessageInfoBus::Handler::BusConnect();
 
     // we have to monitor both the cache folder and the database file and restart AP if either of them gets deleted
     // It is important to note that we are monitoring the parent folder and not the actual cache folder itself since
@@ -436,98 +437,7 @@ bool GUIApplicationManager::OnError(const char* /*window*/, const char* message)
         connection = Qt::QueuedConnection;
     }
 
-    if (m_isCurrentlyLoadingGems)
-    {
-        // if something goes wrong during gem initialization, this is a special case and we need to be extra helpful.
-        const char* userSettingsFile = "_WAF_/user_settings.options";
-        const char* defaultSettingsFile = "_WAF_/default_settings.json";
-
-        QDir engineRoot;
-        AssetUtilities::ComputeEngineRoot(engineRoot);
-
-        QString settingsPath = engineRoot.absoluteFilePath(userSettingsFile);
-        QString friendlyErrorMessage;
-        bool usingDefaults = false;
-
-        if (QFile::exists(settingsPath))
-        {
-            QSettings loader(settingsPath, QSettings::IniFormat);
-            QVariant settingValue = loader.value("Game Projects/enabled_game_projects");
-            QStringList compiledProjects = settingValue.toStringList();
-
-            if (compiledProjects.isEmpty())
-            {
-                QByteArray byteArray;
-                QFile jsonFile;
-                jsonFile.setFileName(engineRoot.absoluteFilePath(defaultSettingsFile));
-                jsonFile.open(QIODevice::ReadOnly | QIODevice::Text);
-                byteArray = jsonFile.readAll();
-                jsonFile.close();
-
-                QJsonObject settingsObject = QJsonDocument::fromJson(byteArray).object();
-                QJsonArray projectsArray = settingsObject["Game Projects"].toArray();
-
-                if (!projectsArray.isEmpty())
-                {
-                    auto projectObject = projectsArray[0].toObject();
-                    QString projects = projectObject["default_value"].toString();
-
-                    if (!projects.isEmpty())
-                    {
-                        compiledProjects = projects.split(',');
-                        usingDefaults = true;
-                    }
-                }
-            }
-
-            for (int i = 0; i < compiledProjects.size(); ++i)
-            {
-                compiledProjects[i] = compiledProjects[i].trimmed();
-            }
-
-            QString enabledProject = AssetUtilities::ComputeProjectName();
-
-            if (!compiledProjects.contains(enabledProject))
-            {
-                QString projectSourceLine;
-
-                if (usingDefaults)
-                {
-                    projectSourceLine = QString("The currently compiled projects according to the defaults in %1 are '%2'").arg(defaultSettingsFile);
-                }
-                else
-                {
-                    projectSourceLine = QString("The currently compiled projects according to %1 are '%2'").arg(userSettingsFile);
-                }
-
-                projectSourceLine = projectSourceLine.arg(compiledProjects.join(", "));
-                friendlyErrorMessage = QString("An error occurred while loading gems.\n"
-                    "The enabled game project is not in the list of compiled projects.\n"
-                    "Please configure the enabled project to be compiled and rebuild or change the enabled project.\n"
-                    "The currently enabled game project (from bootstrap.cfg or /%4 command-line parameter) is '%1'.\n"
-                    "%2\n"
-                    "Full error text:\n"
-                    "%3"
-                ).arg(enabledProject).arg(projectSourceLine).arg(message).arg(AssetUtilities::ProjectPathOverrideParameter);
-            }
-        }
-
-        if (friendlyErrorMessage.isEmpty())
-        {
-            friendlyErrorMessage = QString("An error occurred while loading gems.\n"
-                "This can happen when new gems are added to a project, but those gems need to be built in order to function.\n"
-                "This can also happen when switching to a different project, one which uses gems which are not yet built.\n"
-                "To continue, please build the current project before attempting to run Asset Processor again.\n\n"
-                "Full error text:\n"
-                "%1").arg(message);
-        }
-        QMetaObject::invokeMethod(this, "ShowMessageBox", connection, Q_ARG(QString, QString("Error")), Q_ARG(QString, friendlyErrorMessage), Q_ARG(bool, true));
-    }
-    else
-    {
-        QMetaObject::invokeMethod(this, "ShowMessageBox", connection, Q_ARG(QString, QString("Error")), Q_ARG(QString, QString(message)), Q_ARG(bool, true));
-    }
-    
+    QMetaObject::invokeMethod(this, "ShowMessageBox", connection, Q_ARG(QString, QString("Error")), Q_ARG(QString, QString(message)), Q_ARG(bool, true));
 
     return true;
 }