Updates ImageAsset usage to utilize AssetRef, and standardizes the setter/getter functions and naming conventions, as well as the ability to use and bind named targets.

This commit is contained in:
JeffR 2026-06-16 17:39:30 -05:00
parent a858d8624e
commit 34e3f78a22
82 changed files with 1451 additions and 951 deletions

View file

@ -65,7 +65,10 @@
//-----------------------------------------------------------------------------
StringTableEntry ImageAsset::smNoImageAssetFallback = NULL;
AssetPtr<ImageAsset> ImageAsset::smNoImageAssetFallbackAssetPtr = NULL;
StringTableEntry ImageAsset::smNamedTargetAssetFallback = NULL;
AssetPtr<ImageAsset> ImageAsset::smNamedTargetAssetFallbackAssetPtr = NULL;
//-----------------------------------------------------------------------------
@ -116,14 +119,93 @@ ConsoleSetType(TypeImageAssetPtr)
Con::warnf("(TypeImageAssetPtr) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
IMPLEMENT_STRUCT(AssetRef<ImageAsset>, AssetRefImageAsset, , "")
END_IMPLEMENT_STRUCT
ConsoleType(ImageAssetRef, TypeImageAssetRef, AssetRef<ImageAsset>, ASSET_ID_FIELD_PREFIX)
ConsoleGetType(TypeImageAssetRef)
{
AssetRef<ImageAsset>& ref = *((AssetRef<ImageAsset>*)dptr);
if (ref.assetPtr.isNull())
return ref.assetId;
else
{
if ((ref.assetId[0] == '$' || ref.assetId[0] == '#'))
return ref.assetId;
return ref.assetPtr.getAssetId();
}
}
AssetPtr<ImageAsset> ImageAsset::getNamedTargetAssetPtr(StringTableEntry filePath)
{
// Do a lookup to see if we can find a hit on this path/id
// If not, then we'll register it as a private asset and keep going
// as if we're in this function, we're almost certainly dealing with
// a named target anyways and require the special case.
StringTableEntry imageAssetId = getAssetIdByFilename(filePath);
if (imageAssetId == smNoImageAssetFallback)
{
ImageAsset* privateImage = new ImageAsset();
privateImage->setImageFile(filePath);
imageAssetId = AssetDatabase.addPrivateAsset(privateImage);
}
AssetPtr<ImageAsset> assetPtr;
assetPtr = imageAssetId;
return assetPtr;
}
ConsoleSetType(TypeImageAssetRef)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset pointer.
AssetRef<ImageAsset>* pAssetRef = (AssetRef<ImageAsset>*)(dptr);
// Is the asset pointer the correct type?
if (pAssetRef == NULL)
{
Con::warnf("(TypeImageAssetRef) - Failed to set asset Id '%d'.", pFieldValue);
return;
}
StringTableEntry _in = StringTable->insert(pFieldValue);
if (ImageAsset::isNamedTarget(_in))
{
pAssetRef->assetId = _in;
pAssetRef->assetPtr = ImageAsset::getNamedTargetAssetPtr(_in);
return;
}
// Set asset.
*pAssetRef = _in;
return;
}
// Warn.
Con::warnf("(TypeImageAssetRef) - Cannot set multiple args to a single asset.");
}
//-----------------------------------------------------------------------------
// REFACTOR END
//-----------------------------------------------------------------------------
ImplementEnumType(ImageAssetType,
"Type of mesh data available in a shape.\n"
"Type of image data this asset describes.\n"
"@ingroup gameObjects")
{ ImageAsset::Albedo, "Albedo", "" },
{ ImageAsset::Albedo, "Albedo", "" },
{ ImageAsset::Normal, "Normal", "" },
{ ImageAsset::ORMConfig, "ORMConfig", "" },
{ ImageAsset::GUI, "GUI", "" },
@ -308,6 +390,26 @@ StringTableEntry ImageAsset::getAssetIdByFilename(StringTableEntry fileName)
return imageAssetId;
}
StringTableEntry ImageAsset::getAssetIdFromFilePath(StringTableEntry filePath)
{
if (filePath == StringTable->EmptyString())
return filePath;
// Already a valid asset id.
if (AssetDatabase.isDeclaredAsset(filePath))
return filePath;
StringTableEntry assetId = getAssetIdByFilename(filePath);
if (assetId == smNoImageAssetFallback)
{
ImageAsset* privateImage = new ImageAsset();
privateImage->setImageFile(filePath);
assetId = AssetDatabase.addPrivateAsset(privateImage);
}
return assetId;
}
U32 ImageAsset::getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* imageAsset)
{
(*imageAsset) = assetId;
@ -318,8 +420,13 @@ U32 ImageAsset::getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* ima
}
else
{
//Didn't work, so have us fall back to a placeholder asset
imageAsset->setAssetId(ImageAsset::smNoImageAssetFallback);
if (imageAsset->isNull())
{
//Well that's bad, loading the fallback failed.
Con::errorf("ImageAsset::getAssetById - Finding of asset with id %s failed with no fallback asset", assetId);
return AssetErrCode::Failed;
}
@ -352,6 +459,25 @@ void ImageAsset::initializeAsset(void)
Torque::FS::AddChangeNotification(mImageFile, this, &ImageAsset::_onResourceChanged);
populateImage();
//Make sure our fallbacks are valid
if (smNoImageAssetFallbackAssetPtr.isNull())
{
smNoImageAssetFallbackAssetPtr = smNoImageAssetFallback;
if (smNoImageAssetFallbackAssetPtr.isNull())
Con::errorf("ImageAsset::initializeAsset could not find fallback asset %s!", smNoImageAssetFallback);
else
smNoImageAssetFallbackAssetPtr->load();
}
if (smNamedTargetAssetFallbackAssetPtr.isNull())
{
smNamedTargetAssetFallbackAssetPtr = smNamedTargetAssetFallback;
if (smNamedTargetAssetFallbackAssetPtr.isNull())
Con::errorf("ImageAsset::initializeAsset could not find named target fallback asset %s!", smNamedTargetAssetFallback);
else
smNamedTargetAssetFallbackAssetPtr->load();
}
}
void ImageAsset::onAssetRefresh(void)
@ -470,23 +596,20 @@ GFXTexHandle ImageAsset::getTexture(GFXTextureProfile* requestedProfile)
if (isNamedTarget())
{
GFXTexHandle tex;
AssetPtr<ImageAsset> fallbackAsset;
ImageAsset::getAssetById(smNamedTargetAssetFallback, &fallbackAsset);
if (getNamedTarget().isValid())
{
tex = getNamedTarget()->getTexture();
if (tex.isNull())
GFXTexHandle tex = getNamedTarget()->getTexture();
if (!tex.isNull())
{
return fallbackAsset->getTexture(requestedProfile);
mResourceMap.insert(requestedProfile, tex);
return tex;
}
mResourceMap.insert(requestedProfile, tex);
return tex;
}
else
{
return fallbackAsset->getTexture(requestedProfile);
}
if (smNamedTargetAssetFallbackAssetPtr.notNull())
return smNamedTargetAssetFallbackAssetPtr->getTexture(requestedProfile);
return NULL;
}
if (mLoadedState == Ok)
@ -501,6 +624,9 @@ GFXTexHandle ImageAsset::getTexture(GFXTextureProfile* requestedProfile)
}
}
if (smNoImageAssetFallbackAssetPtr.notNull() && smNoImageAssetFallbackAssetPtr != this)
return smNoImageAssetFallbackAssetPtr->getTexture(requestedProfile);
return NULL;
}
@ -1047,4 +1173,21 @@ DefineEngineMethod(GuiInspectorTypeImageAssetPtr, setIsDeleteBtnVisible, void, (
{
object->setIsDeleteBtnVisible(isVisible);
}
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiInspectorTypeImageAssetRef);
ConsoleDocClass(GuiInspectorTypeImageAssetRef,
"@brief Inspector field type for AssetRef<ImageAsset> fields\n\n"
"Editor use only.\n\n"
"@internal"
);
void GuiInspectorTypeImageAssetRef::consoleInit()
{
Parent::consoleInit();
ConsoleBaseType::getType(TypeImageAssetRef)->setInspectorFieldType("GuiInspectorTypeImageAssetRef");
}
#endif

View file

@ -114,7 +114,10 @@ public:
};
static StringTableEntry smNoImageAssetFallback;
static AssetPtr<ImageAsset> smNoImageAssetFallbackAssetPtr;
static StringTableEntry smNamedTargetAssetFallback;
static AssetPtr<ImageAsset> smNamedTargetAssetFallbackAssetPtr;
enum ImageAssetErrCode
{
@ -193,6 +196,17 @@ public:
static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ImageAsset>* imageAsset);
static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
static StringTableEntry getAssetIdFromFilePath(StringTableEntry filePath);
/// Returns true if the given value follows the named target naming convention:
/// ($backBuffer, #color)
static bool isNamedTarget(StringTableEntry name) { return name != NULL && name != StringTable->EmptyString() && (name[0] == '$' || name[0] == '#'); }
/// Resolves a named render target ($backBuffer, #color) to an asset
/// pointer, binding/creating a private ImageAsset if needed.
static AssetPtr<ImageAsset> getNamedTargetAssetPtr(StringTableEntry filePath);
static U32 getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* imageAsset);
static U32 getAssetById(String assetId, AssetPtr<ImageAsset>* imageAsset) { return getAssetById(assetId.c_str(), imageAsset); };
@ -228,267 +242,8 @@ protected:
DECLARE_STRUCT(AssetPtr<ImageAsset>)
DefineConsoleType(TypeImageAssetPtr, AssetPtr<ImageAsset> )
DECLARE_STRUCT(AssetRef<ImageAsset>)
DefineConsoleType(TypeImageAssetRef, AssetRef<ImageAsset>)
typedef ImageAsset::ImageTypes ImageAssetType;
DefineEnumType(ImageAssetType);
#pragma region Refactor Asset Macros
#define DECLARE_IMAGEASSET(className, name, profile) \
private: \
AssetPtr<ImageAsset> m##name##Asset; \
StringTableEntry m##name##File = StringTable->EmptyString(); \
public: \
void _set##name(StringTableEntry _in){ \
if(m##name##Asset.getAssetId() == _in) \
return; \
if(get##name##File() == _in) \
return; \
if(_in == NULL || !String::compare(_in,StringTable->EmptyString())) \
{ \
m##name##Asset = NULL; \
m##name##File = ""; \
return; \
} \
if(!AssetDatabase.isDeclaredAsset(_in)) \
{ \
StringTableEntry imageAssetId = StringTable->EmptyString(); \
AssetQuery query; \
S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \
if (foundAssetcount != 0) \
{ \
imageAssetId = query.mAssetList[0]; \
} \
else if(Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \
{ \
imageAssetId = ImageAsset::getAssetIdByFilename(_in); \
if (imageAssetId == ImageAsset::smNoImageAssetFallback) \
{ \
ImageAsset* privateImage = new ImageAsset(); \
privateImage->setImageFile(_in); \
imageAssetId = AssetDatabase.addPrivateAsset(privateImage); \
} \
} \
else \
{ \
Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \
imageAssetId = ImageAsset::smNoImageAssetFallback; \
} \
m##name##Asset = imageAssetId; \
m##name##File = _in; \
} \
else \
{ \
m##name##Asset = _in; \
m##name##File = get##name##File(); \
} \
}; \
\
inline StringTableEntry _get##name(void) const { return m##name##Asset.getAssetId(); } \
GFXTexHandle get##name() { return m##name##Asset.notNull() ? m##name##Asset->getTexture(&profile) : NULL; } \
AssetPtr<ImageAsset> get##name##Asset(void) { return m##name##Asset; } \
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data)); return false;} \
StringTableEntry get##name##File(){ return m##name##Asset.notNull() ? m##name##Asset->getImageFile() : ""; }
#define DECLARE_IMAGEASSET_NET(className, name, profile, mask) \
private: \
AssetPtr<ImageAsset> m##name##Asset; \
StringTableEntry m##name##File = StringTable->EmptyString(); \
public: \
void _set##name(StringTableEntry _in){ \
if(m##name##Asset.getAssetId() == _in) \
return; \
if(get##name##File() == _in) \
return; \
if(_in == NULL || !String::compare(_in,StringTable->EmptyString())) \
{ \
m##name##Asset = NULL; \
m##name##File = ""; \
setMaskBits(mask); \
return; \
} \
if(!AssetDatabase.isDeclaredAsset(_in)) \
{ \
StringTableEntry imageAssetId = StringTable->EmptyString(); \
AssetQuery query; \
S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \
if (foundAssetcount != 0) \
{ \
imageAssetId = query.mAssetList[0]; \
} \
else if(Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \
{ \
imageAssetId = ImageAsset::getAssetIdByFilename(_in); \
if (imageAssetId == ImageAsset::smNoImageAssetFallback) \
{ \
ImageAsset* privateImage = new ImageAsset(); \
privateImage->setImageFile(_in); \
imageAssetId = AssetDatabase.addPrivateAsset(privateImage); \
} \
} \
else \
{ \
Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \
imageAssetId = ImageAsset::smNoImageAssetFallback; \
} \
m##name##Asset = imageAssetId; \
m##name##File = _in; \
} \
else \
{ \
m##name##Asset = _in; \
m##name##File = get##name##File(); \
} \
setMaskBits(mask); \
}; \
\
inline StringTableEntry _get##name(void) const { return m##name##Asset.getAssetId(); } \
GFXTexHandle get##name() { return m##name##Asset.notNull() ? m##name##Asset->getTexture(&profile) : NULL; } \
AssetPtr<ImageAsset> get##name##Asset(void) { return m##name##Asset; } \
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data)); return false;} \
StringTableEntry get##name##File(){ return m##name##Asset.notNull() ? m##name##Asset->getImageFile() : ""; }
#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.), AbstractClassRep::FIELD_HideInInspectors);
#define DECLARE_IMAGEASSET_ARRAY(className, name, profile, max) \
private: \
AssetPtr<ImageAsset> m##name##Asset[max]; \
StringTableEntry m##name##File[max] = {StringTable->EmptyString() }; \
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 || !String::compare(_in,StringTable->EmptyString())) \
{ \
m##name##Asset[index] = NULL; \
m##name##File[index] = ""; \
return; \
} \
if(!AssetDatabase.isDeclaredAsset(_in)) \
{ \
StringTableEntry imageAssetId = StringTable->EmptyString(); \
AssetQuery query; \
S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \
if (foundAssetcount != 0) \
{ \
imageAssetId = query.mAssetList[0]; \
} \
else if(Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \
{ \
imageAssetId = ImageAsset::getAssetIdByFilename(_in); \
if (imageAssetId == ImageAsset::smNoImageAssetFallback) \
{ \
ImageAsset* privateImage = new ImageAsset(); \
privateImage->setImageFile(_in); \
imageAssetId = AssetDatabase.addPrivateAsset(privateImage); \
} \
} \
else \
{ \
Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \
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); \
} \
}; \
\
inline StringTableEntry _get##name(const U32& index) const { return m##name##Asset[index].getAssetId(); } \
GFXTexHandle get##name(const U32& index) { return get##name(&profile, index); } \
GFXTexHandle get##name(GFXTextureProfile* requestedProfile, const U32& index) { return m##name##Asset[index].notNull() ? m##name##Asset[index]->getTexture(requestedProfile) : NULL; }\
AssetPtr<ImageAsset> get##name##Asset(const U32& index) { return m##name##Asset[index]; } \
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data), dAtoi(index)); return false;}\
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) \
private: \
AssetPtr<ImageAsset> m##name##Asset[max]; \
StringTableEntry m##name##File[max] = {StringTable->EmptyString() }; \
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 || !String::compare(_in,StringTable->EmptyString())) \
{ \
m##name##Asset[index] = NULL; \
m##name##File[index] = ""; \
setMaskBits(mask); \
return; \
} \
if(!AssetDatabase.isDeclaredAsset(_in)) \
{ \
StringTableEntry imageAssetId = StringTable->EmptyString(); \
AssetQuery query; \
S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \
if (foundAssetcount != 0) \
{ \
imageAssetId = query.mAssetList[0]; \
} \
else if(Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \
{ \
imageAssetId = ImageAsset::getAssetIdByFilename(_in); \
if (imageAssetId == ImageAsset::smNoImageAssetFallback) \
{ \
ImageAsset* privateImage = new ImageAsset(); \
privateImage->setImageFile(_in); \
imageAssetId = AssetDatabase.addPrivateAsset(privateImage); \
} \
} \
else \
{ \
Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \
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); \
}; \
\
inline StringTableEntry _get##name(const U32& index) const { return m##name##Asset[index].getAssetId(); } \
GFXTexHandle get##name(const U32& index) { return m##name##Asset[index].notNull() ? m##name##Asset[index]->getTexture(&profile) : NULL; } \
GFXTexHandle get##name(GFXTextureProfile* requestedProfile, const U32& index) { return m##name##Asset[index].notNull() ? m##name##Asset[index]->getTexture(requestedProfile) : NULL; }\
AssetPtr<ImageAsset> get##name##Asset(const U32& index) { return m##name##Asset[index]; } \
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data), dAtoi(index)); return false;}\
StringTableEntry get##name##File(const U32& idx){ return m##name##Asset[idx].notNull() ? m##name##Asset[idx]->getImageFile() : ""; }
#define INITPERSISTFIELD_IMAGEASSET_ARRAY(name, arraySize, consoleClass, docs) \
addProtectedField(assetText(name, Asset), TypeImageAssetPtr, Offset(m##name##Asset, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));
#define DEF_IMAGEASSET_ARRAY_BINDS(className,name, max)\
DefineEngineMethod(className, get##name, const char*, (S32 index), , "get name")\
{\
return object->get##name##Asset(index).notNull() ? object->get##name##Asset(index)->getImageFile() : ""; \
}\
DefineEngineMethod(className, get##name##Asset, const char*, (S32 index), , assetText(name, asset reference))\
{\
if(index >= max || index < 0)\
return "";\
return object->_get##name(index); \
}\
DefineEngineMethod(className, set##name, void, (const char* map, S32 index), , assetText(name,assignment. first tries asset then flat file.))\
{\
object->_set##name(StringTable->insert(map), index);\
}
#pragma endregion

View file

@ -51,4 +51,13 @@ public:
DECLARE_CONOBJECT(GuiInspectorTypeImageAssetId);
static void consoleInit();
};
class GuiInspectorTypeImageAssetRef : public GuiInspectorTypeImageAssetPtr
{
typedef GuiInspectorTypeImageAssetPtr Parent;
public:
DECLARE_CONOBJECT(GuiInspectorTypeImageAssetRef);
static void consoleInit();
};
#endif

View file

@ -685,7 +685,7 @@ void GuiInspectorTypeMaterialAssetPtr::setPreviewImage(StringTableEntry assetId)
MaterialAsset* matAsset = AssetDatabase.acquireAsset<MaterialAsset>(assetId);
if (matAsset && matAsset->getMaterialDefinition())
{
mPreviewImage->_setBitmap(matAsset->getMaterialDefinition()->_getDiffuseMap(0));
mPreviewImage->_setBitmap(matAsset->getMaterialDefinition()->getDiffuseMapAssetId(0));
}
}
}

View file

@ -2982,27 +2982,27 @@ Torque::Path AssetImporter::importMaterialAsset(AssetImportObject* assetItem)
if (imageType == ImageAsset::ImageTypes::Albedo || childItem->imageSuffixType.isEmpty())
{
newMat->_setDiffuseMap(assetMapFillInStr,0);
newMat->setDiffuseMap(assetMapFillInStr,0);
}
else if (imageType == ImageAsset::ImageTypes::Normal)
{
newMat->_setNormalMap(assetMapFillInStr, 0);
newMat->setNormalMap(assetMapFillInStr, 0);
}
else if (imageType == ImageAsset::ImageTypes::ORMConfig)
{
newMat->_setORMConfigMap(assetMapFillInStr, 0);
newMat->setORMConfigMap(assetMapFillInStr, 0);
}
else if (imageType == ImageAsset::ImageTypes::Metalness)
{
newMat->_setMetalMap(assetMapFillInStr, 0);
newMat->setMetalMap(assetMapFillInStr, 0);
}
else if (imageType == ImageAsset::ImageTypes::AO)
{
newMat->_setAOMap(assetMapFillInStr, 0);
newMat->setAOMap(assetMapFillInStr, 0);
}
else if (imageType == ImageAsset::ImageTypes::Roughness)
{
newMat->_setRoughMap(assetMapFillInStr, 0);
newMat->setRoughMap(assetMapFillInStr, 0);
hasRoughness = true;
}
}