PlatformConfiguration.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #ifndef PLATFORMCONFIGURATION_H
  9. #define PLATFORMCONFIGURATION_H
  10. #if !defined(Q_MOC_RUN)
  11. #include <QList>
  12. #include <QString>
  13. #include <QObject>
  14. #include <QHash>
  15. #include <QRegExp>
  16. #include <QPair>
  17. #include <QVector>
  18. #include <QSet>
  19. #include <AzCore/Settings/SettingsRegistry.h>
  20. #include <AzCore/Settings/SettingsRegistryVisitorUtils.h>
  21. #include <AzCore/std/string/string.h>
  22. #include <native/utilities/assetUtils.h>
  23. #include <native/AssetManager/assetScanFolderInfo.h>
  24. #include <AssetBuilderSDK/AssetBuilderSDK.h>
  25. #include <AzToolsFramework/Asset/AssetUtils.h>
  26. #endif
  27. #include "IPathConversion.h"
  28. namespace AZ
  29. {
  30. class SettingsRegistryInterface;
  31. }
  32. namespace AssetProcessor
  33. {
  34. inline constexpr const char* AssetProcessorSettingsKey{ "/Amazon/AssetProcessor/Settings" };
  35. inline constexpr const char* AssetProcessorServerKey{ "/O3DE/AssetProcessor/Settings/Server" };
  36. class PlatformConfiguration;
  37. class ScanFolderInfo;
  38. extern const char AssetConfigPlatformDir[];
  39. extern const char AssetProcessorPlatformConfigFileName[];
  40. //! Information for a given recognizer, on a specific platform
  41. //! essentially a plain data holder, but with helper funcs
  42. enum class AssetInternalSpec
  43. {
  44. Copy,
  45. Skip
  46. };
  47. //! The data about a particular recognizer, including all platform specs.
  48. //! essentially a plain data holder, but with helper funcs
  49. struct AssetRecognizer
  50. {
  51. AZ_CLASS_ALLOCATOR(AssetRecognizer, AZ::SystemAllocator);
  52. AZ_TYPE_INFO(AssetRecognizer, "{29B7A73A-4D7F-4C19-AEAC-6D6750FB1156}");
  53. AssetRecognizer() = default;
  54. AssetRecognizer(
  55. const AZStd::string& name,
  56. bool testLockSource,
  57. int priority,
  58. bool critical,
  59. bool supportsCreateJobs,
  60. AssetBuilderSDK::FilePatternMatcher patternMatcher,
  61. const AZStd::string& version,
  62. const AZ::Data::AssetType& productAssetType,
  63. bool outputProductDependencies,
  64. bool checkServer = false)
  65. : m_name(name)
  66. , m_testLockSource(testLockSource)
  67. , m_priority(priority)
  68. , m_isCritical(critical)
  69. , m_supportsCreateJobs(supportsCreateJobs)
  70. , m_patternMatcher(patternMatcher)
  71. , m_version(version)
  72. , m_productAssetType(productAssetType) // if specified, it allows you to assign a UUID for the type of products directly.
  73. , m_outputProductDependencies(outputProductDependencies)
  74. , m_checkServer(checkServer)
  75. {}
  76. AZStd::string m_name;
  77. AssetBuilderSDK::FilePatternMatcher m_patternMatcher;
  78. AZStd::string m_version = {};
  79. // the QString is the Platform Identifier ("pc")
  80. // the AssetInternalSpec specifies the type of internal job to process
  81. AZStd::unordered_map<AZStd::string, AssetInternalSpec> m_platformSpecs;
  82. // an optional parameter which is a UUID of types to assign to the output asset(s)
  83. // if you don't specify one, then a heuristic will be used
  84. AZ::Uuid m_productAssetType = AZ::Uuid::CreateNull();
  85. int m_priority = 0; // used in order to sort these jobs vs other jobs when no other priority is applied (such as platform connected)
  86. bool m_testLockSource = false;
  87. bool m_isCritical = false;
  88. bool m_checkServer = false;
  89. bool m_supportsCreateJobs = false; // used to indicate a recognizer that can respond to a createJobs request
  90. bool m_outputProductDependencies = false;
  91. };
  92. //! Dictionary of Asset Recognizers based on name
  93. typedef AZStd::unordered_map<AZStd::string, AssetRecognizer> RecognizerContainer;
  94. typedef QList<const AssetRecognizer*> RecognizerPointerContainer;
  95. //! The structure holds information about a particular exclude recognizer
  96. struct ExcludeAssetRecognizer
  97. {
  98. QString m_name;
  99. AssetBuilderSDK::FilePatternMatcher m_patternMatcher;
  100. };
  101. typedef QHash<QString, ExcludeAssetRecognizer> ExcludeRecognizerContainer;
  102. //! Interface to get constant references to asset and exclude recognizers
  103. struct RecognizerConfiguration
  104. {
  105. AZ_RTTI(RecognizerConfiguration, "{2E4DD73E-8D1E-42BC-A3E3-1A671D636DAC}");
  106. virtual const RecognizerContainer& GetAssetRecognizerContainer() const = 0;
  107. virtual const RecognizerContainer& GetAssetCacheRecognizerContainer() const = 0;
  108. virtual const ExcludeRecognizerContainer& GetExcludeAssetRecognizerContainer() const = 0;
  109. virtual bool AddAssetCacheRecognizerContainer(const RecognizerContainer& recognizerContainer) = 0;
  110. };
  111. /** Reads the platform ini configuration file to determine
  112. * platforms for which assets needs to be build
  113. */
  114. class PlatformConfiguration
  115. : public QObject
  116. , public RecognizerConfiguration
  117. , public AZ::Interface<IPathConversion>::Registrar
  118. {
  119. Q_OBJECT
  120. public:
  121. AZ_RTTI(PlatformConfiguration, "{9F0C465D-A3A6-417E-B69C-62CBD22FD950}", RecognizerConfiguration, IPathConversion);
  122. typedef QPair<QRegExp, QString> RCSpec;
  123. typedef QVector<RCSpec> RCSpecList;
  124. public:
  125. explicit PlatformConfiguration(QObject* pParent = nullptr);
  126. virtual ~PlatformConfiguration() = default;
  127. static void Reflect(AZ::ReflectContext* context);
  128. /** Use this function to parse the set of config files and the gem file to set up the platform config.
  129. * This should be about the only function that is required to be called in order to end up with
  130. * a full configuration.
  131. * Note that order of the config files is relevant - later files override settings in
  132. * files that are earlier.
  133. **/
  134. bool InitializeFromConfigFiles(const QString& absoluteSystemRoot, const QString& absoluteAssetRoot, const QString& projectPath, bool addPlatformConfigs = true, bool addGemsConfigs = true);
  135. //! Merge an AssetProcessor*Config.ini path to the Settings Registry
  136. //! The settings are anchored underneath the AssetProcessor::AssetProcessorSettingsKey JSON pointer
  137. static bool MergeConfigFileToSettingsRegistry(AZ::SettingsRegistryInterface& settingsRegistry, const AZ::IO::PathView& filePathView);
  138. const AZStd::vector<AssetBuilderSDK::PlatformInfo>& GetEnabledPlatforms() const;
  139. const AssetBuilderSDK::PlatformInfo* const GetPlatformByIdentifier(const char* identifier) const;
  140. //! Add AssetProcessor config files from platform specific folders
  141. bool AddPlatformConfigFilePaths(AZStd::vector<AZ::IO::Path>& configList);
  142. int MetaDataFileTypesCount() const { return m_metaDataFileTypes.count(); }
  143. // Metadata file types are (meta file extension, original file extension - or blank if its tacked on the end instead of replacing).
  144. // so for example if its
  145. // blah.tif + blah.tif.metadata, then its ("metadata", "")
  146. // but if its blah.tif + blah.metadata (replacing tif, data is lost) then its ("metadata", "tif")
  147. QPair<QString, QString> GetMetaDataFileTypeAt(int pos) const;
  148. // Metadata extensions can also be a real file, to create a dependency on file types if a specific file changes
  149. // so for example, a Metadata file type pair ("Animations/SkeletonList.xml", "i_caf")
  150. // would cause all i_caf files to be re-evaluated when Animations/SkeletonList.xml is modified.
  151. bool IsMetaDataTypeRealFile(QString relativeName) const;
  152. void EnablePlatform(const AssetBuilderSDK::PlatformInfo& platform, bool enable = true);
  153. //! Gets the minumum jobs specified in the configuration file
  154. int GetMinJobs() const;
  155. int GetMaxJobs() const;
  156. void EnableCommonPlatform();
  157. void AddIntermediateScanFolder();
  158. //! Return how many scan folders there are
  159. int GetScanFolderCount() const;
  160. //! Return the gems info list
  161. AZStd::vector<AzFramework::GemInfo> GetGemsInformation() const;
  162. //! Retrieve the scan folder at a given index.
  163. AssetProcessor::ScanFolderInfo& GetScanFolderAt(int index);
  164. //! Retrieve the scan folder at a given index.
  165. const AssetProcessor::ScanFolderInfo& GetScanFolderAt(int index) const;
  166. //! Retrieve the scan folder found by a boolean predicate function, when the predicate returns true, the current scan folder info is returned.
  167. const AssetProcessor::ScanFolderInfo* FindScanFolder(AZStd::function<bool(const AssetProcessor::ScanFolderInfo&)> predicate) const;
  168. const AssetProcessor::ScanFolderInfo* GetScanFolderById(AZ::s64 id) const override;
  169. const AZ::s64 GetIntermediateAssetScanFolderId() const;
  170. //! Manually add a scan folder. Also used for testing.
  171. void AddScanFolder(const AssetProcessor::ScanFolderInfo& source, bool isUnitTesting = false);
  172. //! Manually add a recognizer. Used for testing.
  173. void AddRecognizer(const AssetRecognizer& source);
  174. //! Manually remove a recognizer. Used for testing.
  175. void RemoveRecognizer(QString name);
  176. //! Manually add an exclude recognizer. Used for testing.
  177. void AddExcludeRecognizer(const ExcludeAssetRecognizer& recogniser);
  178. //! Manually remove an exclude recognizer. Used for testing.
  179. void RemoveExcludeRecognizer(QString name);
  180. //! Manually add a metadata type. Used for testing.
  181. //! The originalextension, if specified, means this metafile type REPLACES the given extension
  182. //! If not specified (blank) it means that the metafile extension is added onto the end instead and does
  183. //! not remove the original file extension
  184. void AddMetaDataType(const QString& type, const QString& originalExtension);
  185. // ------------------- utility functions --------------------
  186. //! Checks to see whether the input file is an excluded file, assumes input is absolute path.
  187. bool IsFileExcluded(QString fileName) const;
  188. //! If you already have a relative path, this is a cheaper function to call:
  189. bool IsFileExcludedRelPath(QString relPath) const;
  190. //! Given a file name, return a container that contains all matching recognizers
  191. //!
  192. //! Returns false if there were no matches, otherwise returns true
  193. bool GetMatchingRecognizers(QString fileName, RecognizerPointerContainer& output) const;
  194. //! given a fileName (as a relative and which scan folder it was found in)
  195. //! Return either an empty string, or the canonical path to a file which overrides it
  196. //! because of folder priority.
  197. //! Note that scanFolderName is only used to exit quickly
  198. //! If its found in any scan folder before it arrives at scanFolderName it will be considered a hit
  199. QString GetOverridingFile(QString relativeName, QString scanFolderName) const;
  200. //! given a relative name, loop over folders and resolve it to a full path with the first existing match.
  201. QString FindFirstMatchingFile(QString relativeName, bool skipIntermediateScanFolder = false, const AssetProcessor::ScanFolderInfo** scanFolderInfo = nullptr) const;
  202. //! given a relative name with wildcard characters (* allowed) find a set of matching files or optionally folders
  203. QStringList FindWildcardMatches(const QString& sourceFolder, QString relativeName, bool includeFolders = false,
  204. bool recursiveSearch = true) const;
  205. //! given a relative name with wildcard characters (* allowed) find a set of matching files or optionally folders
  206. QStringList FindWildcardMatches(
  207. const QString& sourceFolder,
  208. QString relativeName,
  209. const AZStd::unordered_set<AZStd::string>& excludedFolders,
  210. bool includeFolders = false,
  211. bool recursiveSearch = true) const;
  212. //! given a fileName (as a full path), return the database source name which includes the output prefix.
  213. //!
  214. //! for example
  215. //! c:/dev/mygame/textures/texture1.tga
  216. //! ----> [textures/texture1.tga] found under [c:/dev/mygame]
  217. //! c:/dev/engine/models/box01.mdl
  218. //! ----> [models/box01.mdl] found under[c:/dev/engine]
  219. //! note that this does return a database source path by default
  220. bool ConvertToRelativePath(QString fullFileName, QString& databaseSourceName, QString& scanFolderName) const override;
  221. static bool ConvertToRelativePath(const QString& fullFileName, const ScanFolderInfo* scanFolderInfo, QString& databaseSourceName);
  222. //! given a full file name (assumed already fed through the normalization funciton), return the first matching scan folder
  223. const AssetProcessor::ScanFolderInfo* GetScanFolderForFile(const QString& fullFileName) const override;
  224. //! Given a scan folder path, get its complete info
  225. const AssetProcessor::ScanFolderInfo* GetScanFolderByPath(const QString& scanFolderPath) const;
  226. const RecognizerContainer& GetAssetRecognizerContainer() const override;
  227. const RecognizerContainer& GetAssetCacheRecognizerContainer() const override;
  228. const ExcludeRecognizerContainer& GetExcludeAssetRecognizerContainer() const override;
  229. bool AddAssetCacheRecognizerContainer(const RecognizerContainer& recognizerContainer) override;
  230. static bool ConvertToJson(const RecognizerContainer& recognizerContainer, AZStd::string& jsonText);
  231. static bool ConvertFromJson(const AZStd::string& jsonText, RecognizerContainer& recognizerContainer);
  232. /** returns true if the config is valid.
  233. * configs are considered invalid if critical information is missing.
  234. * for example, if no recognizers are given, or no platforms are enabled.
  235. * They can also be considered invalid if a critical parse error occurred during load.
  236. */
  237. bool IsValid() const;
  238. /** If IsValid is false, this will contain the full error string to show to the user.
  239. * Note that IsValid will automatically write this error string to stderror as part of checking
  240. * So this function is there for those wishing to use a GUI.
  241. */
  242. const AZStd::string& GetError() const;
  243. void PopulatePlatformsForScanFolder(AZStd::vector<AssetBuilderSDK::PlatformInfo>& platformsList, QStringList includeTagsList = QStringList(), QStringList excludeTagsList = QStringList());
  244. // uses const + mutability since its a cache.
  245. void CacheIntermediateAssetsScanFolderId() const;
  246. AZStd::optional<AZ::s64> GetIntermediateAssetsScanFolderId() const;
  247. void ReadMetaDataFromSettingsRegistry();
  248. protected:
  249. // call this first, to populate the list of platform informations
  250. void ReadPlatformInfosFromSettingsRegistry();
  251. // call this next, in order to find out what platforms are enabled
  252. void PopulateEnabledPlatforms();
  253. // finally, call this, in order to delete the platforminfos for non-enabled platforms
  254. void FinalizeEnabledPlatforms();
  255. // iterate over all the gems and add their folders to the "scan folders" list as appropriate.
  256. void AddGemScanFolders(const AZStd::vector<AzFramework::GemInfo>& gemInfoList);
  257. void ReadEnabledPlatformsFromSettingsRegistry();
  258. bool ReadRecognizersFromSettingsRegistry(const QString& assetRoot, bool skipScanFolders = false, QStringList scanFolderPatterns = QStringList() );
  259. int GetProjectScanFolderOrder() const;
  260. private:
  261. AZStd::vector<AssetBuilderSDK::PlatformInfo> m_enabledPlatforms;
  262. RecognizerContainer m_assetRecognizers;
  263. RecognizerContainer m_assetCacheServerRecognizers;
  264. ExcludeRecognizerContainer m_excludeAssetRecognizers;
  265. AZStd::vector<AssetProcessor::ScanFolderInfo> m_scanFolders;
  266. QList<QPair<QString, QString> > m_metaDataFileTypes;
  267. QSet<QString> m_metaDataRealFiles;
  268. AZStd::vector<AzFramework::GemInfo> m_gemInfoList;
  269. mutable AZ::s64 m_intermediateAssetScanFolderId = -1; // Cached ID for intermediate scanfolder, for quick lookups
  270. int m_minJobs = 1;
  271. int m_maxJobs = 3;
  272. // used only during file read, keeps the total running list of all the enabled platforms from all config files and command lines
  273. AZStd::vector<AZStd::string> m_tempEnabledPlatforms;
  274. ///! if non-empty, fatalError contains the error that occurred during read.
  275. ///! it will be printed out to the log when
  276. mutable AZStd::string m_fatalError;
  277. };
  278. } // end namespace AssetProcessor
  279. #endif // PLATFORMCONFIGURATION_H