#pragma once #include "assets/assetPtr.h" #include "assets/assetManager.h" #include "module/moduleManager.h" #include "util/settings.h" #include "gui/controls/guiTreeViewCtrl.h" /// /// AssetImportConfig is a SimObject derived object intended to act as a container for all the necessary configuration data when running the Asset Importer. /// It dictates if and how any given asset type will be processed when running an import action. This is because the Asset Importer utilizes a lot of informed logic /// to try and automate as much of the import process as possible. In theory, you would run the import on a given file, and based on your config the importer will do /// everything from importing the designated file, as well as finding and importing any associated files such as images or materials, and prepping the objects at time /// of import to avoid as much manual post-processing as possible. /// class AssetImportConfig : public SimObject { typedef SimObject Parent; //General Settings public: /// /// Duplicate Asset Auto-Resolution Action. Options are None, AutoPrune, AutoRename /// String DuplicateAutoResolution; /// /// Indicates if warnings should be treated as errors. /// bool WarningsAsErrors; /// /// Indicates if importing should be prevented from completing if any errors are detected at all /// bool PreventImportWithErrors; /// /// Should the importer automatically prompt to find missing files if they are not detected automatically by the importer /// bool AutomaticallyPromptMissingFiles; // /// /// Should the importer add the folder name as a prefix to the assetName. Helps prevent name collisions. /// bool AddDirectoryPrefixToAssetName; // // //Mesh Settings /// /// Indicates if this config supports importing meshes /// bool ImportMesh; /// /// When importing a shape, this indicates if it should automatically add a standard suffix onto the name /// bool AlwaysAddShapeSuffix; /// /// If AlwaysAddShapeSuffix is on, this is the suffix to be added /// String AddedShapeSuffix; /// /// Indicates if this config should override the per-format sis files with the config's specific settings /// bool UseManualShapeConfigRules; /// /// Indicates if the up axis in the model file should be overridden /// bool DoUpAxisOverride; /// /// If overriding, what axis should be used as up. Options are X_AXIS, Y_AXIS, Z_AXIS /// String UpAxisOverride; /// /// Indicates if the scale in the model file should be overridden /// bool DoScaleOverride; /// /// If overriding, what scale should be used /// F32 ScaleOverride; /// /// Indicates if scale of nodes should be ignored /// bool IgnoreNodeScale; /// /// Indicates if the center of the model file should be automatically recentered /// bool AdjustCenter; /// /// Indicates if the floor height of the model file should be automatically zero'd /// bool AdjustFloor; /// /// Indicates if submeshes should be collapsed down into a single main mesh /// bool CollapseSubmeshes; /// /// Indicates what LOD mode the model file should utilize to process out LODs. Options are TrailingNumber, DetectDTS, SingleSize /// String LODType; //ImportAssetConfigSettingsList.addNewConfigSetting("TrailingNumber", "Trailing Number", "float", "", "2", "", "Mesh"); /// /// A list of what nodes should be guaranteed to be imported if found in the model file. Separated by either , or ; /// String AlwaysImportedNodes; /// /// what lod value to use if all submeshes are set to the same detail level /// S32 singleDetailSize; /// /// A list of what nodes should be guaranteed to not be imported if found in the model file. Separated by either , or ; /// String AlwaysIgnoreNodes; /// /// A list of what mesh objects should be guaranteed to be imported if found in the model file. Separated by either , or ; /// String AlwaysImportMeshes; /// /// A list of what mesh objects should be guaranteed to not be imported if found in the model file. Separated by either , or ; /// String AlwaysIgnoreMeshes; //Assimp/Collada params /// /// Flag to indicate the shape loader should convert to a left-handed coordinate system /// bool convertLeftHanded; /// /// Should the shape loader calculate tangent space values /// bool calcTangentSpace; /// /// Should the shape loader automatically prune redundant/duplicate materials /// bool removeRedundantMats; /// /// Should the shape loader auto-generate UV Coordinates for the mesh. /// bool genUVCoords; /// /// Should the UV coordinates be transformed. /// bool TransformUVs; /// /// Should the UV coordinates be flipped /// bool flipUVCoords; /// /// Should the shape loader automatically look for instanced submeshes in the model file /// bool findInstances; /// /// Should the shape loader limit the bone weights /// bool limitBoneWeights; /// /// Should the shape loader automatically merge identical/duplicate verts /// bool JoinIdenticalVerts; /// /// Should the shape loader reverse the winding order of the mesh's face indicies /// bool reverseWindingOrder; /// /// Should the normals on the model be inverted /// bool invertNormals; // // //Materials /// /// Does this config allow for importing of materials /// bool ImportMaterials; /// /// When importing a material, should it automatically attempt to merge Roughness, AO and Metalness maps into a single, composited PBR Configuration map /// bool CreateORMConfig; /// /// When creating a material on import, this indicates if it should automatically add a standard suffix onto the name /// bool AlwaysAddMaterialSuffix; /// /// If AlwaysAddMaterialSuffix is on, this is the suffix to be added /// String AddedMaterialSuffix; /// /// When generating a material off of an importing image, should the importer force appending a diffusemap suffix onto the end to avoid potential naming confusion. /// e.g. MyCoolStuff.png is imported, generating MyCoolStuff material asset and MyCoolStuff_Diffuse image asset /// bool UseDiffuseSuffixOnOriginImage; /// /// Should the importer try and use existing material assets in the game directory if at all possible. (Not currently utilized) /// bool UseExistingMaterials; /// /// A list of material names that should not be imported. Separated by either , or ; /// String IgnoreMaterials; /// /// When processing a material asset, should the importer attempt to populate the various material maps on it by looking up common naming conventions for potentially relevent image files /// e.g. If MyCoolStuff_Diffuse.png is imported, generating MyCoolStuff material, it would also find MyCoolStuff_Normal and MyCoolStuff_PBR images and map them to the normal and ORMConfig maps respectively automatically /// bool PopulateMaterialMaps; // //Animations /// /// Does this config allow for importing Shape Animations /// bool ImportAnimations; /// /// When importing a shape file, should the animations within be separated out into unique files /// bool SeparateAnimations; /// /// If separating animations out from a source file, what prefix should be added to the names for grouping association /// String SeparateAnimationPrefix; /// /// Defines the animation timing for the given animation sequence. Options are FrameTime, Seconds, Milliseconds /// String animTiming; /// /// The FPS of the animation sequence /// F32 animFPS; /// /// When importing a shape animation, this indicates if it should automatically add a standard suffix onto the name /// bool AlwaysAddShapeAnimationSuffix; /// /// If AlwaysAddShapeAnimationSuffix is on, this is the suffix to be added /// String AddedShapeAnimationSuffix; // //Collision /// /// Does this configuration generate collision geometry when importing. (Not currently enabled) /// bool GenerateCollisions; /// /// What sort of collision geometry is generated. (Not currently enabled) /// String GenCollisionType; /// /// What prefix is added to the collision geometry generated. (Not currently enabled) /// String CollisionMeshPrefix; /// /// Does this configuration generate Line of Sight collision geometry. (Not currently enabled) /// bool GenerateLOSCollisions; /// /// What sort of Line of Sight collision geometry is generated. (Not currently enabled) /// String GenLOSCollisionType; /// /// What prefix is added to the Line of Sight collision geometry generated. (Not currently enabled) /// String LOSCollisionMeshPrefix; // //Images /// /// Does this configuration support importing images. /// bool importImages; /// /// When importing an image, this indicates if it should automatically add a standard suffix onto the name /// bool AlwaysAddImageSuffix; /// /// If AlwaysAddImageSuffix is on, this is the suffix to be added /// String AddedImageSuffix; /// /// What is the default ImageType images are imported as. Options are: N/A, Diffuse, Normal, Metalness, Roughness, AO, ORMConfig, GUI, Cubemap /// String ImageType; /// /// What type of suffixes are scanned to detect if an importing image is a diffuse map. /// e.g. _Albedo or _Color /// String DiffuseTypeSuffixes; /// /// What type of suffixes are scanned to detect if an importing image is a normal map. /// e.g. _Normal or _Norm /// String NormalTypeSuffixes; /// /// What type of suffixes are scanned to detect if an importing image is a metalness map. /// e.g. _Metalness or _Metal /// String MetalnessTypeSuffixes; /// /// What type of suffixes are scanned to detect if an importing image is a roughness map. /// e.g. _roughness or _rough /// String RoughnessTypeSuffixes; /// /// What type of suffixes are scanned to detect if an importing image is a smoothness map. /// e.g. _smoothness or _smooth /// String SmoothnessTypeSuffixes; /// /// What type of suffixes are scanned to detect if an importing image is a ambient occlusion map. /// e.g. _ambient or _ao /// String AOTypeSuffixes; /// /// What type of suffixes are scanned to detect if an importing image is a ORMConfig map. /// e.g. _Composite or _PBR /// String PBRTypeSuffixes; /// /// Indicates what filter mode images imported with this configuration utilizes. Options are Linear, Bilinear, Trilinear /// String TextureFilteringMode; /// /// Indicates if images imported with this configuration utilize mipmaps /// bool UseMips; /// /// Indicates if images imported with this configuration are in an HDR format /// bool IsHDR; /// /// Indicates what amount of scaling images imported with this configuration use /// F32 Scaling; /// /// Indicates if images imported with this configuration are compressed /// bool ImagesCompressed; /// /// Indicates if images imported with this configuration generate a parent material for it as well /// bool GenerateMaterialOnImport; // //Sounds /// /// Indicates if sounds are imported with this configuration /// bool importSounds; /// /// Indicates what amount the volume is adjusted on sounds imported with this configuration /// F32 VolumeAdjust; /// /// Indicates what amount the pitch is adjusted on sounds imported with this configuration /// F32 PitchAdjust; /// /// Indicates if sounds imported with this configuration are compressed /// bool SoundsCompressed; /// When importing an image, this indicates if it should automatically add a standard suffix onto the name /// bool AlwaysAddSoundSuffix; /// /// If AlwaysAddSoundSuffix is on, this is the suffix to be added /// String AddedSoundSuffix; public: AssetImportConfig(); virtual ~AssetImportConfig(); bool onAdd() override; void onRemove() override; /// Engine. static void initPersistFields(); /// /// Loads a configuration from a Settings object /// @param configSettings, The Settings object to load from /// @param configName, The name of the configuration setting to load from the setting object /// void loadImportConfig(Settings* configSettings, String configName); void CopyTo(AssetImportConfig* target) const; /// Declare Console Object. DECLARE_CONOBJECT(AssetImportConfig); void loadSISFile(Torque::Path filePath); }; /// /// AssetImportConfig is a SimObject derived object that represents and holds information for an importing asset. They are generated and processed by the AssetImporter /// class AssetImportObject : public SimObject { typedef SimObject Parent; public: /// /// What type is the importing asset /// String assetType; /// /// What is the source file path of the importing asset /// Torque::Path filePath; /// /// What is the source file path of the importing asset in string form /// StringTableEntry filePathString; /// /// What is the asset's name /// String assetName; /// /// What is the original, unmodified by processing, asset name /// String cleanAssetName; /// /// What is the name of the module this asset will be importing into /// String moduleName; /// /// What is the current status of this asset item in it's import process /// String status; /// /// If there is a warning or error status, what type is the condition for this asset item /// String statusType; /// /// What is the articulated information of the status of the asset. Contains the error or warning log data. /// String statusInfo; /// /// Is the asset item currently flagged as dirty /// bool dirty; enum { NotProcessed=0, Processed, Skipped, UseForDependencies, Error, Imported }; /// /// Is this asset item marked to be skipped. If it is, it's usually due to being marked as deleted /// U32 importStatus; /// /// Is this specific asset item generated as part of the import process of another item /// bool generatedAsset; /// /// What, if any, importing asset item is this item's parent /// AssetImportObject* parentAssetItem; /// /// What, if any, importing asset item are children of this item /// Vector< AssetImportObject*> childAssetItems; /// /// What is the ultimate asset taml file path for this import item /// String tamlFilePath; // /// /// Specific to ImageAsset type /// What is the image asset's suffix type. Options are: Albedo, Normal, Roughness, AO, Metalness, ORMConfig /// String imageSuffixType; // /// /// Specific to ShapeAsset type /// Processed information about the shape file. Contains numbers and lists of meshes, materials and animations /// GuiTreeViewCtrl* shapeInfo; // /// /// A string that can hold a hint string to help the auto-import ensure the correct asset subtype is assigned. /// e.g. "GUI" would inform an image asset being imported that it should be flagged as a GUI image type /// String typeHint; public: AssetImportObject(); virtual ~AssetImportObject(); bool onAdd() override; void onRemove() override; /// Engine. static void initPersistFields(); /// Declare Console Object. DECLARE_CONOBJECT(AssetImportObject); static bool _setFilePath(void* obj, const char* index, const char* data); void setFilePath(StringTableEntry pFilePath); bool operator == (const AssetImportObject& o) const { return o.getId() == this->getId(); } bool canImport() { return (importStatus == AssetImportObject::Processed); } }; /// /// AssetImporter is a SimObject derived object that processed and imports files and turns them into assets if they are of valid types. /// Utilizes an AssetImportConfig to inform the importing process's behavior. /// class AssetImporter : public SimObject { typedef SimObject Parent; /// /// The import configuration that is currently being utilized /// AssetImportConfig* activeImportConfig; /// /// A log of all the actions that have been performed by the importer /// Vector activityLog; /// /// A list of AssetImportObjects that are to be imported /// Vector importingAssets; /// /// A list of file paths that are to be imported. These are only used for resetting purposes; /// Vector originalImportingFiles; /// /// The Id of the module the assets are to be imported into /// String targetModuleId; /// /// The path any imported assets are placed in as their destination /// String targetPath; /// /// Are there any issues with any of the current import asset items /// bool importIssues; /// /// Is this import action a reimport of an existing asset /// bool isReimport; /// /// Has the heirarchy of asset import items changed due to processing /// bool assetHeirarchyChanged; /// /// A string used for writing into the importLog /// char importLogBuffer[1024]; /// /// only used for passing up the result of an import action for a script-side handled type /// String finalImportedAssetPath; bool mDumpLogs; public: AssetImporter(); virtual ~AssetImporter(); bool onAdd() override; void onRemove() override; /// Engine. static void initPersistFields(); /// Declare Console Object. DECLARE_CONOBJECT(AssetImporter); /// /// Sets the target path for the assets being imported to be deposited into /// @param pTargetPath, The filePath of the destination point assets are imported into /// void setTargetPath(Torque::Path pTargetPath) { targetPath = pTargetPath; } /// /// Processes a file into an AssetImportObject and adds it to the session for importing /// @param filePath, The filePath of the file to be imported in as an asset /// @return AssetImportObject that was created /// AssetImportObject* addImportingFile(Torque::Path filePath); /// /// Adds an existing AssetImportObject to our import session. Generally this would be created in a script somewhere /// @param assetItem, The asset item to be added to the import session /// @param parentItem (Optional), The asset item that will be the parent of the assetItem being added /// void addImportingAssetItem(AssetImportObject* assetItem, AssetImportObject* parentItem); /// /// Adds an importing asset to the current session /// @param assetType, Type of the asset being imported /// @param filePath, path of the file to be imported /// @param parentItem, AssetImportObject that the new item is a child of. null if no parent /// @param assetNameOverride, If not blank, will be the new item's assetName instead of being created off of the filePath /// @return AssetImportObject that was created /// AssetImportObject* addImportingAsset(String assetType, Torque::Path filePath, AssetImportObject* parentItem, String assetNameOverride); /// /// Deletes the asset item from the import session. Affects the item's children as well /// @param assetItem, asset item to be marked as deleted /// void deleteImportingAsset(AssetImportObject* assetItem); /// /// Finds an asset item in the session if it exists, by name /// @param assetName, Asset name to find /// @param assetItem, if null, will loop over and recurse the main import asset items, if a specific AssetImportObject is passed in, it will recurse it's children /// @return AssetImportObject that was found /// AssetImportObject* findImportingAssetByName(String assetName, AssetImportObject* assetItem = nullptr); /// /// Finds the module associated with a given file path /// @param filePath, File path to parse the the module from /// @return ModuleDefinition that was found /// static ModuleDefinition* getModuleFromPath(Torque::Path filePath); /// /// Parses an asset's name to try and find if any of the import config's suffix lists match to it /// @param assetName, Asset name to parse any image suffix out of /// @param suffixType, output, The suffix type that was matched to the asset name /// @return suffix that matched to the asset name /// String parseImageSuffixes(String assetName, String* suffixType); /// /// Parses a file path to determine its asset type /// @param filePath, File path to parse /// @return The asset type as a string /// String getAssetTypeByFile(Torque::Path filePath); /// /// Resets the import session to a clean slate. This will clear all existing AssetImportObjects and the activity log /// and then re-process the original filePaths again. /// @param hardClearSession, Defaults to false. If true, will also clear the original filePaths /// void resetImportSession(bool hardClearSession = false); /// /// Get the number of lines in the activity log /// @return Line count as S32 /// S32 getActivityLogLineCount(); /// /// Gets the log line at a given index /// @param line, line in the log to get /// @return The log line as a string /// String getActivityLogLine(U32 line); /// /// Dumps the entire current activity log to the console. /// void dumpActivityLog(); /// /// Gets the number of top-level asset items in the current import session(doesn't count children) /// @return Number of children /// S32 getAssetItemCount(); /// /// Get the top-level asset item in the current import session at the requested index /// @param index, The index of the item array to get /// @return The AssetImportObject at the index /// AssetImportObject* getAssetItem(U32 index); /// /// Gets the number of child asset items of a given AssetImportObject /// @param assetItem, The AssetImportObject to get the number of child items for /// @return Number of children /// S32 getAssetItemChildCount(AssetImportObject* assetItem); /// /// Get the child asset item of a specific AssetImportObject at the requested index /// @param assetItem, The AssetImportObject to get the number of child items for /// @param index, The index of the child item array to get /// @return The AssetImportObject at the index /// AssetImportObject* getAssetItemChild(AssetImportObject* assetItem, U32 index); /// /// Process AssetImportObject's to prepare them for importing. /// @param assetItem, If null, will loop over the top-level asset items list, if a specific item is provided, will process it's children /// void processImportAssets(AssetImportObject* assetItem = nullptr); /// /// Process a specific AssetImportObject that is an ImageAsset type to prepare it for importing /// @param assetItem, The AssetImportObject to process /// void processImageAsset(AssetImportObject* assetItem); /// /// Process a specific AssetImportObject that is an MaterialAsset type to prepare it for importing /// @param assetItem, The AssetImportObject to process /// void processMaterialAsset(AssetImportObject* assetItem); /// /// Process a specific AssetImportObject that is an ShapeAnimationAsset type to prepare it for importing /// @param assetItem, The AssetImportObject to process /// void processShapeAsset(AssetImportObject* assetItem); /// /// Process a specific AssetImportObject that is an ShapeAsset type to prepare it for importing /// @param assetItem, The AssetImportObject to process /// void processShapeAnimationAsset(AssetImportObject* assetItem); /// /// Process a specific ShapeAsset AssetImportObject with a material id in order to parse and handle the materials listed in the shape file /// @param assetItem, The AssetImportObject to process /// @param materialItemId, The materialItemId in the shapeInfo to process /// void processShapeMaterialInfo(AssetImportObject* assetItem, S32 materialItemId); /// /// Process a specific AssetImportObject that is an SoundAsset type to prepare it for importing /// @param assetItem, The AssetImportObject to process /// void processSoundAsset(AssetImportObject* assetItem); /// /// Run through and validate assets for issues, such as name collisions /// bool validateAssets(); /// /// Validate a specific asset item /// @param assetItem, The AssetImportObject to validate /// void validateAsset(AssetImportObject* assetItem); /// /// Reset the validation status of asset items /// @param assetItem, If null, will loop over the top-level asset items list, if a specific item is provided, will reset it's children /// void resetAssetValidationStatus(AssetImportObject* assetItem = nullptr); /// /// Checks asset items for any collisions in the current import session /// @param assetItemToCheckFor, The asset to check for collisions with /// @param assetItem, if null, will loop over and recurse the main import asset items, if a specific AssetImportObject is passed in, it will recurse it's children /// @return If a collision was detected /// bool checkAssetForCollision(AssetImportObject* assetItemToCheckFor, AssetImportObject* assetItem = nullptr); /// /// Attempts to automatically resolve import issues according to the import config settings /// @param assetItem, The AssetImportObject to resolve /// void resolveAssetItemIssues(AssetImportObject* assetItem); /// /// Runs the import process on a single file in-place. Intended primarily for autoimporting a loose file that's in the game directory. /// @param filePath, The filePath of the file to be imported in as an asset /// @param typeHint, Optional. A string that provides a hint of the intended asset type. Such as an image being intended for GUI use. /// @return AssetId of the asset that was imported. If import failed, it will be empty. /// StringTableEntry autoImportFile(Torque::Path filePath, String typeHint); /// /// Runs the import process in the current session /// @param assetItem, if null, will loop over and recurse the main import asset items, if a specific AssetImportObject is passed in, it will recurse it's children /// void importAssets(AssetImportObject* assetItem = nullptr); /// /// Runs the import processing on a specific ImageAsset item /// @param assetItem, The asset item to import /// @return TAML File path of the new asset that was imported. If import failed, it will be empty. /// Torque::Path importImageAsset(AssetImportObject* assetItem); /// /// Runs the import processing on a specific MaterialAsset item /// @param assetItem, The asset item to import /// @return TAML File path of the new asset that was imported. If import failed, it will be empty. /// Torque::Path importMaterialAsset(AssetImportObject* assetItem); /// /// Runs the import processing on a specific ShapeAsset item /// @param assetItem, The asset item to import /// @return TAML File path of the new asset that was imported. If import failed, it will be empty. /// Torque::Path importShapeAsset(AssetImportObject* assetItem); /// /// Runs the import processing on a specific SoundAsset item /// @param assetItem, The asset item to import /// @return TAML File path of the new asset that was imported. If import failed, it will be empty. /// Torque::Path importSoundAsset(AssetImportObject* assetItem); /// /// Runs the import processing on a specific ShapeAnimationAsset item /// @param assetItem, The asset item to import /// @return TAML File path of the new asset that was imported. If import failed, it will be empty. /// Torque::Path importShapeAnimationAsset(AssetImportObject* assetItem); /// /// Iterates over all the items in the current session and acquires them, which jumpstarts the loading/init'ng process on them, making the available for use immediately /// @param assetItem, if null, will loop over and recurse the main import asset items, if a specific AssetImportObject is passed in, it will recurse it's children /// void acquireAssets(AssetImportObject* assetItem = nullptr); // /// /// Gets the currently active import configuration /// @return Current AssetImportConfig the importer is using /// AssetImportConfig* getImportConfig() { return activeImportConfig; } void setImportConfig(AssetImportConfig* importConfig) { if (importConfig != nullptr) { dSprintf(importLogBuffer, sizeof(importLogBuffer), "Loading import config: %s!", importConfig->getName()); activityLog.push_back(importLogBuffer); activeImportConfig = importConfig; } } /// /// Resets the active import config to whatever the default is. Either a clean slate if one isn't defined /// or loading one if defined via the editor config /// void resetImportConfig(); // static String getTrueFilename(const String& fileName); // /// /// static inline String findImagePath(const String &testPath) { String imagePath; if (Platform::isFile(testPath + String(".jpg"))) imagePath = testPath + String(".jpg"); else if (Platform::isFile(testPath + String(".png"))) imagePath = testPath + String(".png"); else if (Platform::isFile(testPath + String(".dds"))) imagePath = testPath + String(".dds"); else if (Platform::isFile(testPath + String(".tif"))) imagePath = testPath + String(".tif"); if(imagePath.isNotEmpty()) //This ensures case-correct for the filename imagePath = getTrueFilename(imagePath); return imagePath; } // void setTargetModuleId(const String& moduleId) { targetModuleId = moduleId; } const String& getTargetModuleId() { return targetModuleId; } String getFolderPrefixedName(AssetImportObject* assetItem) { String renamedAssetName = assetItem->assetName; S32 dirIndex = assetItem->filePath.getDirectoryCount() - 1; while (dirIndex > -1) { renamedAssetName = assetItem->assetName; String owningFolder = assetItem->filePath.getDirectory(dirIndex); renamedAssetName = owningFolder + "_" + renamedAssetName; if (AssetDatabase.isDeclaredAsset(renamedAssetName)) { dirIndex--; continue; } break; } return renamedAssetName; } };