From 34f0f01cea74a1e4d170013ad2cc2c4bbed9db91 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sun, 8 Aug 2021 16:20:58 -0500 Subject: [PATCH] Adds console function to compare file modified times Adds console function to save a scaled image Improved logic of generating previews for shape, material and image assets to regen if original asset loose file was modified Added logic to generate scaled preview image for material and image assets to improve load times of AB --- Engine/source/T3D/assets/MaterialAsset.cpp | 7 ++ Engine/source/console/fileSystemFunctions.cpp | 21 +++++ Engine/source/gfx/bitmap/gBitmap.cpp | 52 +++++++++++ .../scripts/assetTypes/image.tscript | 52 +++++++++-- .../scripts/assetTypes/material.tscript | 90 +++++++++++++------ .../scripts/assetTypes/shape.tscript | 25 ++++-- 6 files changed, 206 insertions(+), 41 deletions(-) diff --git a/Engine/source/T3D/assets/MaterialAsset.cpp b/Engine/source/T3D/assets/MaterialAsset.cpp index 6e6abc813..94b1d48ea 100644 --- a/Engine/source/T3D/assets/MaterialAsset.cpp +++ b/Engine/source/T3D/assets/MaterialAsset.cpp @@ -346,6 +346,13 @@ DefineEngineStaticMethod(MaterialAsset, getAssetIdByMaterialName, const char*, ( { return MaterialAsset::getAssetIdByMaterialName(StringTable->insert(materialName)); } + +DefineEngineMethod(MaterialAsset, getScriptPath, const char*, (), , + "Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n" + "@return The AssetId of the associated asset, if any.") +{ + return object->getScriptPath(); +} #endif //----------------------------------------------------------------------------- diff --git a/Engine/source/console/fileSystemFunctions.cpp b/Engine/source/console/fileSystemFunctions.cpp index b67ae2c0c..eea26a984 100644 --- a/Engine/source/console/fileSystemFunctions.cpp +++ b/Engine/source/console/fileSystemFunctions.cpp @@ -580,6 +580,27 @@ DefineEngineFunction( fileCreatedTime, String, ( const char* fileName ),, return buffer; } +DefineEngineFunction(compareFileTimes, S32, (const char* fileA, const char* fileB), ("", ""), + "@brief Compares 2 files' modified file times." + + "@param fileName Name and path of first file to compare\n" + "@param fileName Name and path of second file to compare\n" + "@return S32. If value is 1, then fileA is newer. If value is -1, then fileB is newer. If value is 0, they are equal.\n" + "@ingroup FileSystem") +{ + Con::expandScriptFilename(sgScriptFilenameBuffer, sizeof(sgScriptFilenameBuffer), fileA); + + FileTime fileATime = { 0 }; + Platform::getFileTimes(sgScriptFilenameBuffer, NULL, &fileATime); + + Con::expandScriptFilename(sgScriptFilenameBuffer, sizeof(sgScriptFilenameBuffer), fileB); + + FileTime fileBTime = { 0 }; + Platform::getFileTimes(sgScriptFilenameBuffer, NULL, &fileBTime); + + return Platform::compareFileTimes(fileATime, fileBTime); +} + DefineEngineFunction(fileDelete, bool, ( const char* path ),, "@brief Delete a file from the hard drive\n\n" diff --git a/Engine/source/gfx/bitmap/gBitmap.cpp b/Engine/source/gfx/bitmap/gBitmap.cpp index a31e81faf..33c1c700c 100644 --- a/Engine/source/gfx/bitmap/gBitmap.cpp +++ b/Engine/source/gfx/bitmap/gBitmap.cpp @@ -1360,3 +1360,55 @@ DefineEngineFunction( getBitmapInfo, String, ( const char *filename ),, image->getBytesPerPixel(), image->getFormat()); } + +DefineEngineFunction(saveScaledImage, bool, (const char* bitmapSource, const char* bitmapDest, S32 resolutionSize), ("", "", 512), + "Returns image info in the following format: width TAB height TAB bytesPerPixel TAB format. " + "It will return an empty string if the file is not found.\n" + "@ingroup Rendering\n") +{ + Resource image = GBitmap::load(bitmapSource); + if (!image) + return false; + + Torque::Path sourcePath = Torque::Path(bitmapSource); + + /*if (String("dds").equal(sourcePath.getExtension(), String::NoCase)) + { + dds = DDSFile::load(correctPath, scalePower); + if (dds != NULL) + { + if (!dds->decompressToGBitmap(image)) + { + delete image; + image = NULL; + return false; + } + } + }*/ + + image->extrudeMipLevels(); + + U32 mipCount = image->getNumMipLevels(); + U32 targetMips = mFloor(mLog2((F32)resolutionSize)) + 1; + + if (mipCount > targetMips) + { + image->chopTopMips(mipCount - targetMips); + } + + // Open up the file on disk. + FileStream fs; + if (!fs.open(bitmapDest, Torque::FS::File::Write)) + { + Con::errorf("saveScaledImage() - Failed to open output file '%s'!", bitmapDest); + return false; + } + else + { + image->writeBitmap("png", fs); + + fs.close(); + } + + return true; +} diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript index a2f6291c2..b306c9300 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript @@ -172,15 +172,55 @@ function AssetBrowser::importImageAsset(%this, %assetItem) function AssetBrowser::buildImageAssetPreview(%this, %assetDef, %previewData) { + %module = %this.dirHandler.getModuleFromAddress(makeRelativePath(filePath(%assetDef.getImagePath()))); + %previewPath = "tools/resources/previewCache/" @ %module.moduleId @ "/"; + + if(!IsDirectory(%previewPath)) + { + %this.dirHandler.createFolder(%previewPath); + } + + %generatePreview = false; + + %previewFilePath = %previewPath @ %assetDef.assetName @ "_Preview.png"; + if(!isFile(%previewFilePath) || (compareFileTimes(%assetDef.getImagePath(), %previewFilePath) == 1)) + { + %generatePreview = true; + } + + %previewAssetName = %module.moduleId @ "_" @ %assetDef.assetName @ "_PreviewImage"; + + if(%generatePreview) + { + displayEditorLoadingGui("Generating Image Asset Preview..."); + + %success = saveScaledImage(%assetDef.getImagePath(), %previewFilePath); + + %previewAsset = new ImageAsset() + { + assetName = %previewAssetName; + versionId = 1; + imageFile = fileName(%previewFilePath); + }; + + %previewImgAssetPath = %previewPath @ %previewAsset.assetName @ ".asset.taml"; + %assetImportSuccessful = TAMLWrite(%previewAsset, %previewImgAssetPath); + + %toolsModuleDef = ModuleDatabase.findModule("ToolsModule",1); + + %success = AssetDatabase.addDeclaredAsset(%toolsModuleDef, %previewImgAssetPath); + + hideEditorLoadingGui(); + } + + //Revalidate. If it didn't work, just use the default placeholder one + if(!isFile(%previewFilePath)) + %previewAssetName = "ToolsModule:genericAssetIcon_image"; + %previewData.assetName = %assetDef.assetName; %previewData.assetPath = %assetDef.scriptFile; - //%previewData.doubleClickCommand = "EditorOpenFileInTorsion( "@%previewData.assetPath@", 0 );"; - %imageFilePath = %assetDef.getImagePath(); - if(isFile(%imageFilePath)) - %previewData.previewImage = %imageFilePath; - else - %previewData.previewImage = "core/rendering/images/unavailable"; + %previewData.previewImage = "ToolsModule:" @ %previewAssetName;//%assetDef.fileName; %previewData.assetFriendlyName = %assetDef.assetName; %previewData.assetDesc = %assetDef.description; diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript index ddcdb6214..229a4c14d 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript @@ -423,41 +423,77 @@ function AssetBrowser::importMaterialAsset(%this, %assetItem) function AssetBrowser::buildMaterialAssetPreview(%this, %assetDef, %previewData) { + %module = %this.dirHandler.getModuleFromAddress(makeRelativePath(filePath(%assetDef.getScriptPath()))); + %previewPath = "tools/resources/previewCache/" @ %module.moduleId @ "/"; + + if(!IsDirectory(%previewPath)) + { + %this.dirHandler.createFolder(%previewPath); + } + + %generatePreview = false; + + %previewFilePath = %previewPath @ %assetDef.assetName @ "_Preview.png"; + if(!isFile(%previewFilePath) || (compareFileTimes(%assetDef.getImagePath(), %previewFilePath) == 1)) + { + %generatePreview = true; + } + + %previewAssetName = %module.moduleId @ "_" @ %assetDef.assetName @ "_PreviewImage"; + + if(%generatePreview) + { + displayEditorLoadingGui("Generating Material Asset Preview..."); + + if(isObject(%assetDef.materialDefinitionName)) + { + if(isFile(%assetDef.materialDefinitionName.getDiffuseMap(0))) + { + %difMap = %assetDef.materialDefinitionName.getDiffuseMap(0); + } + else if(%assetDef.materialDefinitionName.getDiffuseMapAsset(0) !$= "") + { + %imgAsset = AssetDatabase.acquireAsset(%assetDef.materialDefinitionName.getDiffuseMapAsset(0)); + %difMap = %imgAsset.getImagePath(); + } + + //%success = saveScaledImage(%difMap, %previewFilePath); + + %previewAsset = new ImageAsset() + { + assetName = %previewAssetName; + versionId = 1; + imageFile = fileName(%previewFilePath); + }; + + %previewImgAssetPath = %previewPath @ %previewAsset.assetName @ ".asset.taml"; + %assetImportSuccessful = TAMLWrite(%previewAsset, %previewImgAssetPath); + + %toolsModuleDef = ModuleDatabase.findModule("ToolsModule",1); + + %success = AssetDatabase.addDeclaredAsset(%toolsModuleDef, %previewImgAssetPath); + } + + hideEditorLoadingGui(); + } + + //Revalidate. If it didn't work, just use the default placeholder one + if(!isFile(%previewFilePath)) + %previewAssetName = "ToolsModule:genericAssetIcon_image"; + %previewData.assetName = %assetDef.assetName; %previewData.assetPath = %assetDef.scriptFile; + + %previewData.previewImage = "ToolsModule:" @ %previewAssetName;//%assetDef.fileName; + + %previewData.assetFriendlyName = %assetDef.assetName; + %previewData.assetDesc = %assetDef.description; - //Lotta prepwork - /*%previewData.doubleClickCommand = %assetDef@".materialDefinitionName.reload(); " - @ "$Tools::materialEditorList = \"\";" - @ "EWorldEditor.clearSelection();" - @ "MaterialEditorGui.currentObject = 0;" - @ "MaterialEditorGui.currentMode = \"asset\";" - @ "MaterialEditorGui.currentMaterial = "@%assetDef@".materialDefinitionName;" - @ "MaterialEditorGui.setActiveMaterial( "@%assetDef@".materialDefinitionName );" - @ "EditorGui.setEditor(MaterialEditorPlugin); " - @ "AssetBrowser.hideDialog();";*/ - if(%this.selectMode) %previewData.doubleClickCommand = "AssetBrowser.selectAsset( AssetBrowser.selectedAsset );"; else %previewData.doubleClickCommand = "AssetBrowser.editAsset( "@%assetDef@" );"; - %previewData.previewImage = "ToolsModule:materialIcon_image"; - - if(isObject(%assetDef.materialDefinitionName)) - { - if(isFile(%assetDef.materialDefinitionName.getDiffuseMap(0))) - %previewData.previewImage = %assetDef.materialDefinitionName.getDiffuseMap(0); - else if(%assetDef.materialDefinitionName.getDiffuseMapAsset(0) !$= "") - { - %imgAsset = AssetDatabase.acquireAsset(%assetDef.materialDefinitionName.getDiffuseMapAsset(0)); - %previewData.previewImage = %imgAsset.getImagePath(); - } - //add cubemap preview here(for skybox materials) - } - - %previewData.assetFriendlyName = %assetDef.assetName; - %previewData.assetDesc = %assetDef.description; %previewData.tooltip = "Asset Name: " @ %assetDef.assetName @ "\n" @ "Asset Type: Material Asset\n" @ "Asset Definition ID: " @ %assetDef; diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript index 947115312..e4687faf1 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript @@ -245,15 +245,24 @@ function AssetBrowser::importShapeAsset(%this, %assetItem) function AssetBrowser::buildShapeAssetPreview(%this, %assetDef, %previewData) { %module = %this.dirHandler.getModuleFromAddress(makeRelativePath(filePath(%assetDef.getShapeFile()))); - %previewPath = "tools/resources/shapePreviewCache/" @ %module.moduleId @ "/"; + %previewPath = "tools/resources/previewCache/" @ %module.moduleId @ "/"; if(!IsDirectory(%previewPath)) { %this.dirHandler.createFolder(%previewPath); } + %generatePreview = false; + %previewFilePath = %previewPath @ %assetDef.assetName @ "_Preview.png"; - if(!isFile(%previewFilePath)) + if(!isFile(%previewFilePath) || (compareFileTimes(%assetDef.getShapeFile(), %previewFilePath) == 1)) + { + %generatePreview = true; + } + + %previewAssetName = %module.moduleId @ "_" @ %assetDef.assetName @ "_PreviewImage"; + + if(%generatePreview) { displayEditorLoadingGui("Generating Shape Asset Preview..."); @@ -275,15 +284,15 @@ function AssetBrowser::buildShapeAssetPreview(%this, %assetDef, %previewData) $TSLastDetail::dumpImposters = %oldImposterSetting; - %newAsset = new ImageAsset() + %previewAsset = new ImageAsset() { - assetName = %assetDef.assetName @ "_PreviewImage"; + assetName = %previewAssetName; versionId = 1; imageFile = fileName(%previewFilePath); }; - %previewImgAssetPath = %previewPath @ %newAsset.assetName @ ".asset.taml"; - %assetImportSuccessful = TAMLWrite(%newAsset, %previewImgAssetPath); + %previewImgAssetPath = %previewPath @ %previewAsset.assetName @ ".asset.taml"; + %assetImportSuccessful = TAMLWrite(%previewAsset, %previewImgAssetPath); %toolsModuleDef = ModuleDatabase.findModule("ToolsModule",1); @@ -294,12 +303,12 @@ function AssetBrowser::buildShapeAssetPreview(%this, %assetDef, %previewData) //Revalidate. If it didn't work, just use the default placeholder one if(!isFile(%previewFilePath)) - %previewFilePath = "ToolsModule:genericAssetIcon_image"; + %previewAssetName = "ToolsModule:genericAssetIcon_image"; %previewData.assetName = %assetDef.assetName; %previewData.assetPath = %assetDef.fileName; - %previewData.previewImage = "ToolsModule:" @ %assetDef.assetName @ "_PreviewImage";//%assetDef.fileName; + %previewData.previewImage = "ToolsModule:" @ %previewAssetName;//%assetDef.fileName; %previewData.assetFriendlyName = %assetDef.assetName; %previewData.assetDesc = %assetDef.description;