فهرست منبع

Merge pull request #1114 from Azaezel/alpha41/assetAnalysisAugs

asset load flow work
Brian Roberts 1 سال پیش
والد
کامیت
a8194fdf3a

+ 12 - 5
Engine/source/T3D/assets/ImageAsset.cpp

@@ -125,13 +125,18 @@ ImplementEnumType(ImageAssetType,
 
 EndImplementEnumType;
 
-
+const String ImageAsset::mErrCodeStrings[] =
+{
+   "TooManyMips",
+   "UnKnown"
+};
 //-----------------------------------------------------------------------------
 ImageAsset::ImageAsset() : AssetBase(), mUseMips(true), mIsHDRImage(false), mIsValidImage(false), mImageType(Albedo)
 {
    mImageFileName = StringTable->EmptyString();
    mImagePath = StringTable->EmptyString();
    mLoadedState = AssetErrCode::NotLoaded;
+   mChangeSignal.notify(this, &ImageAsset::onAssetRefresh);
 }
 
 //-----------------------------------------------------------------------------
@@ -202,6 +207,7 @@ U32 ImageAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr<ImageAsse
    {
       //acquire and bind the asset, and return it out
       imageAsset->setAssetId(query.mAssetList[0]);
+      (*imageAsset)->loadImage();
       return (*imageAsset)->mLoadedState;
    }
 }
