diff --git a/Engine/source/T3D/assets/ShapeAsset.cpp b/Engine/source/T3D/assets/ShapeAsset.cpp index d0b652851..0c89ae5b1 100644 --- a/Engine/source/T3D/assets/ShapeAsset.cpp +++ b/Engine/source/T3D/assets/ShapeAsset.cpp @@ -119,6 +119,7 @@ ShapeAsset::ShapeAsset() mConstructorFileName = StringTable->EmptyString(); mFilePath = StringTable->EmptyString(); mConstructorFilePath = StringTable->EmptyString(); + mLoadedState = AssetErrCode::NotLoaded; } //----------------------------------------------------------------------------- @@ -264,7 +265,8 @@ bool ShapeAsset::loadShape() if (!mShape) { - Con::errorf("StaticMesh::updateShape : failed to load shape file!"); + Con::errorf("ShapeAsset::loadShape : failed to load shape file!"); + mLoadedState = BadFileReference; return false; //if it failed to load, bail out } @@ -280,8 +282,10 @@ bool ShapeAsset::loadShape() if (!mShape->addSequence(srcPath, srcName, srcName, mAnimationAssets[i]->getStartFrame(), mAnimationAssets[i]->getEndFrame(), mAnimationAssets[i]->getPadRotation(), mAnimationAssets[i]->getPadTransforms())) + { + mLoadedState = MissingAnimatons; return false; - + } if (mAnimationAssets[i]->isBlend()) hasBlends = true; } @@ -300,14 +304,20 @@ bool ShapeAsset::loadShape() if (blendAnimAsset.isNull()) { Con::errorf("ShapeAsset::initializeAsset - Unable to acquire reference animation asset %s for asset %s to blend!", mAnimationAssets[i]->getBlendAnimationName(), mAnimationAssets[i]->getAssetName()); - return false; + { + mLoadedState = MissingAnimatons; + return false; + } } String refAnimName = blendAnimAsset->getAnimationName(); if (!mShape->setSequenceBlend(mAnimationAssets[i]->getAnimationName(), true, blendAnimAsset->getAnimationName(), mAnimationAssets[i]->getBlendFrame())) { Con::errorf("ShapeAnimationAsset::initializeAsset - Unable to set animation clip %s for asset %s to blend!", mAnimationAssets[i]->getAnimationName(), mAnimationAssets[i]->getAssetName()); - return false; + { + mLoadedState = MissingAnimatons; + return false; + } } } } @@ -315,6 +325,7 @@ bool ShapeAsset::loadShape() mChangeSignal.trigger(); + mLoadedState = Ok; return true; } @@ -410,21 +421,21 @@ StringTableEntry ShapeAsset::getAssetIdByFilename(StringTableEntry fileName) return shapeAssetId; } -bool ShapeAsset::getAssetById(StringTableEntry assetId, AssetPtr* shapeAsset) +U32 ShapeAsset::getAssetById(StringTableEntry assetId, AssetPtr* shapeAsset) { (*shapeAsset) = assetId; - if (!shapeAsset->isNull()) - return true; + if ((*shapeAsset)) + return (*shapeAsset)->mLoadedState; //Didn't work, so have us fall back to a placeholder asset StringTableEntry noShapeId = StringTable->insert("Core_Rendering:noshape"); shapeAsset->setAssetId(noShapeId); + (*shapeAsset)->mLoadedState = AssetErrCode::UsingFallback; + if (shapeAsset->notNull()) + return AssetErrCode::UsingFallback; - if (!shapeAsset->isNull()) - return true; - - return false; + return AssetErrCode::Failed; } //------------------------------------------------------------------------------ @@ -503,6 +514,7 @@ DefineEngineMethod(ShapeAsset, getAnimation, ShapeAnimationAsset*, (S32 index), // GuiInspectorTypeAssetId //----------------------------------------------------------------------------- +#ifdef TORQUE_TOOLS IMPLEMENT_CONOBJECT(GuiInspectorTypeShapeAssetPtr); ConsoleDocClass(GuiInspectorTypeShapeAssetPtr, @@ -596,6 +608,8 @@ void GuiInspectorTypeShapeAssetId::consoleInit() ConsoleBaseType::getType(TypeShapeAssetId)->setInspectorFieldType("GuiInspectorTypeShapeAssetId"); } +#endif + DefineEngineMethod(ShapeAsset, getShapeFile, const char*, (), , "Creates a new script asset using the targetFilePath.\n" "@return The bool result of calling exec") diff --git a/Engine/source/T3D/assets/ShapeAsset.h b/Engine/source/T3D/assets/ShapeAsset.h index 65e0a4ca9..3843379e7 100644 --- a/Engine/source/T3D/assets/ShapeAsset.h +++ b/Engine/source/T3D/assets/ShapeAsset.h @@ -54,7 +54,9 @@ #include "ShapeAnimationAsset.h" #endif +#ifdef TORQUE_TOOLS #include "gui/editor/guiInspectorTypes.h" +#endif //----------------------------------------------------------------------------- class ShapeAsset : public AssetBase @@ -81,6 +83,13 @@ protected: ShapeAssetChanged mChangeSignal; public: + enum ShapeAssetErrCode + { + TooManyVerts = AssetErrCode::Extended, + TooManyBones, + MissingAnimatons + }; + ShapeAsset(); virtual ~ShapeAsset(); @@ -96,6 +105,7 @@ public: DECLARE_CONOBJECT(ShapeAsset); bool loadShape(); + U32 mLoadedState; TSShape* getShape() { return mShape; } @@ -138,8 +148,9 @@ public: inline StringTableEntry getShapeConstructorFilePath(void) const { return mConstructorFilePath; }; static bool getAssetByFilename(StringTableEntry fileName, AssetPtr* shapeAsset); + static StringTableEntry getAssetIdByFilename(StringTableEntry fileName); - static bool getAssetById(StringTableEntry assetId, AssetPtr* shapeAsset); + static U32 getAssetById(StringTableEntry assetId, AssetPtr* shapeAsset); static StringTableEntry getNoShapeAssetId() { return StringTable->insert("Core_Rendering:noshape"); } @@ -154,6 +165,7 @@ protected: }; +#ifdef TORQUE_TOOLS DefineConsoleType(TypeShapeAssetPtr, S32) DefineConsoleType(TypeShapeAssetId, String) @@ -182,6 +194,72 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeShapeAssetId); static void consoleInit(); }; +#endif + +#define assetText(x,suff) std::string(std::string(#x) + std::string(#suff)).c_str() + +#define initShapeAsset(name) m##name##Filename = StringTable->EmptyString(); m##name##AssetId = StringTable->EmptyString(); m##name##Asset = NULL; +#define bindShapeAsset(name) if (m##name##AssetId != StringTable->EmptyString()) m##name##Asset = m##name##AssetId; + +#define scriptBindShapeAsset(name, consoleClass, docs) addProtectedField(assetText(name, File), TypeShapeFilename, Offset(m##name##Filename, consoleClass), consoleClass::_set##name##Filename, & defaultProtectedGetFn, assetText(name, docs)); \ + addProtectedField(assetText(name, Asset), TypeShapeAssetId, Offset(m##name##AssetId, consoleClass), consoleClass::_set##name##Asset, & defaultProtectedGetFn, assetText(name, asset reference.)); + +#define DECLARE_SHAPEASSET(className,name) protected: \ + StringTableEntry m##name##Filename;\ + StringTableEntry m##name##AssetId;\ + AssetPtr m##name##Asset;\ + public: \ + const StringTableEntry& get##name() const { return m##name##Filename; }\ + void set##name(FileName _in) { m##name##Filename = _in; }\ + const AssetPtr & get##name##Asset() const { return m##name##Asset; }\ + void set##name##Asset(AssetPtr_in) { m##name##Asset = _in; }\ +static bool _set##name##Filename(void* obj, const char* index, const char* data)\ +{\ + className* shape = static_cast(obj);\ + \ + StringTableEntry assetId = ShapeAsset::getAssetIdByFilename(StringTable->insert(data));\ + if (assetId != StringTable->EmptyString())\ + {\ + if (shape->_set##name##Asset(obj, index, assetId))\ + {\ + if (assetId == StringTable->insert("Core_Rendering:noShape"))\ + {\ + shape->m##name##Filename = data;\ + shape->m##name##AssetId = StringTable->EmptyString();\ + \ + return true;\ + }\ + else\ + {\ + shape->m##name##AssetId = assetId;\ + shape->m##name##Filename = StringTable->EmptyString();\ + \ + return false;\ + }\ + }\ + }\ + else\ + {\ + shape->m##name##Asset = StringTable->EmptyString();\ + }\ + \ + return true;\ +}\ +\ +static bool _set##name##Asset(void* obj, const char* index, const char* data)\ +{\ + className* shape = static_cast(obj);\ + shape->m##name##AssetId = StringTable->insert(data);\ + if (ShapeAsset::getAssetById(shape->m##name##AssetId, &shape->m##name##Asset))\ + {\ + if (shape->m##name##Asset.getAssetId() != StringTable->insert("Core_Rendering:noShape"))\ + shape->m##name##Filename = StringTable->EmptyString();\ + \ + shape->setMaskBits(-1);\ + return true;\ + }\ + return false;\ +} #endif diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 6f70e2760..29c5b8b8c 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -361,20 +361,15 @@ bool ShapeBaseData::preload(bool server, String &errorStr) } //Legacy catch - if (shapeAssetId == StringTable->EmptyString() && shapeName != StringTable->EmptyString()) + if (shapeName != StringTable->EmptyString()) { - StringTableEntry assetId = ShapeAsset::getAssetIdByFilename(shapeName); - if (assetId != StringTable->EmptyString()) - { - shapeAssetId = assetId; - } + shapeAssetId = ShapeAsset::getAssetIdByFilename(shapeName); } - - if (ShapeAsset::getAssetById(shapeAssetId, &shapeAsset)) + U32 assetState = ShapeAsset::getAssetById(shapeAssetId, &shapeAsset); + if (AssetErrCode::Failed != assetState) { - //Special exception case. If we've defaulted to the 'no shape' mesh, don't save it out, we'll retain the original ids/paths so it doesn't break - //the TSStatic - if (shapeAsset.getAssetId() != StringTable->insert("Core_Rendering:noshape")) + //only clear the legacy direct file reference if everything checks out fully + if (assetState == AssetErrCode::Ok) { shapeName = StringTable->EmptyString(); } diff --git a/Engine/source/assets/assetBase.h b/Engine/source/assets/assetBase.h index f127c83cc..cdffbc14e 100644 --- a/Engine/source/assets/assetBase.h +++ b/Engine/source/assets/assetBase.h @@ -56,6 +56,19 @@ extern StringTableEntry assetAutoUnloadField; //----------------------------------------------------------------------------- +enum AssetErrCode +{ + Failed, + Ok, + NotLoaded, + BadFileReference, + InvalidFormat, + DependencyNotFound, + FileTooLarge, + UsingFallback, + Extended +}; + class AssetBase : public SimObject { friend class AssetManager;