From 50f74368b330007484292470ce1b164482da2db1 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 15 Jun 2025 22:07:12 +0100 Subject: [PATCH 01/13] various fixes around preview assets and imageassets text field Imageasset text field now displays correctly in inspector previews now use assets again assetBrowser hides previewCache folder --- Engine/source/T3D/assets/ImageAsset.h | 32 +++++++++++------ Engine/source/console/console.cpp | 17 +++++++++ .../assetBrowser/scripts/assetBrowser.tscript | 4 +-- .../scripts/assetTypes/image.tscript | 32 ++++++++++++++--- .../scripts/assetTypes/material.tscript | 35 ++++++++++++++---- .../scripts/assetTypes/shape.tscript | 36 ++++++++++++------- 6 files changed, 121 insertions(+), 35 deletions(-) diff --git a/Engine/source/T3D/assets/ImageAsset.h b/Engine/source/T3D/assets/ImageAsset.h index 082ddb04f..c60523b81 100644 --- a/Engine/source/T3D/assets/ImageAsset.h +++ b/Engine/source/T3D/assets/ImageAsset.h @@ -233,10 +233,10 @@ DefineEnumType(ImageAssetType); #pragma region Refactor Asset Macros -#define DECLARE_IMAGEASSET(className, name, profile) \ +#define DECLARE_IMAGEASSET(className, name, profile) \ private: \ - AssetPtr m##name##Asset;\ - String m##name##File;\ + AssetPtr m##name##Asset; \ + StringTableEntry m##name##File = StringTable->EmptyString(); \ public: \ void _set##name(StringTableEntry _in){ \ if(m##name##Asset.getAssetId() == _in) \ @@ -244,6 +244,7 @@ public: if(_in == NULL || _in == StringTable->EmptyString()) \ { \ m##name##Asset = NULL; \ + m##name##File = ""; \ return; \ } \ if(!AssetDatabase.isDeclaredAsset(_in)) \ @@ -271,10 +272,12 @@ public: imageAssetId = ImageAsset::smNoImageAssetFallback; \ } \ m##name##Asset = imageAssetId; \ + m##name##File = _in; \ } \ else \ { \ m##name##Asset = _in; \ + m##name##File = get##name##File(); \ } \ }; \ \ @@ -285,10 +288,10 @@ public: StringTableEntry get##name##File(){ return m##name##Asset.notNull() ? m##name##Asset->getImageFile() : ""; } -#define DECLARE_IMAGEASSET_NET(className, name, profile, mask) \ +#define DECLARE_IMAGEASSET_NET(className, name, profile, mask) \ private: \ AssetPtr m##name##Asset; \ - String m##name##File;\ + StringTableEntry m##name##File = StringTable->EmptyString(); \ public: \ void _set##name(StringTableEntry _in){ \ if(m##name##Asset.getAssetId() == _in) \ @@ -296,6 +299,7 @@ public: if(_in == NULL || _in == StringTable->EmptyString()) \ { \ m##name##Asset = NULL; \ + m##name##File = ""; \ setMaskBits(mask); \ return; \ } \ @@ -324,10 +328,12 @@ public: imageAssetId = ImageAsset::smNoImageAssetFallback; \ } \ m##name##Asset = imageAssetId; \ + m##name##File = _in; \ } \ else \ { \ m##name##Asset = _in; \ + m##name##File = get##name##File(); \ } \ setMaskBits(mask); \ }; \ @@ -339,15 +345,15 @@ public: StringTableEntry get##name##File(){ return m##name##Asset.notNull() ? m##name##Asset->getImageFile() : ""; } -#define INITPERSISTFIELD_IMAGEASSET(name, consoleClass, docs) \ +#define INITPERSISTFIELD_IMAGEASSET(name, consoleClass, docs) \ addProtectedField(assetText(name, Asset), TypeImageAssetPtr, Offset(m##name##Asset, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, asset docs.)); \ addProtectedField(assetText(name, File), TypeFilename, Offset(m##name##File, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, file docs.)); -#define DECLARE_IMAGEASSET_ARRAY(className, name, profile, max) \ +#define DECLARE_IMAGEASSET_ARRAY(className, name, profile, max) \ private: \ AssetPtr m##name##Asset[max]; \ - String m##name##File[max];\ + StringTableEntry m##name##File[max] = {StringTable->EmptyString() }; \ public: \ void _set##name(StringTableEntry _in, const U32& index){ \ if(m##name##Asset[index].getAssetId() == _in) \ @@ -355,6 +361,7 @@ public: if(_in == NULL || _in == StringTable->EmptyString()) \ { \ m##name##Asset[index] = NULL; \ + m##name##File[index] = ""; \ return; \ } \ if(!AssetDatabase.isDeclaredAsset(_in)) \ @@ -382,10 +389,12 @@ public: imageAssetId = ImageAsset::smNoImageAssetFallback; \ } \ m##name##Asset[index] = imageAssetId; \ + m##name##File[index] = _in; \ } \ else \ { \ m##name##Asset[index] = _in; \ + m##name##File[index] = get##name##File(index); \ } \ }; \ \ @@ -397,10 +406,10 @@ public: StringTableEntry get##name##File(const U32& idx){ return m##name##Asset[idx].notNull() ? m##name##Asset[idx]->getImageFile() : ""; } -#define DECLARE_IMAGEASSET_ARRAY_NET(className, name, profile, max, mask) \ +#define DECLARE_IMAGEASSET_ARRAY_NET(className, name, profile, max, mask) \ private: \ AssetPtr m##name##Asset[max]; \ - String m##name##File[max];\ + StringTableEntry m##name##File[max] = {StringTable->EmptyString() }; \ public: \ void _set##name(StringTableEntry _in, const U32& index){ \ if(m##name##Asset[index].getAssetId() == _in) \ @@ -408,6 +417,7 @@ public: if(_in == NULL || _in == StringTable->EmptyString()) \ { \ m##name##Asset[index] = NULL; \ + m##name##File[index] = ""; \ setMaskBits(mask); \ return; \ } \ @@ -436,10 +446,12 @@ public: imageAssetId = ImageAsset::smNoImageAssetFallback; \ } \ m##name##Asset[index] = imageAssetId; \ + m##name##File[index] = _in; \ } \ else \ { \ m##name##Asset[index] = _in; \ + m##name##File[index] = get##name##File(index); \ } \ setMaskBits(mask); \ }; \ diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index eb967f35e..4b9316e6f 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -2226,6 +2226,23 @@ bool stripRepeatSlashes(char* pDstPath, const char* pSrcPath, S32 dstSize) //----------------------------------------------------------------------------- +DefineEngineFunction(expandPath, const char*, (const char* path),, "(string path) - Expands an expando or relative path into a full path.") +{ + char* ret = Con::getReturnBuffer(1024); + Con::expandPath(ret, 1024, path); + return ret; +} + +//----------------------------------------------------------------------------- + +DefineEngineFunction(collapsePath, const char*, (const char* path), , "(string path) - Collapses a path into either an expando path or a relative path.") +{ + char* ret = Con::getReturnBuffer(1024); + Con::collapsePath(ret, 1024, path); + return ret; +} + + DefineEngineFunction( log, void, ( const char* message ),, "@brief Logs a message to the console.\n\n" "@param message The message text.\n" diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript index d53e8a4cb..04b12ab3d 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript @@ -258,7 +258,7 @@ function AssetBrowser::initialize(%this) if(!isObject(%this.dirHandler)) { - %this.dirHandler = makedirectoryHandler(%this-->filterTree, "cache,shaderCache", ""); + %this.dirHandler = makedirectoryHandler(%this-->filterTree, "cache,shaderCache,previewCache", ""); %this.dirHandler.currentAddress = "data/"; } @@ -1613,7 +1613,7 @@ function AssetBrowser::doRebuildAssetArray(%this) else { //got it. - if(%folderName $= "shaderCache" || %folderName $= "cache" || %folderName $= ".git") + if(%folderName $= "shaderCache" || %folderName $= "cache" || %folderName $= ".git" || %folderName $= "previewCache") continue; if(!%this.coreModulesFilter && %folderName $= "core" && %breadcrumbPath $= "") diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript index f571f2aa6..1aa34f78c 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript @@ -42,29 +42,53 @@ function ImageAsset::generatePreviewImage(%this, %previewButton, %forceRegenerat if(%forceRegenerate $= "") %forceRegenerate = false; - %previewPath = "tools/resources/previewCache/" @ %previewButton.moduleName @ "/"; + %previewPath = "tools/resources/previewCache/" @ %previewButton.moduleName @ "/"; if(!IsDirectory(%previewPath)) { $CurrentAssetBrowser.dirHandler.createFolder(%previewPath); } - %previewFilePath = %previewPath @ %this.assetName @ ".png"; + %previewFilePath = %previewPath @ %this.assetName @ "_Preview.png"; if(!isFile(%previewFilePath) || (compareFileTimes(%this.getImagePath(), %previewFilePath) == 1)) { %generatePreview = true; } + %previewAssetName = "ToolsModule:" @ %this.assetName @ "_Preview"; + if(%generatePreview || %forceRegenerate) { %success = saveScaledImage(%this.getImagePath(), %previewFilePath, EditorSettings.value("Assets/Browser/PreviewImageSize")); if(%success) - %previewButton.setBitmap(%previewFilePath); - + { + + if(!AssetDatabase.isDeclaredAsset(%previewAssetName)) + { + %preview_Asset = new ImageAsset() + { + assetName = %this.assetName @ "_Preview"; + versionId = 1; + imageFile = makeFullPath(%previewFilePath); + }; + + TamlWrite(%preview_Asset, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); + %toolsModuleDef = ModuleDatabase.findModule("ToolsModule",1); + AssetDatabase.addDeclaredAsset(%toolsModuleDef, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); + } + + %previewButton.bitmapAsset = %previewAssetName; + } + return %success; } + else + { + %previewButton.bitmapAsset = %previewAssetName; + return true; + } return false; } diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript index bd88e1274..33456e96a 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript @@ -101,8 +101,7 @@ function MaterialAsset::generatePreviewImage(%this, %previewButton, %forceRegene if(%forceRegenerate $= "") %forceRegenerate = false; - %module = $CurrentAssetBrowser.dirHandler.getModuleFromAddress(makeRelativePath(filePath(AssetDatabase.getAssetFilePath(%this.getAssetId())))); - %previewPath = "tools/resources/previewCache/" @ %module.moduleId @ "/"; + %previewPath = "tools/resources/previewCache/" @ %previewButton.moduleName @ "/"; if(!IsDirectory(%previewPath)) { @@ -111,7 +110,8 @@ function MaterialAsset::generatePreviewImage(%this, %previewButton, %forceRegene %generatePreview = false; - %previewFilePath = %previewPath @ %this.assetName @ ".png"; + %previewFilePath = %previewPath @ %this.assetName @ "_Preview.png"; + if(!isFile(%previewFilePath)) { %generatePreview = true; @@ -126,6 +126,8 @@ function MaterialAsset::generatePreviewImage(%this, %previewButton, %forceRegene } } + %previewAssetName = "ToolsModule:" @ %this.assetName @ "_Preview"; + if(%generatePreview || %forceRegenerate) { if(isObject(%this.materialDefinitionName)) @@ -137,22 +139,41 @@ function MaterialAsset::generatePreviewImage(%this, %previewButton, %forceRegene %diffuseMapAsset = AssetDatabase.acquireAsset(%diffuseMapAssetId); AssetDatabase.releaseAsset(%diffuseMapAssetId); } + %previewShapeDef = AssetDatabase.acquireAsset("ToolsModule:previewSphereShape"); %generatedFilePath = %previewShapeDef.generateCachedPreviewImage(256, %this.materialDefinitionName); pathCopy(%generatedFilePath, %previewFilePath, false); fileDelete(%generatedFilePath); - if(isFile(%previewFilePath)) + if(!AssetDatabase.isDeclaredAsset(%previewAssetName)) { - %previewButton.setBitmap(%previewFilePath); - return true; + %preview_Asset = new ImageAsset() + { + assetName = %this.assetName @ "_Preview"; + versionId = 1; + imageFile = makeFullPath(%previewFilePath); + }; + + TamlWrite(%preview_Asset, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); + %toolsModuleDef = ModuleDatabase.findModule("ToolsModule",1); + AssetDatabase.addDeclaredAsset(%toolsModuleDef, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); } + %previewButton.bitmapAsset = %previewAssetName; + return true; + } + else + { return false; } } - + else + { + %previewButton.bitmapAsset = %previewAssetName; + return true; + } + return false; } diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript index 855ba712c..d91ea925d 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript @@ -111,23 +111,21 @@ function ShapeAsset::generatePreviewImage(%this, %previewButton, %forceRegenerat if(%forceRegenerate $= "") %forceRegenerate = false; - %assetId = %this.getAssetId(); - - %module = %previewButton.assetBrowser.dirHandler.getModuleFromAddress(makeRelativePath(filePath(%this.getShapePath()))); - %previewPath = "tools/resources/previewCache/" @ %module.moduleId @ "/"; + %previewPath = "tools/resources/previewCache/" @ %previewButton.moduleName @ "/"; if(!IsDirectory(%previewPath)) { - %previewButton.assetBrowser.dirHandler.createFolder(%previewPath); + $CurrentAssetBrowser.dirHandler.createFolder(%previewPath); } - %generatePreview = false; + %previewFilePath = %previewPath @ %this.assetName @ "_Preview.png"; - %previewFilePath = %previewPath @ %this.assetName @ ".png"; if(!isFile(%previewFilePath) || (compareFileTimes(%this.getShapePath(), %previewFilePath) == 1)) { %generatePreview = true; } + + %previewAssetName = "ToolsModule:" @ %this.assetName @ "_Preview"; if(%generatePreview || %forceRegenerate) { @@ -146,14 +144,28 @@ function ShapeAsset::generatePreviewImage(%this, %previewButton, %forceRegenerat pathCopy(%filePath, %previewFilePath, false); fileDelete(%filePath); //cleanup - - if(isFile(%previewFilePath)) + + if(!AssetDatabase.isDeclaredAsset(%previewAssetName)) { - %previewButton.setBitmap(%previewFilePath); - return true; + %preview_Asset = new ImageAsset() + { + assetName = %this.assetName @ "_Preview"; + versionId = 1; + imageFile = makeFullPath(%previewFilePath); + }; + + TamlWrite(%preview_Asset, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); + %toolsModuleDef = ModuleDatabase.findModule("ToolsModule",1); + AssetDatabase.addDeclaredAsset(%toolsModuleDef, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); } - return false; + %previewButton.bitmapAsset = %previewAssetName; + return true; + } + else + { + %previewButton.bitmapAsset = %previewAssetName; + return true; } return false; From fc9f221ac07ef49a477fb1d689a84705ecbd646d Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 16 Jun 2025 08:33:11 +0100 Subject: [PATCH 02/13] Prepend symbol for image files Prepend image filenames in imageassets with "@" symbol so expand and collapse works correctly for files relative to that asset.taml file. --- Engine/source/T3D/assets/assetImporter.cpp | 2 +- Engine/source/assets/assetBase.cpp | 22 ++++++++++++++++--- .../scripts/assetTypes/image.tscript | 2 +- .../scripts/assetTypes/material.tscript | 2 +- .../scripts/assetTypes/shape.tscript | 2 +- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Engine/source/T3D/assets/assetImporter.cpp b/Engine/source/T3D/assets/assetImporter.cpp index eca044509..2a6ee089f 100644 --- a/Engine/source/T3D/assets/assetImporter.cpp +++ b/Engine/source/T3D/assets/assetImporter.cpp @@ -2825,7 +2825,7 @@ Torque::Path AssetImporter::importImageAsset(AssetImportObject* assetItem) StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str()); String imageFileName = assetItem->filePath.getFullFileName(); - String assetPath = targetPath + "/" + imageFileName; + String assetPath = "@" + imageFileName; String tamlPath = targetPath + "/" + assetName + ".asset.taml"; String originalPath = assetItem->filePath.getFullPath().c_str(); diff --git a/Engine/source/assets/assetBase.cpp b/Engine/source/assets/assetBase.cpp index dba9f142a..fcb9b5051 100644 --- a/Engine/source/assets/assetBase.cpp +++ b/Engine/source/assets/assetBase.cpp @@ -226,9 +226,20 @@ StringTableEntry AssetBase::expandAssetFilePath(const char* pAssetFilePath) cons assetBasePathHint = NULL; } - // Expand the path with the asset base-path hint. char assetFilePathBuffer[1024]; - Con::expandPath(assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetFilePath, assetBasePathHint); + + if (*pAssetFilePath != '@') + { + // Expand the path with the asset base-path hint. + Con::expandPath(assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetFilePath, assetBasePathHint); + return StringTable->insert(assetFilePathBuffer); + } + + if(!getOwned()) + return StringTable->insert(pAssetFilePath); + + // Format expanded path taking into account any missing slash. + dSprintf(assetFilePathBuffer, sizeof(assetFilePathBuffer), "%s/%s", mpOwningAssetManager->getAssetPath(getAssetId()), pAssetFilePath + (pAssetFilePath[1] == '/' ? 2 : 1)); return StringTable->insert(assetFilePathBuffer); } @@ -254,6 +265,11 @@ StringTableEntry AssetBase::collapseAssetFilePath(const char* pAssetFilePath) co char assetFilePathBuffer[1024]; + if (*pAssetFilePath == '@') + { + return StringTable->insert(pAssetFilePath); + } + // Is the asset not owned or private? if (!getOwned() || getAssetPrivate()) { @@ -272,7 +288,7 @@ StringTableEntry AssetBase::collapseAssetFilePath(const char* pAssetFilePath) co StringTableEntry relativePath = Platform::makeRelativePathName(pAssetFilePath, assetBasePath); // Format the collapsed path. - dSprintf(assetFilePathBuffer, sizeof(assetFilePathBuffer), "%s", relativePath); + dSprintf(assetFilePathBuffer, sizeof(assetFilePathBuffer), "@%s", relativePath); } else { diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript index 1aa34f78c..eb29fb365 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/image.tscript @@ -71,7 +71,7 @@ function ImageAsset::generatePreviewImage(%this, %previewButton, %forceRegenerat { assetName = %this.assetName @ "_Preview"; versionId = 1; - imageFile = makeFullPath(%previewFilePath); + imageFile = "@" @ %this.assetName @ "_Preview.png"; }; TamlWrite(%preview_Asset, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript index 33456e96a..78d611b5f 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript @@ -152,7 +152,7 @@ function MaterialAsset::generatePreviewImage(%this, %previewButton, %forceRegene { assetName = %this.assetName @ "_Preview"; versionId = 1; - imageFile = makeFullPath(%previewFilePath); + imageFile = "@" @ %this.assetName @ "_Preview.png"; }; TamlWrite(%preview_Asset, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript index d91ea925d..be6d0087e 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript @@ -151,7 +151,7 @@ function ShapeAsset::generatePreviewImage(%this, %previewButton, %forceRegenerat { assetName = %this.assetName @ "_Preview"; versionId = 1; - imageFile = makeFullPath(%previewFilePath); + imageFile = "@" @ %this.assetName @ "_Preview.png"; }; TamlWrite(%preview_Asset, expandPath("^ToolsModule/resources/previewCache/" @ %previewButton.moduleName @ "/" @ %preview_Asset.AssetName @ ".asset.taml")); From 67f217ada125bae06d96e521049351e7a574b974 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 17 Jun 2025 12:20:47 +0100 Subject: [PATCH 03/13] Update assetImporter.cpp asset importing for images shouldnt execute a file copy, original file path is enough as it is relative to exe --- Engine/source/T3D/assets/assetImporter.cpp | 27 ++-------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/Engine/source/T3D/assets/assetImporter.cpp b/Engine/source/T3D/assets/assetImporter.cpp index 2a6ee089f..5d0c55d78 100644 --- a/Engine/source/T3D/assets/assetImporter.cpp +++ b/Engine/source/T3D/assets/assetImporter.cpp @@ -2829,25 +2829,14 @@ Torque::Path AssetImporter::importImageAsset(AssetImportObject* assetItem) String tamlPath = targetPath + "/" + assetName + ".asset.taml"; String originalPath = assetItem->filePath.getFullPath().c_str(); - char qualifiedFromFile[2048]; - char qualifiedToFile[2048]; - -#ifndef TORQUE_SECURE_VFS - Platform::makeFullPathName(originalPath.c_str(), qualifiedFromFile, sizeof(qualifiedFromFile)); - Platform::makeFullPathName(assetPath.c_str(), qualifiedToFile, sizeof(qualifiedToFile)); -#else - dStrcpy(qualifiedFromFile, originalPath.c_str(), sizeof(qualifiedFromFile)); - dStrcpy(qualifiedToFile, assetPath.c_str(), sizeof(qualifiedToFile)); -#endif - newAsset->setAssetName(assetName); newAsset->setImageFile(assetPath.c_str()); //If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original //file path for reimporting support later - if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::IsFile(qualifiedFromFile)) + if (!isReimport) { - newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile); + newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, originalPath.c_str()); } if (assetItem->typeHint != String::EmptyString) @@ -2870,18 +2859,6 @@ Torque::Path AssetImporter::importImageAsset(AssetImportObject* assetItem) return ""; } - if (!isReimport) - { - bool isInPlace = !String::compare(qualifiedFromFile, qualifiedToFile); - - if (!isInPlace && !Torque::FS::CopyFile(qualifiedFromFile, qualifiedToFile, !isReimport)) - { - dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", assetItem->filePath.getFullPath().c_str()); - activityLog.push_back(importLogBuffer); - return ""; - } - } - return tamlPath; } From 3d77b59b7157f50c7d2b91036f651a3795d35d9e Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 17 Jun 2025 14:57:18 +0100 Subject: [PATCH 04/13] Update assetImporter.cpp refresh asset so image asset can write out its image metadata --- Engine/source/T3D/assets/assetImporter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Engine/source/T3D/assets/assetImporter.cpp b/Engine/source/T3D/assets/assetImporter.cpp index 5d0c55d78..726f490de 100644 --- a/Engine/source/T3D/assets/assetImporter.cpp +++ b/Engine/source/T3D/assets/assetImporter.cpp @@ -2805,6 +2805,7 @@ void AssetImporter::acquireAssets(AssetImportObject* assetItem) if (AssetDatabase.isDeclaredAsset(assetId)) { AssetDatabase.acquireAsset(assetId); + AssetDatabase.refreshAsset(assetId); AssetDatabase.releaseAsset(assetId); } } From 48b512ef73dc9a111616f7bb84f02fbb8f7eed61 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 17 Jun 2025 15:06:07 +0100 Subject: [PATCH 05/13] move population of image metadata to onAssetRefresh --- Engine/source/T3D/assets/ImageAsset.cpp | 87 +++++++++++++------------ Engine/source/T3D/assets/ImageAsset.h | 2 +- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/Engine/source/T3D/assets/ImageAsset.cpp b/Engine/source/T3D/assets/ImageAsset.cpp index 7e0cf1952..99dc97eb9 100644 --- a/Engine/source/T3D/assets/ImageAsset.cpp +++ b/Engine/source/T3D/assets/ImageAsset.cpp @@ -345,6 +345,8 @@ void ImageAsset::initializeAsset(void) return; mImageFile = expandAssetFilePath(mImageFile); + + populateImage(); } void ImageAsset::onAssetRefresh(void) @@ -356,6 +358,8 @@ void ImageAsset::onAssetRefresh(void) // Call parent. Parent::onAssetRefresh(); + populateImage(); + } //------------------------------------------------------------------------------ @@ -395,46 +399,6 @@ void ImageAsset::setImageFile(StringTableEntry pImageFile) mImageFile = getOwned() ? expandAssetFilePath(pImageFile) : StringTable->insert(pImageFile); - if (Torque::FS::IsFile(mImageFile)) - { - if (dStrEndsWith(mImageFile, ".dds")) - { - DDSFile* tempFile = new DDSFile(); - FileStream* ddsFs; - if ((ddsFs = FileStream::createAndOpen(mImageFile, Torque::FS::File::Read)) == NULL) - { - Con::errorf("ImageAsset::setImageFile Failed to open ddsfile: %s", mImageFile); - } - - if (!tempFile->readHeader(*ddsFs)) - { - Con::errorf("ImageAsset::setImageFile Failed to read header of ddsfile: %s", mImageFile); - } - else - { - mImageWidth = tempFile->mWidth; - mImageHeight = tempFile->mHeight; - } - - ddsFs->close(); - delete tempFile; - } - else - { - if (!stbi_info(mImageFile, &mImageWidth, &mImageHeight, &mImageChannels)) - { - StringTableEntry stbErr = stbi_failure_reason(); - if (stbErr == StringTable->EmptyString()) - stbErr = "ImageAsset::Unkown Error!"; - - Con::errorf("ImageAsset::setImageFile STB Get file info failed: %s", stbErr); - } - } - - // we only support 2d textures..... for no ;) - mImageDepth = 1; - } - refreshAsset(); } @@ -675,6 +639,49 @@ void ImageAsset::onTamlCustomRead(const TamlCustomNodes& customNodes) } } +void ImageAsset::populateImage(void) +{ + if (Torque::FS::IsFile(mImageFile)) + { + if (dStrEndsWith(mImageFile, ".dds")) + { + DDSFile* tempFile = new DDSFile(); + FileStream* ddsFs; + if ((ddsFs = FileStream::createAndOpen(mImageFile, Torque::FS::File::Read)) == NULL) + { + Con::errorf("ImageAsset::setImageFile Failed to open ddsfile: %s", mImageFile); + } + + if (!tempFile->readHeader(*ddsFs)) + { + Con::errorf("ImageAsset::setImageFile Failed to read header of ddsfile: %s", mImageFile); + } + else + { + mImageWidth = tempFile->mWidth; + mImageHeight = tempFile->mHeight; + } + + ddsFs->close(); + delete tempFile; + } + else + { + if (!stbi_info(mImageFile, &mImageWidth, &mImageHeight, &mImageChannels)) + { + StringTableEntry stbErr = stbi_failure_reason(); + if (stbErr == StringTable->EmptyString()) + stbErr = "ImageAsset::Unkown Error!"; + + Con::errorf("ImageAsset::setImageFile STB Get file info failed: %s", stbErr); + } + } + + // we only support 2d textures..... for now ;) + mImageDepth = 1; + } +} + const char* ImageAsset::getImageInfo() { if (isAssetValid()) diff --git a/Engine/source/T3D/assets/ImageAsset.h b/Engine/source/T3D/assets/ImageAsset.h index c60523b81..2300e0de6 100644 --- a/Engine/source/T3D/assets/ImageAsset.h +++ b/Engine/source/T3D/assets/ImageAsset.h @@ -196,7 +196,7 @@ public: static U32 getAssetById(StringTableEntry assetId, AssetPtr* imageAsset); static U32 getAssetById(String assetId, AssetPtr* imageAsset) { return getAssetById(assetId.c_str(), imageAsset); }; - + void populateImage(void); const char* getImageInfo(); protected: From 794a8c900de74f8afd7d9319d1fa17acee2d4832 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 17 Jun 2025 16:49:07 +0100 Subject: [PATCH 06/13] Update ImageAsset.cpp add change notification on intialize asset use this callback to update information about the image on refresh. Remove notification when the asset is removed and when the imagefile changes --- Engine/source/T3D/assets/ImageAsset.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Engine/source/T3D/assets/ImageAsset.cpp b/Engine/source/T3D/assets/ImageAsset.cpp index 99dc97eb9..bc831a2c8 100644 --- a/Engine/source/T3D/assets/ImageAsset.cpp +++ b/Engine/source/T3D/assets/ImageAsset.cpp @@ -213,6 +213,8 @@ bool ImageAsset::onAdd() void ImageAsset::onRemove() { + Torque::FS::RemoveChangeNotification(mImageFile, this, &ImageAsset::_onResourceChanged); + // Call Parent. Parent::onRemove(); } @@ -346,6 +348,9 @@ void ImageAsset::initializeAsset(void) mImageFile = expandAssetFilePath(mImageFile); + if (getOwned()) + Torque::FS::AddChangeNotification(mImageFile, this, &ImageAsset::_onResourceChanged); + populateImage(); } @@ -389,6 +394,8 @@ void ImageAsset::setImageFile(StringTableEntry pImageFile) if (pImageFile == mImageFile) return; + Torque::FS::RemoveChangeNotification(mImageFile, this, &ImageAsset::_onResourceChanged); + if (String(pImageFile).startsWith("#") || String(pImageFile).startsWith("$")) { mImageFile = StringTable->insert(pImageFile); From 51b1e3b07ea74545444e72ca444f03c1141d48af Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 18 Jun 2025 09:27:47 +0100 Subject: [PATCH 07/13] update cursors GuiCursor needs to be changed to use bitmapAsset guiTypes.GuiCursor safety around rendering getBitmap() --- Engine/source/gui/core/guiTypes.cpp | 4 ++++ .../BaseGame/game/tools/gui/cursors.ed.tscript | 12 ++++++------ .../tools/worldEditor/scripts/cursors.ed.tscript | 16 ++++++++-------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/Engine/source/gui/core/guiTypes.cpp b/Engine/source/gui/core/guiTypes.cpp index 79d24b297..f0dbf8ebc 100644 --- a/Engine/source/gui/core/guiTypes.cpp +++ b/Engine/source/gui/core/guiTypes.cpp @@ -116,6 +116,10 @@ void GuiCursor::render(const Point2I &pos) { mExtent.set(getBitmap()->getWidth(), getBitmap()->getHeight()); } + else + { + return; + } // Render the cursor centered according to dimensions of texture S32 texWidth = getBitmap()->getWidth(); diff --git a/Templates/BaseGame/game/tools/gui/cursors.ed.tscript b/Templates/BaseGame/game/tools/gui/cursors.ed.tscript index 7e1ffbf7c..a4fff7628 100644 --- a/Templates/BaseGame/game/tools/gui/cursors.ed.tscript +++ b/Templates/BaseGame/game/tools/gui/cursors.ed.tscript @@ -24,40 +24,40 @@ new GuiCursor(LeftRightCursor) { hotSpot = "0.5 0"; renderOffset = "0.5 0"; - bitmapName = "./Images/leftRight"; + bitmapAsset = "ToolsModule:leftRight_image"; }; new GuiCursor(UpDownCursor) { hotSpot = "1 1"; renderOffset = "0 1"; - bitmapName = "./Images/upDown"; + bitmapAsset = "ToolsModule:upDown_image"; }; new GuiCursor(NWSECursor) { hotSpot = "1 1"; renderOffset = "0.5 0.5"; - bitmapName = "./Images/NWSE"; + bitmapAsset = "ToolsModule:NWSE_image"; }; new GuiCursor(NESWCursor) { hotSpot = "1 1"; renderOffset = "0.5 0.5"; - bitmapName = "./Images/NESW"; + bitmapAsset = "ToolsModule:NESW_image"; }; new GuiCursor(MoveCursor) { hotSpot = "1 1"; renderOffset = "0.5 0.5"; - bitmapName = "./Images/move"; + bitmapAsset = "ToolsModule:move_image"; }; new GuiCursor(TextEditCursor) { hotSpot = "1 1"; renderOffset = "0.5 0.5"; - bitmapName = "./Images/textEdit"; + bitmapAsset = "ToolsModule:textEdit_image"; }; diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/cursors.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/cursors.ed.tscript index f281b653a..2a7400884 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/cursors.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/cursors.ed.tscript @@ -27,48 +27,48 @@ new GuiCursor(EditorHandCursor) { hotSpot = "7 0"; - bitmapName = "~/worldEditor/images/CUR_hand.png"; + bitmapAsset = "ToolsModule:CUR_hand_image"; }; new GuiCursor(EditorRotateCursor) { hotSpot = "11 18"; - bitmapName = "~/worldEditor/images/CUR_rotate.png"; + bitmapAsset = "ToolsModule:CUR_rotate_image"; }; new GuiCursor(EditorMoveCursor) { hotSpot = "9 13"; - bitmapName = "~/worldEditor/images/CUR_grab.png"; + bitmapAsset = "ToolsModule:CUR_grab_image"; }; new GuiCursor(EditorArrowCursor) { hotSpot = "0 0"; - bitmapName = "~/worldEditor/images/CUR_3darrow.png"; + bitmapAsset = "ToolsModule:CUR_3darrow_image"; }; new GuiCursor(EditorUpDownCursor) { hotSpot = "5 10"; - bitmapName = "~/worldEditor/images/CUR_3dupdown"; + bitmapAsset = "ToolsModule:CUR_3dupdown_image"; }; new GuiCursor(EditorLeftRightCursor) { hotSpot = "9 5"; - bitmapName = "~/worldEditor/images/CUR_3dleftright"; + bitmapAsset = "ToolsModule:CUR_3dleftright_image"; }; new GuiCursor(EditorDiagRightCursor) { hotSpot = "8 8"; - bitmapName = "~/worldEditor/images/CUR_3ddiagright"; + bitmapAsset = "ToolsModule:CUR_3ddiagright_image"; }; new GuiCursor(EditorDiagLeftCursor) { hotSpot = "8 8"; - bitmapName = "~/worldEditor/images/CUR_3ddiagleft"; + bitmapAsset = "ToolsModule:CUR_3ddiagleft_image"; }; new GuiControl(EmptyControl) From a276ad2505278918d90fa1353842c0435c2d7a4f Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 18 Jun 2025 09:29:12 +0100 Subject: [PATCH 08/13] Update cursors.tscript missed UI cursors --- Templates/BaseGame/game/data/UI/scripts/cursors.tscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Templates/BaseGame/game/data/UI/scripts/cursors.tscript b/Templates/BaseGame/game/data/UI/scripts/cursors.tscript index ba81636f7..ba54e5bed 100644 --- a/Templates/BaseGame/game/data/UI/scripts/cursors.tscript +++ b/Templates/BaseGame/game/data/UI/scripts/cursors.tscript @@ -26,7 +26,7 @@ if($platform $= "macos") { hotSpot = "4 4"; renderOffset = "0 0"; - bitmapName = "data/ui/images/macCursor"; + bitmapAsset = "UI:macCursor_image"; }; } else @@ -35,6 +35,6 @@ else { hotSpot = "1 1"; renderOffset = "0 0"; - bitmapName = "data/ui/images/defaultCursor"; + bitmapAsset = "UI:defaultCursor_image"; }; } From 6f9c4158d86a44ba185037ae2aa073cc291ec84f Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 18 Jun 2025 17:05:35 +0100 Subject: [PATCH 09/13] gui offscreen material test added interaction static guioffscreencanvas to capture mouse events added test shape --- Engine/source/T3D/fps/guiCrossHairHud.cpp | 75 ++++++++++++++++-- Engine/source/gui/core/guiCanvas.cpp | 6 ++ Engine/source/gui/core/guiOffscreenCanvas.cpp | 4 +- Engine/source/gui/core/guiOffscreenCanvas.h | 5 ++ .../ScreenTarget.asset.taml | 11 +++ .../monitor_base_mat.asset.taml | 13 +++ .../monitor_screen_mat.asset.taml | 16 ++++ .../monitor_shape.asset.taml | 6 ++ .../gui_offscreen_test/monitor_shape.fbx | Bin 0 -> 23916 bytes .../gui_offscreen_test/monitor_shape.tscript | 61 ++++++++++++++ 10 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/ScreenTarget.asset.taml create mode 100644 Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml create mode 100644 Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_screen_mat.asset.taml create mode 100644 Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.asset.taml create mode 100644 Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.fbx create mode 100644 Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.tscript diff --git a/Engine/source/T3D/fps/guiCrossHairHud.cpp b/Engine/source/T3D/fps/guiCrossHairHud.cpp index eaa318c53..6e6dc2fce 100644 --- a/Engine/source/T3D/fps/guiCrossHairHud.cpp +++ b/Engine/source/T3D/fps/guiCrossHairHud.cpp @@ -30,7 +30,11 @@ #include "T3D/shapeBase.h" #include "gfx/gfxDrawUtil.h" #include "console/engineAPI.h" - +#include "gui/core/guiOffscreenCanvas.h" +#include "T3D/tsStatic.h" +#include "materials/baseMatInstance.h" +#include "materials/matInstance.h" +#include "materials/materialDefinition.h" //----------------------------------------------------------------------------- /// Vary basic cross hair hud. @@ -46,12 +50,14 @@ class GuiCrossHairHud : public GuiBitmapCtrl LinearColorF mDamageFrameColor; Point2I mDamageRectSize; Point2I mDamageOffset; + PlatformTimer* mFrameTime; protected: void drawDamage(Point2I offset, F32 damage, F32 opacity); public: GuiCrossHairHud(); + ~GuiCrossHairHud(); void onRender( Point2I, const RectI &) override; static void initPersistFields(); @@ -95,6 +101,12 @@ GuiCrossHairHud::GuiCrossHairHud() mDamageFrameColor.set( 1.0f, 0.6f, 0.0f, 1.0f ); mDamageRectSize.set(50, 4); mDamageOffset.set(0,32); + mFrameTime = PlatformTimer::create(); +} + +GuiCrossHairHud::~GuiCrossHairHud() +{ + SAFE_DELETE(mFrameTime); } void GuiCrossHairHud::initPersistFields() @@ -114,13 +126,14 @@ void GuiCrossHairHud::initPersistFields() void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) { + GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL; // Must have a connection and player control object GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn) return; - GameBase* control = dynamic_cast(conn->getCameraObject()); + /*GameBase* control = dynamic_cast(conn->getCameraObject()); if (!control || !(control->getTypeMask() & ObjectMask) || !conn->isFirstPerson()) - return; + return;*/ // Parent render. Parent::onRender(offset,updateRect); @@ -139,11 +152,61 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) // Collision info. We're going to be running LOS tests and we // don't want to collide with the control object. - static U32 losMask = TerrainObjectType | ShapeBaseObjectType; - control->disableCollision(); + static U32 losMask = TerrainObjectType | ShapeBaseObjectType | StaticShapeObjectType; + //control->disableCollision(); RayInfo info; if (gClientContainer.castRay(camPos, endPos, losMask, &info)) { + // is this a tsstatic? then it could be a offscreen canvas, check the list. + if (TSStatic* ts = dynamic_cast(info.object)) + { + if (mFrameTime->getElapsedMs() > 32) + { + mFrameTime->reset(); + + Point3F newStart, newEnd; + ts->getWorldTransform().mulP(camPos, &newStart); + ts->getWorldTransform().mulP(endPos, &newEnd); + + newStart.convolveInverse(ts->getScale()); + newEnd.convolveInverse(ts->getScale()); + + info.generateTexCoord = true; + if (ts->getShapeInstance()->castRayOpcode(0, newStart, newEnd, &info)) + { + MatInstance* matInst = dynamic_cast(info.material); + if (matInst) + { + Material* mat = matInst->getMaterial(); + if (mat && mat->getDiffuseMapAsset(0).notNull() && mat->getDiffuseMapAsset(0)->isNamedTarget()) + { + String canvasName = String(mat->getDiffuseMapAsset(0)->getImageFile()).substr(1, (U32)strlen(mat->getDiffuseMapAsset(0)->getImageFile()) - 1); + for (GuiOffscreenCanvas* canvas : GuiOffscreenCanvas::sList) + { + if (canvas->getTarget()->getName() == canvasName) + { + if (!canvas->canInteract() || canvas->getMaxInteractDistance() < info.distance) + { + break; + } + + Point2I canvasSize = canvas->getWindowSize(); + Point2I newCursorPos(mRound(mClampF((info.texCoord.x * canvasSize.x), 0.0f, (F32)canvasSize.x)), + mRound(mClampF((info.texCoord.y * canvasSize.y), 0.0f, (F32)canvasSize.y))); + + canvas->setCursorPos(newCursorPos); + canvas->markDirty(); + GuiOffscreenCanvas::sActiveOffscreenCanvas = canvas; + break; + } + } + } + } + } + } + + } + // Hit something... but we'll only display health for named // ShapeBase objects. Could mask against the object type here // and do a static cast if it's a ShapeBaseObjectType, but this @@ -157,7 +220,7 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) } // Restore control object collision - control->enableCollision(); + //control->enableCollision(); } diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index d00c3024a..b14f7ece2 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -690,6 +690,12 @@ bool GuiCanvas::processInputEvent(InputEventInfo &inputEvent) mConsumeLastInputEvent = true; mLastInputDeviceType = inputEvent.deviceType; + // If we have an active offscreen canvas, give it the input + if (GuiOffscreenCanvas::sActiveOffscreenCanvas && + (GuiOffscreenCanvas::sActiveOffscreenCanvas != this) && + GuiOffscreenCanvas::sActiveOffscreenCanvas->processInputEvent(inputEvent)) + return mConsumeLastInputEvent; + // First call the general input handler (on the extremely off-chance that it will be handled): if (mFirstResponder && mFirstResponder->onInputEvent(inputEvent)) { diff --git a/Engine/source/gui/core/guiOffscreenCanvas.cpp b/Engine/source/gui/core/guiOffscreenCanvas.cpp index 522882b14..55562b028 100644 --- a/Engine/source/gui/core/guiOffscreenCanvas.cpp +++ b/Engine/source/gui/core/guiOffscreenCanvas.cpp @@ -9,6 +9,7 @@ IMPLEMENT_CONOBJECT(GuiOffscreenCanvas); +GuiOffscreenCanvas* GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL; Vector GuiOffscreenCanvas::sList; GuiOffscreenCanvas::GuiOffscreenCanvas() @@ -33,7 +34,8 @@ void GuiOffscreenCanvas::initPersistFields() addField( "targetName", TypeRealString, Offset( mTargetName, GuiOffscreenCanvas ), ""); addField( "dynamicTarget", TypeBool, Offset( mDynamicTarget, GuiOffscreenCanvas ), ""); addField( "useDepth", TypeBool, Offset( mUseDepth, GuiOffscreenCanvas ), ""); - + addField("canInteract", TypeBool, Offset(mCanInteract, GuiOffscreenCanvas), ""); + addField("maxInteractDistance", TypeF32, Offset(mMaxInteractDistance, GuiOffscreenCanvas), ""); Parent::initPersistFields(); } diff --git a/Engine/source/gui/core/guiOffscreenCanvas.h b/Engine/source/gui/core/guiOffscreenCanvas.h index 0d7a79d35..de8c221b8 100644 --- a/Engine/source/gui/core/guiOffscreenCanvas.h +++ b/Engine/source/gui/core/guiOffscreenCanvas.h @@ -38,6 +38,8 @@ public: void _teardownTargets(); NamedTexTargetRef getTarget() { return &mNamedTarget; } + bool canInteract() { return mCanInteract; } + F32 getMaxInteractDistance() { return mMaxInteractDistance; } void markDirty() { mTargetDirty = true; } @@ -59,9 +61,12 @@ protected: bool mUseDepth; GFXTexHandle mTargetDepth; + bool mCanInteract; + F32 mMaxInteractDistance; public: static Vector sList; + static GuiOffscreenCanvas* sActiveOffscreenCanvas; }; #endif diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/ScreenTarget.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/ScreenTarget.asset.taml new file mode 100644 index 000000000..fc9196375 --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/ScreenTarget.asset.taml @@ -0,0 +1,11 @@ + + + + + diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml new file mode 100644 index 000000000..75d507122 --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_screen_mat.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_screen_mat.asset.taml new file mode 100644 index 000000000..db7490eea --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_screen_mat.asset.taml @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.asset.taml new file mode 100644 index 000000000..1a8665bbd --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.asset.taml @@ -0,0 +1,6 @@ + diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.fbx b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.fbx new file mode 100644 index 0000000000000000000000000000000000000000..3acc77e04f80a98e20239215f1ef3ab02cbb053e GIT binary patch literal 23916 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 z'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 literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.tscript b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.tscript new file mode 100644 index 000000000..18269168b --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.tscript @@ -0,0 +1,61 @@ + +singleton TSShapeConstructor(monitor_shapefbx) +{ + baseShapeAsset = "Prototyping:monitor_shape"; + singleDetailSize = "0"; + neverImportMat = "DefaultMaterial ColorEffect*"; + flipUVCoords = "0"; + joinIdenticalVerts = "0"; + reverseWindingOrder = "0"; + removeRedundantMats = "0"; + animFPS = "2"; +}; + +function monitor_shapefbx::onLoad(%this) +{ + %this.addNode("Col-1", "", "0 0 0 0 0 1 0", "0", ""); + %this.addNode("ColBox-1", "Col-1", "0 0 0 1 0 0 0", "0", "Bounds"); + %this.addCollisionDetail("-1", "Box", "Bounds", "4", "10", "30", "32", "30", "30", "30", "Flood fill"); + %this.setBounds("-0.8 -0.244957 -0.0409516 0.8 0.244957 1.10231"); + + if (!isObject(screen_Canvas)) + { + new GuiOffscreenCanvas(screen_Canvas) { + targetName = "screen_Canvas"; + targetSize = "1280 720"; + dynamicTarget = false; + canInteract = true; + maxInteractDistance = "3"; + }; + } + + if(isObject(OptionsMenu)) + { + screen_Canvas.setContent(OptionsMenu); + } + + %screen_Canvas_asset = "Prototyping:ScreenTarget"; + if(!AssetDatabase.isDeclaredAsset(%screen_Canvas_asset)) + { + %screen_asset = new ImageAsset() + { + assetName = "ScreenTarget"; + versionId = 1; + imageFile = "#screen_Canvas"; + }; + TamlWrite(%screen_asset, expandPath("^Prototyping/gui_offscreen_test/" @ %screen_asset.AssetName @ ".asset.taml")); + %previewModule = ModuleDatabase.findModule("Prototyping",1); + AssetDatabase.addDeclaredAsset(%previewModule, expandPath("^Prototyping/gui_offscreen_test/" @ %screen_asset.AssetName @ ".asset.taml")); + } + + %mat_asset = "Prototyping:monitor_screen_mat"; + if(!AssetDatabase.isDeclaredAsset(%mat_asset)) + { + echo("Material asset not found, this should exist"); + } + + %assetDef = AssetDatabase.acquireAsset(%mat_asset); + %material = %assetDef.materialDefinitionName; + %material.DiffuseMapAsset = %screen_Canvas_asset; + +} From b5cd9d0c730f46476269e1253f8296481048c9e4 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 18 Jun 2025 17:08:40 +0100 Subject: [PATCH 10/13] Update guiCrossHairHud.cpp --- Engine/source/T3D/fps/guiCrossHairHud.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Engine/source/T3D/fps/guiCrossHairHud.cpp b/Engine/source/T3D/fps/guiCrossHairHud.cpp index 6e6dc2fce..f8d5afdeb 100644 --- a/Engine/source/T3D/fps/guiCrossHairHud.cpp +++ b/Engine/source/T3D/fps/guiCrossHairHud.cpp @@ -131,9 +131,9 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn) return; - /*GameBase* control = dynamic_cast(conn->getCameraObject()); + GameBase* control = dynamic_cast(conn->getCameraObject()); if (!control || !(control->getTypeMask() & ObjectMask) || !conn->isFirstPerson()) - return;*/ + return; // Parent render. Parent::onRender(offset,updateRect); @@ -153,7 +153,7 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) // Collision info. We're going to be running LOS tests and we // don't want to collide with the control object. static U32 losMask = TerrainObjectType | ShapeBaseObjectType | StaticShapeObjectType; - //control->disableCollision(); + control->disableCollision(); RayInfo info; if (gClientContainer.castRay(camPos, endPos, losMask, &info)) { @@ -220,7 +220,7 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) } // Restore control object collision - //control->enableCollision(); + control->enableCollision(); } From 1918ecfdd6ab7dccda9f272c1a23bb47baf1ae7f Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 18 Jun 2025 20:44:37 +0100 Subject: [PATCH 11/13] feedback from az fixes for interaction from az --- Engine/source/T3D/fps/guiCrossHairHud.cpp | 3 +-- Engine/source/gui/core/guiCanvas.cpp | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Engine/source/T3D/fps/guiCrossHairHud.cpp b/Engine/source/T3D/fps/guiCrossHairHud.cpp index f8d5afdeb..052350be1 100644 --- a/Engine/source/T3D/fps/guiCrossHairHud.cpp +++ b/Engine/source/T3D/fps/guiCrossHairHud.cpp @@ -126,7 +126,6 @@ void GuiCrossHairHud::initPersistFields() void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) { - GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL; // Must have a connection and player control object GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn) @@ -162,6 +161,7 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) { if (mFrameTime->getElapsedMs() > 32) { + GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL; mFrameTime->reset(); Point3F newStart, newEnd; @@ -204,7 +204,6 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) } } } - } // Hit something... but we'll only display health for named diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index b14f7ece2..c9f603d05 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -694,7 +694,10 @@ bool GuiCanvas::processInputEvent(InputEventInfo &inputEvent) if (GuiOffscreenCanvas::sActiveOffscreenCanvas && (GuiOffscreenCanvas::sActiveOffscreenCanvas != this) && GuiOffscreenCanvas::sActiveOffscreenCanvas->processInputEvent(inputEvent)) + { + GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL; return mConsumeLastInputEvent; + } // First call the general input handler (on the extremely off-chance that it will be handled): if (mFirstResponder && mFirstResponder->onInputEvent(inputEvent)) From 26e18cdfe83666c1665ffa3daa5da23ca1fe8505 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 18 Jun 2025 21:17:13 +0100 Subject: [PATCH 12/13] feedback from az scripts changed to reflect a better standard of loading offscreencanvas on client and not on the server --- .../game/data/Prototyping/Prototyping.tscript | 15 +++++++ .../monitor_base_mat.asset.taml | 1 + .../gui_offscreen_test/monitor_shape.tscript | 41 ------------------- 3 files changed, 16 insertions(+), 41 deletions(-) diff --git a/Templates/BaseGame/game/data/Prototyping/Prototyping.tscript b/Templates/BaseGame/game/data/Prototyping/Prototyping.tscript index c053fd2cf..bd3841f9e 100644 --- a/Templates/BaseGame/game/data/Prototyping/Prototyping.tscript +++ b/Templates/BaseGame/game/data/Prototyping/Prototyping.tscript @@ -42,6 +42,21 @@ function Prototyping::initClient(%this) //This is called when a client connects to a server function Prototyping::onCreateClientConnection(%this) { + if (!isObject(screen_Canvas)) + { + new GuiOffscreenCanvas(screen_Canvas) { + targetName = "screen_Canvas"; + targetSize = "1280 720"; + dynamicTarget = false; + canInteract = true; + maxInteractDistance = "3"; + }; + } + + if(isObject(OptionsMenu)) + { + screen_Canvas.setContent(OptionsMenu); + } } //This is called when a client disconnects from a server diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml index 75d507122..6267d5871 100644 --- a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml @@ -4,6 +4,7 @@ Date: Thu, 19 Jun 2025 07:53:32 +0100 Subject: [PATCH 13/13] Update ImageAsset.h add check for if _in matches the filename that is already set for image asset, this stops the set being called twice when loading the same image asset --- Engine/source/T3D/assets/ImageAsset.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Engine/source/T3D/assets/ImageAsset.h b/Engine/source/T3D/assets/ImageAsset.h index 2300e0de6..102f59052 100644 --- a/Engine/source/T3D/assets/ImageAsset.h +++ b/Engine/source/T3D/assets/ImageAsset.h @@ -123,7 +123,7 @@ public: }; static const String mErrCodeStrings[U32(ImageAssetErrCode::Extended) - U32(Parent::Extended) + 1]; - static U32 getAssetErrCode(ConcreteAssetPtr checkAsset) { if (checkAsset) return checkAsset->mLoadedState; else return 0; } + static U32 getAssetErrCode(ConcreteAssetPtr checkAsset) { if (checkAsset.notNull()) return checkAsset->mLoadedState; else return 0; } static String getAssetErrstrn(U32 errCode) { @@ -241,6 +241,8 @@ public: void _set##name(StringTableEntry _in){ \ if(m##name##Asset.getAssetId() == _in) \ return; \ + if(get##name##File() == _in) \ + return; \ if(_in == NULL || _in == StringTable->EmptyString()) \ { \ m##name##Asset = NULL; \ @@ -296,6 +298,8 @@ public: void _set##name(StringTableEntry _in){ \ if(m##name##Asset.getAssetId() == _in) \ return; \ + if(get##name##File() == _in) \ + return; \ if(_in == NULL || _in == StringTable->EmptyString()) \ { \ m##name##Asset = NULL; \ @@ -358,6 +362,8 @@ public: void _set##name(StringTableEntry _in, const U32& index){ \ if(m##name##Asset[index].getAssetId() == _in) \ return; \ + if(get##name##File(index) == _in) \ + return; \ if(_in == NULL || _in == StringTable->EmptyString()) \ { \ m##name##Asset[index] = NULL; \ @@ -414,6 +420,8 @@ public: void _set##name(StringTableEntry _in, const U32& index){ \ if(m##name##Asset[index].getAssetId() == _in) \ return; \ + if(get##name##File(index) == _in) \ + return; \ if(_in == NULL || _in == StringTable->EmptyString()) \ { \ m##name##Asset[index] = NULL; \