@@ -234,12 +240,14 @@ U32 ImageAsset::getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* ima
 
    if (imageAsset->notNull())
    {
+      (*imageAsset)->loadImage();
       return (*imageAsset)->mLoadedState;
    }
    else
    {
       if (imageAsset->isNull())
       {
+         (*imageAsset)->loadImage();
          //Well that's bad, loading the fallback failed.
          Con::warnf("ImageAsset::getAssetById - Finding of asset with id %s failed with no fallback asset", assetId);
          return AssetErrCode::Failed;
@@ -248,6 +256,7 @@ U32 ImageAsset::getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* ima
       //handle noshape not being loaded itself
       if ((*imageAsset)->mLoadedState == BadFileReference)
       {
+         (*imageAsset)->loadImage();
          Con::warnf("ImageAsset::getAssetById - Finding of asset with id %s failed, and fallback asset reported error of Bad File Reference.", assetId);
          return AssetErrCode::BadFileReference;
       }
@@ -268,6 +277,7 @@ void ImageAsset::copyTo(SimObject* object)
 
 void ImageAsset::loadImage()
 {
+   if (mLoadedState == AssetErrCode::Ok) return;
    if (mImagePath)
    {
       if (!Torque::FS::IsFile(mImagePath))
@@ -279,7 +289,6 @@ void ImageAsset::loadImage()
 
       mLoadedState = Ok;
       mIsValidImage = true;
-      mChangeSignal.trigger();
       return;
    }
    mLoadedState = BadFileReference;
@@ -292,13 +301,11 @@ void ImageAsset::initializeAsset()
    ResourceManager::get().getChangedSignal().notify(this, &ImageAsset::_onResourceChanged);
 
    mImagePath = getOwned() ? expandAssetFilePath(mImageFileName) : mImagePath;
-   loadImage();
 }
 
 void ImageAsset::onAssetRefresh()
 {
    mImagePath = getOwned() ? expandAssetFilePath(mImageFileName) : mImagePath;
-   loadImage();
 }
 
 void ImageAsset::_onResourceChanged(const Torque::Path& path)
@@ -308,7 +315,7 @@ void ImageAsset::_onResourceChanged(const Torque::Path& path)
 
    refreshAsset();
 
-   //loadImage();
+   onAssetRefresh();
 }
 
 void ImageAsset::setImageFileName(const char* pScriptFile)

+ 17 - 0
Engine/source/T3D/assets/ImageAsset.h

@@ -54,6 +54,7 @@
 class ImageAsset : public AssetBase
 {
    typedef AssetBase Parent;
+   typedef AssetPtr<ImageAsset> ConcreteAssetPtr;
 
 public:
    /// The different types of image use cases
@@ -75,6 +76,22 @@ public:
 
    static StringTableEntry smNoImageAssetFallback;
 
+   enum ImageAssetErrCode
+   {
+      TooManyMips = AssetErrCode::Extended,
+      Extended
+   };
+
+   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 String getAssetErrstrn(U32 errCode)
+   {
+      if (errCode < Parent::Extended) return Parent::getAssetErrstrn(errCode);
+      if (errCode > ImageAssetErrCode::Extended) return "undefined error";
+      return mErrCodeStrings[errCode - Parent::Extended];
+   };
+
 protected:
    StringTableEntry mImageFileName;
    StringTableEntry mImagePath;

+ 7 - 0
Engine/source/T3D/assets/MaterialAsset.cpp

@@ -45,6 +45,13 @@
 
 StringTableEntry MaterialAsset::smNoMaterialAssetFallback = NULL;
 
+const String MaterialAsset::mErrCodeStrings[] =
+{
+   "ScriptLoaded",
+   "DefinitionAlreadyExists",
+   "EmbeddedDefinition",
+   "UnKnown"
+};
 //-----------------------------------------------------------------------------
 
 IMPLEMENT_CONOBJECT(MaterialAsset);

+ 11 - 0
Engine/source/T3D/assets/MaterialAsset.h

@@ -63,6 +63,7 @@
 class MaterialAsset : public AssetBase
 {
    typedef AssetBase Parent;
+   typedef AssetPtr<MaterialAsset> ConcreteAssetPtr;
 
    String                  mShaderGraphFile;
    StringTableEntry        mScriptFile;
@@ -82,6 +83,16 @@ public:
       Extended
    };
 
+   static const String mErrCodeStrings[U32(MaterialAssetErrCode::Extended) - U32(Parent::Extended) + 1];
+   static U32 getAssetErrCode(ConcreteAssetPtr checkAsset) { if (checkAsset) return checkAsset->mLoadedState; else return 0; }
+
+   static String getAssetErrstrn(U32 errCode)
+   {
+      if (errCode < Parent::Extended) return Parent::getAssetErrstrn(errCode);
+      if (errCode > MaterialAssetErrCode::Extended) return "undefined error";
+      return mErrCodeStrings[errCode - Parent::Extended];
+   };
+
 public:
    MaterialAsset();
    virtual ~MaterialAsset();

+ 6 - 0
Engine/source/T3D/assets/ShapeAnimationAsset.cpp

@@ -90,6 +90,12 @@ ConsoleSetType(TypeShapeAnimationAssetPtr)
    Con::warnf("(TypeShapeAnimationAssetPtr) - Cannot set multiple args to a single asset.");
 }
 
+const String ShapeAnimationAsset::mErrCodeStrings[] =
+{
+   "TooManyBones",
+   "UnKnown"
+};
+
 //-----------------------------------------------------------------------------
 
 ShapeAnimationAsset::ShapeAnimationAsset() : 

+ 22 - 1
Engine/source/T3D/assets/ShapeAnimationAsset.h

@@ -44,11 +44,17 @@
 #include "core/resource.h"
 #endif
 
+#ifndef _ASSET_PTR_H_
+#include "assets/assetPtr.h"
+#endif
+
+#include "assetMacroHelpers.h"
+
 //-----------------------------------------------------------------------------
 class ShapeAnimationAsset : public AssetBase
 {
    typedef AssetBase Parent;
-
+   typedef AssetPtr<ShapeAnimationAsset> ConcreteAssetPtr;
 protected:
    StringTableEntry   mFileName;
    StringTableEntry   mFilePath;
@@ -72,6 +78,21 @@ protected:
    Resource<TSShape> mSourceShape;
 
 public:
+   enum ShapeAnimationAssetErrCode
+   {
+      TooManyBones = AssetErrCode::Extended,
+      Extended
+   };
+
+   static const String mErrCodeStrings[U32(ShapeAnimationAssetErrCode::Extended) - U32(Parent::Extended) + 1];
+   static U32 getAssetErrCode(ConcreteAssetPtr checkAsset) { if (checkAsset) return checkAsset->mLoadedState; else return 0; }
+
+   static String getAssetErrstrn(U32 errCode)
+   {
+      if (errCode < Parent::Extended) return Parent::getAssetErrstrn(errCode);
+      if (errCode > ShapeAnimationAssetErrCode::Extended) return "undefined error";
+      return mErrCodeStrings[errCode - Parent::Extended];
+   };
    ShapeAnimationAsset();
    virtual ~ShapeAnimationAsset();
 

+ 6 - 7
Engine/source/T3D/assets/ShapeAsset.cpp

@@ -117,7 +117,7 @@ ConsoleSetType(TypeShapeAssetId)
 
 //-----------------------------------------------------------------------------
 
-const String ShapeAsset::mShapeErrCodeStrings[] =
+const String ShapeAsset::mErrCodeStrings[] =
 {
    "TooManyVerts",
    "TooManyBones",
@@ -224,8 +224,6 @@ void ShapeAsset::initializeAsset()
       String normalPath = String(mFilePath) + "_imposter_normals.dds";
       mNormalImposterPath = StringTable->insert(normalPath.c_str());
    }
-
-   loadShape();
 }
 
 void ShapeAsset::setShapeFile(const char* pShapeFile)
@@ -307,11 +305,13 @@ void ShapeAsset::_onResourceChanged(const Torque::Path &path)
 
    refreshAsset();
 
-   loadShape();
+   onAssetRefresh();
 }
 
 bool ShapeAsset::loadShape()
 {
+   if (mLoadedState == AssetErrCode::Ok) return true;
+
    mMaterialAssets.clear();
    mMaterialAssetIds.clear();
 
@@ -396,7 +396,8 @@ bool ShapeAsset::loadShape()
             //First, we need to make sure the anim asset we depend on for our blend is loaded
             AssetPtr<ShapeAnimationAsset> blendAnimAsset = mAnimationAssets[i]->getBlendAnimationName();
 
-            if (blendAnimAsset.isNull())
+            U32 assetStatus = ShapeAnimationAsset::getAssetErrCode(blendAnimAsset);
+            if (assetStatus != AssetBase::Ok)
             {
                Con::errorf("ShapeAsset::initializeAsset - Unable to acquire reference animation asset %s for asset %s to blend!", mAnimationAssets[i]->getBlendAnimationName(), mAnimationAssets[i]->getAssetName());
                {
@@ -533,8 +534,6 @@ void ShapeAsset::onAssetRefresh(void)
    // Update.
    if(!Platform::isFullPath(mFileName))
       mFilePath = getOwned() ? expandAssetFilePath(mFileName) : mFilePath;
-
-   loadShape();
 }
 
 void ShapeAsset::SplitSequencePathAndName(String& srcPath, String& srcName)

+ 5 - 5
Engine/source/T3D/assets/ShapeAsset.h

@@ -65,6 +65,7 @@
 class ShapeAsset : public AssetBase
 {
    typedef AssetBase Parent;
+   typedef AssetPtr<ShapeAsset> ConcreteAssetPtr;
 
 protected:
    StringTableEntry   mFileName;
@@ -104,15 +105,14 @@ public:
 
    static StringTableEntry smNoShapeAssetFallback;
 
-   static const String mShapeErrCodeStrings[U32(ShapeAssetErrCode::Extended) - U32(Parent::Extended) + 1];
-
-   static U32 getAssetErrCode(AssetPtr<ShapeAsset> shapeAsset) { if (shapeAsset) return shapeAsset->mLoadedState; else return 0; }
+   static const String mErrCodeStrings[U32(ShapeAssetErrCode::Extended) - U32(Parent::Extended) + 1];
+   static U32 getAssetErrCode(ConcreteAssetPtr checkAsset) { if (checkAsset) return checkAsset->mLoadedState; else return 0; }
 
    static String getAssetErrstrn(U32 errCode)
    {
       if (errCode < Parent::Extended) return Parent::getAssetErrstrn(errCode);
       if (errCode > ShapeAssetErrCode::Extended) return "undefined error";
-      return mShapeErrCodeStrings[errCode - Parent::Extended];
+      return mErrCodeStrings[errCode - Parent::Extended];
    };
 
    ShapeAsset();
@@ -136,7 +136,7 @@ public:
 
    TSShape* getShape() { return mShape; }
 
-   Resource<TSShape> getShapeResource() { return mShape; }
+   Resource<TSShape> getShapeResource() { loadShape(); return mShape; }
 
    void SplitSequencePathAndName(String& srcPath, String& srcName);
    StringTableEntry getShapeFileName() { return mFileName; }

+ 12 - 3
Engine/source/T3D/assets/SoundAsset.cpp

@@ -106,6 +106,14 @@ ConsoleSetType(TypeSoundAssetId)
    Con::warnf("(TypeAssetId) - Cannot set multiple args to a single asset.");
 }
 
+const String SoundAsset::mErrCodeStrings[] =
+{
+   "BadProfile",
+   "BadDescription",
+   "BadBufferData",
+   "UnKnown"
+};
+
 //-----------------------------------------------------------------------------
 
 SoundAsset::SoundAsset()
@@ -190,7 +198,7 @@ void SoundAsset::initializeAsset(void)
       return;
 
    mSoundPath = getOwned() ? expandAssetFilePath(mSoundFile) : mSoundPath;
-   loadSound();
+   //loadSound();
 }
 
 void SoundAsset::_onResourceChanged(const Torque::Path &path)
@@ -200,7 +208,7 @@ void SoundAsset::_onResourceChanged(const Torque::Path &path)
 
    refreshAsset();
 
-   loadSound();
+   //loadSound();
 }
 
 void SoundAsset::onAssetRefresh(void)
