/* * 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 "../utilities/ApplicationManagerAPI.h" #include "native/AssetManager/assetProcessorManager.h" #include "native/utilities/PlatformConfiguration.h" namespace AssetProcessor { struct RCCompiler { //! RC.exe execution result struct Result { Result(int exitCode, bool crashed, const QString& outputDir); Result() = default; int m_exitCode = 1; bool m_crashed = false; QString m_outputDir; }; virtual ~RCCompiler() = default; virtual bool Initialize(const QString& systemRoot, const QString& rcExecutableFullPath) = 0; virtual bool Execute(const QString& inputFile, const QString& watchFolder, const QString& platformIdentifier, const QString& params, const QString& dest, const AssetBuilderSDK::JobCancelListener* jobCancelListener, Result& result) const = 0; virtual void RequestQuit() = 0; }; //! Worker class to handle shell execution of the legacy rc.exe compiler class NativeLegacyRCCompiler : public RCCompiler { public: NativeLegacyRCCompiler(); bool Initialize(const QString& systemRoot, const QString& rcExecutableFullPath) override; bool Execute(const QString& inputFile, const QString& watchFolder, const QString& platformIdentifier, const QString& params, const QString& dest, const AssetBuilderSDK::JobCancelListener* jobCancelListener, Result& result) const override; static QString BuildCommand(const QString& inputFile, const QString& watchFolder, const QString& platformIdentifier, const QString& params, const QString& dest); void RequestQuit() override; private: static const int s_maxSleepTime; static const unsigned int s_jobMaximumWaitTime; bool m_resourceCompilerInitialized; QDir m_systemRoot; QString m_rcExecutableFullPath; volatile bool m_requestedQuit; }; //! Internal structure that consolidates a internal builder id, its name, and its custom fixed rc param match class BuilderIdAndName { public: enum class Type { REGISTERED_BUILDER, UNREGISTERED_BUILDER }; BuilderIdAndName() = default; BuilderIdAndName(QString builderName, QString builderId, Type type, QString rcParam = QString("")); BuilderIdAndName(const BuilderIdAndName& src) = default; BuilderIdAndName& operator=(const AssetProcessor::BuilderIdAndName& src); const QString& GetName() const; bool GetUuid(AZ::Uuid& builderUuid) const; const QString& GetRcParam() const; const QString& GetId() const; const Type GetType() const; private: Type m_type = Type::UNREGISTERED_BUILDER; QString m_builderName; QString m_builderId; QString m_rcParam; }; extern const BuilderIdAndName BUILDER_ID_COPY; extern const BuilderIdAndName BUILDER_ID_RC; extern const BuilderIdAndName BUILDER_ID_SKIP; extern const QHash INTERNAL_BUILDER_BY_ID; //! Internal Builder version of the asset recognizer structure that is read in from the platform configuration class struct InternalAssetRecognizer : public AssetRecognizer { InternalAssetRecognizer(const AssetRecognizer& src, const QString& builderId, const QHash& assetPlatformSpecByPlatform); InternalAssetRecognizer(const InternalAssetRecognizer& src) = default; AZ::u32 CalculateCRC() const; //! Map of platform specs based on the identifier of the platform QHash m_platformSpecsByPlatform; //! unique id that is generated for each unique internal asset recognizer //! which can be used as the key for the job parameter map (see AssetBuilderSDK::JobParameterMap) AZ::u32 m_paramID; //! Keep track which internal builder type this recognizer is for const QString m_builderId; }; typedef QHash InternalRecognizerContainer; typedef QList InternalRecognizerPointerContainer; typedef AZStd::function RegisterBuilderDescCallback; typedef AZStd::list InternalAssetRecognizerList; class InternalRecognizerBasedBuilder : public AssetBuilderSDK::AssetBuilderCommandBus::Handler { public: //! Constructor to initialize the internal based builder to a present set of internal builders and fixed bus id InternalRecognizerBasedBuilder(); virtual ~InternalRecognizerBasedBuilder(); AssetBuilderSDK::AssetBuilderDesc CreateBuilderDesc(const QString& builderId, const AZStd::vector& builderPatterns); void ShutDown() override; virtual bool Initialize(const RecognizerConfiguration& recognizerConfig); virtual void InitializeAssetRecognizers(const RecognizerContainer& assetRecognizers); virtual void UnInitialize(); //! Returns false if there were no matches, otherwise returns true virtual bool GetMatchingRecognizers(const AZStd::vector& platformInfos, const QString& fileName, InternalRecognizerPointerContainer& output) const; void CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response); void ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response); static bool MatchTempFileToSkip(const QString& outputFilename); static void RegisterInternalAssetRecognizerToMap( const AssetRecognizer& assetRecognizer, const QString& builderId, QHash& sourceAssetPlatformSpecs, QHash& internalRecognizerListByType); //! Split all of the asset recognizers from a container into buckets based on their specific builder action type static void BuildInternalAssetRecognizersByType( const RecognizerContainer& assetRecognizers, QHash& internalRecognizerListByType); protected: //! Constructor to initialize the internal builders and a general internal builder uuid that is used for bus //! registration. This constructor is helpful for deriving other classes from this builder for purposes like //! unit testing. InternalRecognizerBasedBuilder(QHash inputBuilderByIdMap, AZ::Uuid internalBuilderUuid); // overridden in unit tests. Searches for RC.EXE virtual bool FindRC(QString& rcAbsolutePathOut); void CreateLegacyRCJob( const AssetBuilderSDK::CreateJobsRequest& request, QString rcParam, AssetBuilderSDK::CreateJobsResponse& response); void ProcessLegacyRCJob( const AssetBuilderSDK::ProcessJobRequest& request, QString rcParam, AZ::Uuid productAssetType, const AssetBuilderSDK::JobCancelListener& jobCancelListener, AssetBuilderSDK::ProcessJobResponse& response); //! Given a folder (dest) containing the aftermath of a RC process, generate a response structure. //! if responseFromRCCompiler is true it means that the response is an already-populated response struct //! that was loaded from a response file and we should just append legacy SubIDs to it (responses are used INSTEAD of //! heuristics). //! otherwise it means that we know nothing about the files that were produced and should perform heuristics to determine. //! productAssetType is what uuid type (or nulls) to apply to the generated products for when responseFromRCCompiler is false. void ProcessRCResultFolder(const QString &dest, const AZ::Uuid& productAssetType, bool responseFromRCCompiler, AssetBuilderSDK::ProcessJobResponse &response); void ProcessCopyJob( const AssetBuilderSDK::ProcessJobRequest& request, AZ::Uuid productAssetType, bool outputProductDependencies, const AssetBuilderSDK::JobCancelListener& jobCancelListener, AssetBuilderSDK::ProcessJobResponse& response); // overridable so we can unit-test override it. virtual QFileInfoList GetFilesInDirectory(const QString& directoryPath); // overridable so we can unit-test override it. virtual bool SaveProcessJobRequestFile(const char* requestFileDir, const char* requestFileName, const AssetBuilderSDK::ProcessJobRequest& request); // returns false only if there is a critical failure. virtual bool LoadProcessJobResponseFile(const char* responseFileDir, const char* responseFileName, AssetBuilderSDK::ProcessJobResponse& response, bool& responseLoaded); AZStd::unique_ptr m_rcCompiler; volatile bool m_isShuttingDown; InternalRecognizerContainer m_assetRecognizerDictionary; QHash m_builderById; //! UUid for the internal recognizer for logging purposes since the this //! class manages multiple internal build uuids AZ::Uuid m_internalRecognizerBuilderUuid; }; } // namespace AssetProcessor