@@ -210,11 +218,12 @@ void SoundAsset::onAssetRefresh(void)
 
    //Update
    mSoundPath = getOwned() ? expandAssetFilePath(mSoundFile) : mSoundPath;
-   loadSound();
+   //loadSound();
 }
 
 bool SoundAsset::loadSound()
 {
+   if (mLoadedState == AssetErrCode::Ok) return true;
    if (mSoundPath)
    {
       if (!Torque::FS::IsFile(mSoundPath))

+ 19 - 1
Engine/source/T3D/assets/SoundAsset.h

@@ -70,6 +70,7 @@ class SFXResource;
 class SoundAsset : public AssetBase
 {
    typedef AssetBase Parent;
+   typedef AssetPtr<SoundAsset> ConcreteAssetPtr;
 
 protected:
    StringTableEntry        mSoundFile;
@@ -106,6 +107,23 @@ protected:
    SoundAssetChanged mChangeSignal;
 
 public:
+   enum SoundAssetErrCode
+   {
+      BadProfile = AssetErrCode::Extended,
+      BadDescription,
+      BadBufferData,
+      Extended
+   };
+
+   static const String mErrCodeStrings[U32(SoundAssetErrCode::Extended) - U32(Parent::Extended) + 1];
+   static U32 getAssetErrCode(ConcreteAssetPtr checkAsset) { if (checkAsset) return checkAsset->mLoadedState; else return 0; }
+
+   static String getAssetErrstrn(U32 errCode)
+   {
+      if (errCode < Parent::Extended) return Parent::getAssetErrstrn(errCode);
+      if (errCode > SoundAssetErrCode::Extended) return "undefined error";
+      return mErrCodeStrings[errCode - Parent::Extended];
+   };
    SoundAsset();
    virtual ~SoundAsset();
 
@@ -114,7 +132,7 @@ public:
    virtual void copyTo(SimObject* object);
 
    //SFXResource* getSound() { return mSoundResource; }
-   Resource<SFXResource> getSoundResource() { return mSFXProfile.getResource(); }
+   Resource<SFXResource> getSoundResource() { loadSound(); return mSFXProfile.getResource(); }
 
    /// Declare Console Object.
    DECLARE_CONOBJECT(SoundAsset);

+ 4 - 2
Engine/source/T3D/decal/decalData.cpp

@@ -340,9 +340,11 @@ void DecalData::_initMaterial()
 
 void DecalData::_updateMaterial()
 {
-   if(mMaterialAsset.isNull())
+   U32 assetStatus = MaterialAsset::getAssetErrCode(mMaterialAsset);
+   if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
+   {
       return;
-
+   }
    // Only update material instance if we have one allocated.
    if ( matInst )
       _initMaterial();

+ 6 - 2
Engine/source/T3D/groundPlane.cpp

@@ -157,7 +157,8 @@ bool GroundPlane::onAdd()
 
 void GroundPlane::onRemove()
 {
-   if (!mMaterialAsset.isNull())
+   U32 assetStatus = MaterialAsset::getAssetErrCode(mMaterialAsset);
+   if (assetStatus == AssetBase::Ok)
       AssetDatabase.releaseAsset(mMaterialAsset.getAssetId());
 
    //SAFE_DELETE(mMaterialInst);
@@ -593,8 +594,11 @@ void GroundPlane::generateGrid( U32 width, U32 height, F32 squareSize,
 
 void GroundPlane::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
 {
-   if (!mMaterialAsset.isNull() && mMaterialAsset->getAssetId() != MaterialAsset::smNoMaterialAssetFallback)
+   U32 assetStatus = MaterialAsset::getAssetErrCode(mMaterialAsset);
+   if (assetStatus == AssetBase::Ok)
+   {
       usedAssetsList->push_back_unique(mMaterialAsset->getAssetId());
+   }
 
 }
 

+ 4 - 2
Engine/source/T3D/physics/physicsShape.cpp

@@ -241,9 +241,11 @@ void PhysicsShapeData::onRemove()
 
 void PhysicsShapeData::_onResourceChanged( const Torque::Path &path )
 {
-   if (mShapeAsset.isNull())
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
+   if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
+   {
       return;
-
+   }
    if ( path != Path(mShapeAsset->getShapeFilePath()) )
       return;
 

+ 1 - 1
Engine/source/T3D/sfx/sfxEmitter.cpp

@@ -698,7 +698,7 @@ void SFXEmitter::_update()
    // is toggled on a local profile sound.  It makes the
    // editor feel responsive and that things are working.
    if(  gEditingMission &&
-        (mSoundAsset.isNull() || !mSoundAsset->getSfxProfile()) &&
+        (SoundAsset::getAssetErrCode(mSoundAsset) || !mSoundAsset->getSfxProfile()) &&
         mPlayOnAdd && 
         mDirty.test( IsLooping ) )
       prevState = SFXStatusPlaying;

+ 2 - 1
Engine/source/T3D/shapeBase.cpp

@@ -344,7 +344,8 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
    }
 
    S32 i;
-   if (ShapeAsset::getAssetErrCode(mShapeAsset) != ShapeAsset::Failed && ShapeAsset::getAssetErrCode(mShapeAsset) != ShapeAsset::BadFileReference)
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
+   if (assetStatus == AssetBase::Ok|| assetStatus == AssetBase::UsingFallback)
    {
       if (!server && !mShape->preloadMaterialList(mShape.getPath()) && NetConnection::filesWereDownloaded())
          shapeError = true;

+ 6 - 2
Engine/source/T3D/tsStatic.cpp

@@ -391,7 +391,8 @@ bool TSStatic::_createShape()
    mAmbientThread = NULL;
    mShape = NULL;
 
-   if(!mShapeAsset.isNull())
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
+   if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback)
    {
       //Special-case handling, usually because we set noShape
       mShape = mShapeAsset->getShapeResource();
@@ -1628,8 +1629,11 @@ void TSStatic::updateMaterials()
 
 void TSStatic::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
 {
-   if(!mShapeAsset.isNull() && mShapeAsset->getAssetId() != ShapeAsset::smNoShapeAssetFallback)
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
+   if (assetStatus == AssetBase::Ok)
+   {
       usedAssetsList->push_back_unique(mShapeAsset->getAssetId());
+   }
 }
 
 //------------------------------------------------------------------------

+ 2 - 1
Engine/source/afx/afxMagicMissile.cpp

@@ -527,7 +527,8 @@ bool afxMagicMissileData::preload(bool server, String &errorStr)
             Con::errorf(ConsoleLogEntry::General, "afxMagicMissileData::preload: Invalid packet, bad datablockid(lightDesc): %d", lightDescId);   
    }
 
-   if (!mProjectileShapeAsset.isNull()) 
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mProjectileShapeAsset);
+   if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback)
    {
       projectileShape = mProjectileShapeAsset->getShapeResource();
       if (bool(projectileShape) == false)

+ 3 - 0
Engine/source/assets/assetBase.cpp

@@ -58,6 +58,7 @@ const String AssetBase::mErrCodeStrings[] =
    "Failed",
    "Ok",
    "NotLoaded",
+   "Reloading",
    "BadFileReference",
    "InvalidFormat",
    "DependencyNotFound",
@@ -293,6 +294,8 @@ void AssetBase::refreshAsset(void)
    if (mpOwningAssetManager == NULL || !mAssetInitialized)
       return;
 
+   mLoadedState = Reloading;
+
    // Yes, so refresh the asset via the asset manager.
    mpOwningAssetManager->refreshAsset(getAssetId());
 }

+ 2 - 0
Engine/source/assets/assetBase.h

@@ -75,6 +75,7 @@ public:
       Failed,
       Ok,
       NotLoaded,
+      Reloading,
       BadFileReference,
       InvalidFormat,
       DependencyNotFound,
@@ -90,6 +91,7 @@ public:
       return mErrCodeStrings[errCode];
    };
    U32 getStatus() { return mLoadedState; };
+
    AssetBase();
    virtual ~AssetBase();
 

+ 6 - 4
Engine/source/environment/VolumetricFog.cpp

@@ -352,8 +352,8 @@ bool VolumetricFog::setShapeAsset(const StringTableEntry shapeAssetId)
 bool VolumetricFog::LoadShape()
 {
    GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip };
-
-   if (mShapeAsset.isNull())
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
+   if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
    {
       Con::errorf("[VolumetricFog] Failed to load shape asset.");
       return false;
@@ -1217,9 +1217,11 @@ void VolumetricFog::InitTexture()
 {
    mIsTextured = false;
 
-   if (mTextureAsset.isNull())
+   U32 assetStatus = ImageAsset::getAssetErrCode(mTextureAsset);
+   if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
+   {
       return;
-
+   }
    if (!mTexture.isNull())
    {
       mIsTextured = true;

+ 18 - 5
Engine/source/forest/ts/tsForestItemData.cpp

@@ -99,7 +99,12 @@ void TSForestItemData::inspectPostApply()
 
 void TSForestItemData::_onResourceChanged( const Torque::Path &path )
 {
-   if (mShapeAsset.isNull()) return;
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
+   if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
+   {
+      return;
+   }
+
    if ( path != Path(mShapeAsset->getShapeFilePath()) )
       return;
    
@@ -111,8 +116,11 @@ void TSForestItemData::_onResourceChanged( const Torque::Path &path )
 
 void TSForestItemData::_loadShape()
 {
-   if (mShapeAsset.isNull()) return;
-
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
+   if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
+   {
+      return;
+   }
    _setShape(mShapeAssetId);
 
    if ( !(bool)mShape )
@@ -157,7 +165,12 @@ TSShapeInstance* TSForestItemData::_getShapeInstance() const
 
 void TSForestItemData::_checkLastDetail()
 {
-   if (mShapeAsset.isNull()) return;
+   U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
+   if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
+   {
+      return;
+   }
+
    const S32 dl = mShape->mSmallestVisibleDL;
    const TSDetail *detail = &mShape->details[dl];
 
@@ -255,4 +268,4 @@ bool TSForestItemData::render( TSRenderState *rdata, const ForestItem &item ) co
    shapeInst->animate();
    shapeInst->render( *rdata );
    return true;
-}
+}

+ 2 - 1
Engine/source/gui/controls/guiGameListMenuCtrl.cpp

@@ -1758,7 +1758,8 @@ bool GuiGameListMenuProfile::onAdd()
 
    // We can't call enforceConstraints() here because incRefCount initializes
    // some of the things to enforce. Do a basic sanity check here instead.
-   if(mBitmapAsset.isNull())
+   U32 assetStatus = ImageAsset::getAssetErrCode(mBitmapAsset);
+   if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
    {
       Con::errorf( "GuiGameListMenuProfile: %s can't be created without a bitmap. Please add a 'Bitmap' property to the object definition.", getName() );
       return false;

+ 2 - 1
Engine/source/ts/tsShapeConstruct.cpp

@@ -528,7 +528,8 @@ void TSShapeConstructor::_onLoad(TSShape* shape)
 
       AssetPtr<ShapeAnimationAsset> sequenceAsset = mSequenceAssetIds[i];
 
-      if (sequenceAsset.isNull())
+      U32 assetStatus = ShapeAnimationAsset::getAssetErrCode(sequenceAsset);
+      if (assetStatus != AssetBase::Ok)
          continue;
 
       // Split the sequence path from the target sequence name