diff --git a/Engine/source/T3D/assets/ImageAsset.cpp b/Engine/source/T3D/assets/ImageAsset.cpp index 7e0cf1952..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(); } @@ -345,6 +347,11 @@ void ImageAsset::initializeAsset(void) return; mImageFile = expandAssetFilePath(mImageFile); + + if (getOwned()) + Torque::FS::AddChangeNotification(mImageFile, this, &ImageAsset::_onResourceChanged); + + populateImage(); } void ImageAsset::onAssetRefresh(void) @@ -356,6 +363,8 @@ void ImageAsset::onAssetRefresh(void) // Call parent. Parent::onAssetRefresh(); + populateImage(); + } //------------------------------------------------------------------------------ @@ -385,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); @@ -395,46 +406,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 +646,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 082ddb04f..97623f5a4 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) { @@ -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: @@ -233,17 +233,20 @@ 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) \ return; \ - if(_in == NULL || _in == StringTable->EmptyString()) \ + if(get##name##File() == _in) \ + return; \ + if(_in == NULL || _in == StringTable->EmptyString() || _in == "") \ { \ m##name##Asset = NULL; \ + m##name##File = ""; \ return; \ } \ if(!AssetDatabase.isDeclaredAsset(_in)) \ @@ -271,10 +274,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,17 +290,20 @@ 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) \ return; \ - if(_in == NULL || _in == StringTable->EmptyString()) \ + if(get##name##File() == _in) \ + return; \ + if(_in == NULL || _in == StringTable->EmptyString() || _in == "") \ { \ m##name##Asset = NULL; \ + m##name##File = ""; \ setMaskBits(mask); \ return; \ } \ @@ -324,10 +332,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,22 +349,25 @@ 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) \ return; \ - if(_in == NULL || _in == StringTable->EmptyString()) \ + if(get##name##File(index) == _in) \ + return; \ + if(_in == NULL || _in == StringTable->EmptyString() || _in == "") \ { \ m##name##Asset[index] = NULL; \ + m##name##File[index] = ""; \ return; \ } \ if(!AssetDatabase.isDeclaredAsset(_in)) \ @@ -382,10 +395,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,17 +412,20 @@ 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) \ return; \ - if(_in == NULL || _in == StringTable->EmptyString()) \ + if(get##name##File(index) == _in) \ + return; \ + if(_in == NULL || _in == StringTable->EmptyString() || _in == "") \ { \ m##name##Asset[index] = NULL; \ + m##name##File[index] = ""; \ setMaskBits(mask); \ return; \ } \ @@ -436,10 +454,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/T3D/assets/ShapeAsset.cpp b/Engine/source/T3D/assets/ShapeAsset.cpp index ff27573cc..0ec856cde 100644 --- a/Engine/source/T3D/assets/ShapeAsset.cpp +++ b/Engine/source/T3D/assets/ShapeAsset.cpp @@ -60,12 +60,20 @@ StringTableEntry ShapeAsset::smNoShapeAssetFallback = NULL; IMPLEMENT_CONOBJECT(ShapeAsset); -ConsoleType(assetIdString, TypeShapeAssetPtr, String, ASSET_ID_FIELD_PREFIX) + +//----------------------------------------------------------------------------- +// REFACTOR +//----------------------------------------------------------------------------- + +IMPLEMENT_STRUCT(AssetPtr, AssetPtrShapeAsset, , "") +END_IMPLEMENT_STRUCT + +ConsoleType(ShapeAssetPtr, TypeShapeAssetPtr, AssetPtr, ASSET_ID_FIELD_PREFIX) + ConsoleGetType(TypeShapeAssetPtr) { // Fetch asset Id. - //return *((StringTableEntry*)dptr); return (*((AssetPtr*)dptr)).getAssetId(); } @@ -77,17 +85,24 @@ ConsoleSetType(TypeShapeAssetPtr) // Yes, so fetch field value. const char* pFieldValue = argv[0]; - // Fetch asset Id. - StringTableEntry* assetId = (StringTableEntry*)(dptr); + // Fetch asset pointer. + AssetPtr* pAssetPtr = dynamic_cast*>((AssetPtrBase*)(dptr)); - // Update asset value. - *assetId = StringTable->insert(pFieldValue); + // Is the asset pointer the correct type? + if (pAssetPtr == NULL) + { + Con::warnf("(TypeShapeAssetPtr) - Failed to set asset Id '%d'.", pFieldValue); + return; + } + + // Set asset. + pAssetPtr->setAssetId(pFieldValue); return; } // Warn. - Con::warnf("(TypeAssetId) - Cannot set multiple args to a single asset."); + Con::warnf("(TypeShapeAssetPtr) - Cannot set multiple args to a single asset."); } //----------------------------------------------------------------------------- @@ -115,6 +130,8 @@ ConsoleSetType(TypeShapeAssetId) Con::warnf("(TypeAssetId) - Cannot set multiple args to a single asset."); } +//----------------------------------------------------------------------------- +// REFACTOR END //----------------------------------------------------------------------------- const String ShapeAsset::mErrCodeStrings[] = @@ -128,15 +145,11 @@ const String ShapeAsset::mErrCodeStrings[] = ShapeAsset::ShapeAsset() { - mFileName = StringTable->EmptyString(); + mShapeFile = StringTable->EmptyString(); mConstructorFileName = StringTable->EmptyString(); - mFilePath = StringTable->EmptyString(); - mConstructorFilePath = StringTable->EmptyString(); mDiffuseImposterFileName = StringTable->EmptyString(); - mDiffuseImposterPath = StringTable->EmptyString(); mNormalImposterFileName = StringTable->EmptyString(); - mNormalImposterPath = StringTable->EmptyString(); mLoadedState = AssetErrCode::NotLoaded; @@ -169,7 +182,7 @@ void ShapeAsset::initPersistFields() // Call parent. Parent::initPersistFields(); - addProtectedField("fileName", TypeAssetLooseFilePath, Offset(mFileName, ShapeAsset), + addProtectedField("fileName", TypeAssetLooseFilePath, Offset(mShapeFile, ShapeAsset), &setShapeFile, &getShapeFile, "Path to the shape file we want to render"); addProtectedField("constuctorFileName", TypeAssetLooseFilePath, Offset(mConstructorFileName, ShapeAsset), &setShapeConstructorFile, &getShapeConstructorFile, "Path to the shape file we want to render"); @@ -200,29 +213,31 @@ void ShapeAsset::initializeAsset() // Call parent. Parent::initializeAsset(); - if (mFileName == StringTable->EmptyString()) + if (mShapeFile == StringTable->EmptyString()) return; ResourceManager::get().getChangedSignal().notify(this, &ShapeAsset::_onResourceChanged); //Ensure our path is expando'd if it isn't already - mFilePath = getOwned() ? expandAssetFilePath(mFileName) : mFilePath; + mShapeFile = getOwned() ? expandAssetFilePath(mShapeFile) : mShapeFile; - mConstructorFilePath = getOwned() ? expandAssetFilePath(mConstructorFileName) : mConstructorFilePath; - if (!Torque::FS::IsFile(mConstructorFilePath)) - Con::errorf("ShapeAsset::initializeAsset (%s) could not find %s!", getAssetName(), mConstructorFilePath); - mDiffuseImposterPath = getOwned() ? expandAssetFilePath(mDiffuseImposterFileName) : mDiffuseImposterFileName; - if (mDiffuseImposterPath == StringTable->EmptyString()) + mConstructorFileName = getOwned() ? expandAssetFilePath(mConstructorFileName) : mConstructorFileName; + if (!Torque::FS::IsFile(mConstructorFileName)) + Con::errorf("ShapeAsset::initializeAsset (%s) could not find %s!", getAssetName(), mConstructorFileName); + + + mDiffuseImposterFileName = getOwned() ? expandAssetFilePath(mDiffuseImposterFileName) : mDiffuseImposterFileName; + if (mDiffuseImposterFileName == StringTable->EmptyString()) { - String diffusePath = String(mFilePath) + "_imposter.dds"; - mDiffuseImposterPath = StringTable->insert(diffusePath.c_str()); + String diffusePath = String(mShapeFile) + "_imposter.dds"; + mDiffuseImposterFileName = StringTable->insert(diffusePath.c_str()); } - mNormalImposterPath = getOwned() ? expandAssetFilePath(mNormalImposterFileName) : mNormalImposterFileName; - if (mNormalImposterPath == StringTable->EmptyString()) + mNormalImposterFileName = getOwned() ? expandAssetFilePath(mNormalImposterFileName) : mNormalImposterFileName; + if (mNormalImposterFileName == StringTable->EmptyString()) { - String normalPath = String(mFilePath) + "_imposter_normals.dds"; - mNormalImposterPath = StringTable->insert(normalPath.c_str()); + String normalPath = String(mShapeFile) + "_imposter_normals.dds"; + mNormalImposterFileName = StringTable->insert(normalPath.c_str()); } } @@ -235,10 +250,10 @@ void ShapeAsset::setShapeFile(const char* pShapeFile) pShapeFile = StringTable->insert(pShapeFile, true); // Ignore no change, - if (pShapeFile == mFileName) + if (pShapeFile == mShapeFile) return; - mFileName = getOwned() ? expandAssetFilePath(pShapeFile) : pShapeFile; + mShapeFile = getOwned() ? expandAssetFilePath(pShapeFile) : pShapeFile; // Refresh the asset. refreshAsset(); @@ -300,7 +315,7 @@ void ShapeAsset::setNormalImposterFile(const char* pImageFile) void ShapeAsset::_onResourceChanged(const Torque::Path &path) { - if (path != Torque::Path(mFilePath) ) + if (path != Torque::Path(mShapeFile) ) return; refreshAsset(); @@ -349,17 +364,17 @@ U32 ShapeAsset::load() } } - mShape = ResourceManager::get().load(mFilePath); + mShape = ResourceManager::get().load(mShapeFile); if (!mShape) { - Con::errorf("ShapeAsset::loadShape : failed to load shape file %s (%s)!", getAssetName(), mFilePath); + Con::errorf("ShapeAsset::loadShape : failed to load shape file %s (%s)!", getAssetName(), mShapeFile); mLoadedState = BadFileReference; return mLoadedState; //if it failed to load, bail out } // Construct billboards if not done already if (GFXDevice::devicePresent()) - mShape->setupBillboardDetails(mFilePath, mDiffuseImposterPath, mNormalImposterPath); + mShape->setupBillboardDetails(mShapeFile, mDiffuseImposterFileName, mNormalImposterFileName); //If they exist, grab our imposters here and bind them to our shapeAsset @@ -419,8 +434,6 @@ U32 ShapeAsset::load() mLoadedState = Ok; - mChangeSignal.trigger(); - return mLoadedState; } @@ -478,7 +491,38 @@ StringTableEntry ShapeAsset::getAssetIdByFilename(StringTableEntry fileName) } else { - AssetPtr shapeAsset = shapeAssetId; //ensures the fallback is loaded + foundAssetcount = AssetDatabase.findAssetType(&query, "ShapeAsset"); + if (foundAssetcount != 0) + { + // loop all image assets and see if we can find one + // using the same image file/named target. + for (auto shapeAsset : query.mAssetList) + { + AssetPtr temp = shapeAsset; + if (temp.notNull()) + { + if (temp->getShapeFile() == fileName) + { + return shapeAsset; + } + else + { + Torque::Path temp1 = temp->getShapeFile(); + Torque::Path temp2 = fileName; + + if (temp1.getPath() == temp2.getPath() && temp1.getFileName() == temp2.getFileName()) + { + return shapeAsset; + } + } + + } + } + } + else + { + AssetPtr shapeAsset = shapeAssetId; //ensures the fallback is loaded + } } return shapeAssetId; @@ -527,16 +571,43 @@ void ShapeAsset::copyTo(SimObject* object) void ShapeAsset::onAssetRefresh(void) { - if (mFileName == StringTable->EmptyString()) + // Ignore if not yet added to the sim. + if (!isProperlyAdded()) return; - // Update. - if(!Platform::isFullPath(mFileName)) - mFilePath = getOwned() ? expandAssetFilePath(mFileName) : mFilePath; + if (mShapeFile == StringTable->EmptyString()) + return; + + // Call parent. + Parent::onAssetRefresh(); load(); } +void ShapeAsset::onTamlPreWrite(void) +{ + // Call parent. + Parent::onTamlPreWrite(); + + // ensure paths are collapsed. + mShapeFile = collapseAssetFilePath(mShapeFile); + mConstructorFileName = collapseAssetFilePath(mConstructorFileName); + mDiffuseImposterFileName = collapseAssetFilePath(mDiffuseImposterFileName); + mNormalImposterFileName = collapseAssetFilePath(mNormalImposterFileName); +} + +void ShapeAsset::onTamlPostWrite(void) +{ + // Call parent. + Parent::onTamlPostWrite(); + + // ensure paths are expanded. + mShapeFile = expandAssetFilePath(mShapeFile); + mConstructorFileName = expandAssetFilePath(mConstructorFileName); + mDiffuseImposterFileName = expandAssetFilePath(mDiffuseImposterFileName); + mNormalImposterFileName = expandAssetFilePath(mNormalImposterFileName); +} + void ShapeAsset::SplitSequencePathAndName(String& srcPath, String& srcName) { srcName = ""; @@ -626,7 +697,7 @@ const char* ShapeAsset::generateCachedPreviewImage(S32 resolution, String overri delete imposterCap; delete shape; - String dumpPath = String(mFilePath) + ".png"; + String dumpPath = String(mShapeFile) + ".png"; char* returnBuffer = Con::getReturnBuffer(128); dSprintf(returnBuffer, 128, "%s", dumpPath.c_str()); @@ -670,14 +741,14 @@ DefineEngineMethod(ShapeAsset, getShapePath, const char*, (), , "Gets the shape's file path\n" "@return The filename of the shape file") { - return object->getShapeFilePath(); + return object->getShapeFile(); } DefineEngineMethod(ShapeAsset, getShapeConstructorFilePath, const char*, (), , "Gets the shape's constructor file.\n" "@return The filename of the shape constructor file") { - return object->getShapeConstructorFilePath(); + return object->getShapeConstructorFile(); } DefineEngineMethod(ShapeAsset, getStatusString, String, (), , "get status string")\ @@ -913,5 +984,4 @@ void GuiInspectorTypeShapeAssetId::consoleInit() ConsoleBaseType::getType(TypeShapeAssetId)->setInspectorFieldType("GuiInspectorTypeShapeAssetId"); } - #endif diff --git a/Engine/source/T3D/assets/ShapeAsset.h b/Engine/source/T3D/assets/ShapeAsset.h index 2d186346d..150f60b80 100644 --- a/Engine/source/T3D/assets/ShapeAsset.h +++ b/Engine/source/T3D/assets/ShapeAsset.h @@ -67,33 +67,6 @@ class ShapeAsset : public AssetBase typedef AssetBase Parent; typedef AssetPtr ConcreteAssetPtr; -protected: - StringTableEntry mFileName; - StringTableEntry mConstructorFileName; - StringTableEntry mFilePath; - StringTableEntry mConstructorFilePath; - Resource mShape; - - StringTableEntry mDiffuseImposterFileName; - StringTableEntry mDiffuseImposterPath; - - StringTableEntry mNormalImposterFileName; - StringTableEntry mNormalImposterPath; - - //Material assets we're dependent on and use - Vector mMaterialAssetIds; - Vector> mMaterialAssets; - - //Animation assets we're dependent on and use - Vector mAnimationAssetIds; - Vector> mAnimationAssets; - - typedef Signal ShapeAssetChanged; - ShapeAssetChanged mChangeSignal; - - typedef Signal ShapeAssetArrayChanged; - ShapeAssetArrayChanged mChangeArraySignal; - public: enum ShapeAssetErrCode { @@ -115,6 +88,23 @@ public: return mErrCodeStrings[errCode - Parent::Extended]; }; +private: + StringTableEntry mShapeFile; + StringTableEntry mConstructorFileName; + StringTableEntry mDiffuseImposterFileName; + StringTableEntry mNormalImposterFileName; + + //Material assets we're dependent on and use + Vector mMaterialAssetIds; + Vector> mMaterialAssets; + + //Animation assets we're dependent on and use + Vector mAnimationAssetIds; + Vector> mAnimationAssets; + + Resource mShape; +public: + ShapeAsset(); virtual ~ShapeAsset(); @@ -127,8 +117,6 @@ public: virtual void setDataField(StringTableEntry slotName, StringTableEntry array, StringTableEntry value); - void initializeAsset() override; - /// Declare Console Object. DECLARE_CONOBJECT(ShapeAsset); @@ -139,10 +127,8 @@ public: Resource getShapeResource() { load(); return mShape; } void SplitSequencePathAndName(String& srcPath, String& srcName); - StringTableEntry getShapeFileName() { return mFileName; } - StringTableEntry getShapePath() { return mFilePath; } - U32 getShapeFilenameHash() { return _StringTable::hashString(mFilePath); } + U32 getShapeFilenameHash() { return _StringTable::hashString(mShapeFile); } Vector> getMaterialAssets() { return mMaterialAssets; } @@ -164,26 +150,18 @@ public: void _onResourceChanged(const Torque::Path& path); - ShapeAssetChanged& getChangedSignal() { return mChangeSignal; } - ShapeAssetArrayChanged& getChangedArraySignal() { return mChangeArraySignal; } - void setShapeFile(const char* pScriptFile); - inline StringTableEntry getShapeFile(void) const { return mFileName; }; + inline StringTableEntry getShapeFile(void) const { return mShapeFile; }; void setShapeConstructorFile(const char* pScriptFile); inline StringTableEntry getShapeConstructorFile(void) const { return mConstructorFileName; }; - inline StringTableEntry getShapeFilePath(void) const { return mFilePath; }; - inline StringTableEntry getShapeConstructorFilePath(void) const { return mConstructorFilePath; }; - //Imposter images void setDiffuseImposterFile(const char* pImageFile); inline StringTableEntry getDiffuseImposterFile(void) const { return mDiffuseImposterFileName; }; - inline StringTableEntry getDiffuseImposterFilePath(void) const { return mDiffuseImposterPath; }; void setNormalImposterFile(const char* pImageFile); inline StringTableEntry getNormalImposterFile(void) const { return mNormalImposterFileName; }; - inline StringTableEntry getNormalImposterFilePath(void) const { return mNormalImposterPath; }; static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr* shapeAsset); @@ -195,23 +173,34 @@ public: #endif protected: - void onAssetRefresh(void) override; + // Asset Base callback + void initializeAsset(void) override; + void onAssetRefresh(void) override; + /// Taml callbacks. + void onTamlPreWrite(void) override; + void onTamlPostWrite(void) override; + +protected: static bool setShapeFile(void* obj, StringTableEntry index, StringTableEntry data) { static_cast(obj)->setShapeFile(data); return false; } static const char* getShapeFile(void* obj, const char* data) { return static_cast(obj)->getShapeFile(); } + static bool writeShapeFile(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getShapeFile() != StringTable->EmptyString(); } static bool setShapeConstructorFile(void* obj, const char* index, const char* data) { static_cast(obj)->setShapeConstructorFile(data); return false; } static const char* getShapeConstructorFile(void* obj, const char* data) { return static_cast(obj)->getShapeConstructorFile(); } static bool setDiffuseImposterFile(void* obj, StringTableEntry index, StringTableEntry data) { static_cast(obj)->setDiffuseImposterFile(data); return false; } static const char* getDiffuseImposterFile(void* obj, const char* data) { return static_cast(obj)->getDiffuseImposterFile(); } + static bool setNormalImposterFile(void* obj, StringTableEntry index, StringTableEntry data) { static_cast(obj)->setNormalImposterFile(data); return false; } static const char* getNormalImposterFile(void* obj, const char* data) { return static_cast(obj)->getNormalImposterFile(); } }; -DefineConsoleType(TypeShapeAssetPtr, S32) DefineConsoleType(TypeShapeAssetId, String) +DECLARE_STRUCT(AssetPtr) +DefineConsoleType(TypeShapeAssetPtr, AssetPtr) + #ifdef TORQUE_TOOLS //----------------------------------------------------------------------------- // TypeAssetId GuiInspectorField Class @@ -246,251 +235,256 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeShapeAssetId); static void consoleInit(); }; + #endif -#pragma region Singular Asset Macros +//----------------------------------------------------------------------------- +// REFACTOR +//----------------------------------------------------------------------------- -#define DECLARE_SHAPEASSET(className,name,changeFunc) public: \ - Resourcem##name;\ - StringTableEntry m##name##Name; \ - StringTableEntry m##name##AssetId;\ - AssetPtr m##name##Asset;\ -public: \ - const StringTableEntry get##name##File() const { return StringTable->insert(m##name##Name); }\ - void set##name##Name(const FileName &_in) { m##name##Name = _in;}\ - const AssetPtr & get##name##Asset() const { return m##name##Asset; }\ - void set##name##Asset(const AssetPtr &_in) { m##name##Asset = _in;}\ - \ - bool _set##name(StringTableEntry _in)\ - {\ - if(m##name##AssetId != _in || m##name##Name != _in)\ - {\ - if (m##name##Asset.notNull())\ - {\ - m##name##Asset->getChangedSignal().remove(this, &className::changeFunc);\ - }\ - if (_in == NULL || _in == StringTable->EmptyString())\ - {\ - m##name##Name = StringTable->EmptyString();\ - m##name##AssetId = StringTable->EmptyString();\ - m##name##Asset = NULL;\ - m##name = NULL;\ - return true;\ - }\ - \ - if (AssetDatabase.isDeclaredAsset(_in))\ - {\ - m##name##AssetId = _in;\ - \ - U32 assetState = ShapeAsset::getAssetById(m##name##AssetId, &m##name##Asset);\ - \ - if (ShapeAsset::Ok == assetState)\ - {\ - m##name##Name = StringTable->EmptyString();\ - }\ - }\ - else\ - {\ - StringTableEntry assetId = ShapeAsset::getAssetIdByFilename(_in);\ - if (assetId != StringTable->EmptyString())\ - {\ - m##name##AssetId = assetId;\ - if (ShapeAsset::getAssetById(m##name##AssetId, &m##name##Asset) == ShapeAsset::Ok)\ - {\ - m##name##Name = StringTable->EmptyString();\ - }\ - }\ - else\ - {\ - m##name##Name = _in;\ - m##name##AssetId = StringTable->EmptyString();\ - m##name##Asset = NULL;\ - }\ - }\ - }\ - if (get##name() != StringTable->EmptyString() && m##name##Asset.notNull())\ - {\ - m##name = m##name##Asset->getShapeResource();\ - \ - m##name##Asset->getChangedSignal().notify(this, &className::changeFunc);\ - }\ - else\ - {\ - m##name = NULL;\ - }\ - \ - if(get##name() == StringTable->EmptyString())\ - return true;\ - \ - if (m##name##Asset.notNull() && m##name##Asset->getStatus() != ShapeAsset::Ok)\ - {\ - Con::errorf("%s(%s)::_set%s() - shape asset failure \"%s\" due to [%s]", macroText(className), getName(), macroText(name), _in, ShapeAsset::getAssetErrstrn(m##name##Asset->getStatus()).c_str());\ - return false; \ - }\ - else if (!m##name)\ - {\ - Con::errorf("%s(%s)::_set%s() - Couldn't load shape \"%s\"", macroText(className), getName(), macroText(name), _in);\ - return false;\ - }\ - return true;\ - }\ - \ - const StringTableEntry get##name() const\ - {\ - if (m##name##Asset && (m##name##Asset->getShapePath() != StringTable->EmptyString()))\ - return m##name##Asset->getShapePath();\ - else if (m##name##AssetId != StringTable->EmptyString())\ - return m##name##AssetId;\ - else if (m##name##Name != StringTable->EmptyString())\ - return m##name##Name;\ - else\ - return StringTable->EmptyString();\ - }\ - Resource get##name##Resource() \ - {\ - return m##name;\ - }\ - bool is##name##Valid() {return (get##name() != StringTable->EmptyString() && m##name##Asset->getStatus() == AssetBase::Ok); } +#pragma region Refactor Asset Macros -#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS +#define DECLARE_SHAPEASSET_REFACTOR(className, name) \ +private: \ + AssetPtr 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 || _in == StringTable->EmptyString() || _in == "") \ + { \ + m##name##Asset = NULL; \ + m##name##File = ""; \ + return; \ + } \ + if (!AssetDatabase.isDeclaredAsset(_in)) \ + { \ + StringTableEntry shapeAssetId = StringTable->EmptyString(); \ + AssetQuery query; \ + S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \ + if (foundAssetcount != 0) \ + { \ + shapeAssetId = query.mAssetList[0]; \ + } \ + else if (Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \ + { \ + shapeAssetId = ShapeAsset::getAssetIdByFilename(_in); \ + if (shapeAssetId == ShapeAsset::smNoShapeAssetFallback) \ + { \ + ShapeAsset* privateShape = new ShapeAsset(); \ + privateShape->setShapeFile(_in); \ + shapeAssetId = AssetDatabase.addPrivateAsset(privateShape); \ + } \ + } \ + else \ + { \ + Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \ + shapeAssetId = ShapeAsset::smNoShapeAssetFallback; \ + } \ + m##name##Asset = shapeAssetId; \ + m##name##File = _in; \ + } \ + else \ + { \ + m##name##Asset = _in; \ + m##name##File = get##name##File(); \ + } \ + }; \ + \ + inline StringTableEntry _get##name##AssetId(void) const { return m##name##Asset.getAssetId(); } \ + Resource get##name() { if (m##name##Asset.notNull()) return m##name##Asset->getShapeResource(); else return ResourceManager::get().load( "" ); } \ + AssetPtr get##name##Asset(void) { return m##name##Asset; } \ + static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast(obj)->_set##name(_getStringTable()->insert(data)); return false; } \ + StringTableEntry get##name##File() { return m##name##Asset.notNull() ? m##name##Asset->getShapeFile() : ""; } -#define INITPERSISTFIELD_SHAPEASSET(name, consoleClass, docs) \ - addProtectedField(assetText(name, File), TypeShapeFilename, Offset(m##name##Name, consoleClass), _set##name##Data, & defaultProtectedGetFn, assetText(name, docs)); \ - addProtectedField(assetText(name, Asset), TypeShapeAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, & defaultProtectedGetFn, assetText(name, asset reference.)); +#define DECLARE_SHAPEASSET_NET_REFACTOR(className, name, mask) \ +private: \ + AssetPtr 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 || _in == StringTable->EmptyString() || _in == "") \ + { \ + m##name##Asset = NULL; \ + m##name##File = ""; \ + setMaskBits(mask); \ + return; \ + } \ + if (!AssetDatabase.isDeclaredAsset(_in)) \ + { \ + StringTableEntry shapeAssetId = StringTable->EmptyString(); \ + AssetQuery query; \ + S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \ + if (foundAssetcount != 0) \ + { \ + shapeAssetId = query.mAssetList[0]; \ + } \ + else if (Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \ + { \ + shapeAssetId = ShapeAsset::getAssetIdByFilename(_in); \ + if (shapeAssetId == ShapeAsset::smNoShapeAssetFallback) \ + { \ + ShapeAsset* privateShape = new ShapeAsset(); \ + privateShape->setShapeFile(_in); \ + shapeAssetId = AssetDatabase.addPrivateAsset(privateShape); \ + } \ + } \ + else \ + { \ + Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \ + shapeAssetId = ShapeAsset::smNoShapeAssetFallback; \ + } \ + m##name##Asset = shapeAssetId; \ + m##name##File = _in; \ + } \ + else \ + { \ + m##name##Asset = _in; \ + m##name##File = get##name##File(); \ + } \ + setMaskBits(mask); \ + }; \ + \ + inline StringTableEntry _get##name##AssetId(void) const { return m##name##Asset.getAssetId(); } \ + Resource get##name() { if (m##name##Asset.notNull()) return m##name##Asset->getShapeResource(); else return ResourceManager::get().load( "" ); } \ + AssetPtr get##name##Asset(void) { return m##name##Asset; } \ + static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast(obj)->_set##name(_getStringTable()->insert(data)); return false; } \ + StringTableEntry get##name##File() { return m##name##Asset.notNull() ? m##name##Asset->getShapeFile() : ""; } -#else +#define INITPERSISTFIELD_SHAPEASSET_REFACTOR(name, consoleClass, docs) \ + addProtectedField(assetText(name, Asset), TypeShapeAssetPtr, 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 INITPERSISTFIELD_SHAPEASSET(name, consoleClass, docs) \ - addProtectedField(assetText(name, File), TypeShapeFilename, Offset(m##name##Name, consoleClass), _set##name##Data, & defaultProtectedGetFn, assetText(name, docs), AbstractClassRep::FIELD_HideInInspectors); \ - addProtectedField(assetText(name, Asset), TypeShapeAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, & defaultProtectedGetFn, assetText(name, asset reference.)); -#endif // SHOW_LEGACY_FILE_FIELDS +#define DECLARE_SHAPEASSET_ARRAY_REFACTOR(className, name, max) \ +private: \ + AssetPtr 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 || _in == StringTable->EmptyString() || _in == "") \ + { \ + m##name##Asset[index] = NULL; \ + m##name##File[index] = ""; \ + return; \ + } \ + if (!AssetDatabase.isDeclaredAsset(_in)) \ + { \ + StringTableEntry shapeAssetId = StringTable->EmptyString(); \ + AssetQuery query; \ + S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \ + if (foundAssetcount != 0) \ + { \ + shapeAssetId = query.mAssetList[0]; \ + } \ + else if (Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \ + { \ + shapeAssetId = ShapeAsset::getAssetIdByFilename(_in); \ + if (shapeAssetId == ShapeAsset::smNoShapeAssetFallback) \ + { \ + ShapeAsset* privateShape = new ShapeAsset(); \ + privateShape->setShapeFile(_in); \ + shapeAssetId = AssetDatabase.addPrivateAsset(privateShape); \ + } \ + } \ + else \ + { \ + Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \ + shapeAssetId = ShapeAsset::smNoShapeAssetFallback; \ + } \ + m##name##Asset[index] = shapeAssetId; \ + m##name##File[index] = _in; \ + } \ + else \ + { \ + m##name##Asset[index] = _in; \ + m##name##File[index] = get##name##File(index); \ + } \ + }; \ + \ + inline StringTableEntry _get##name##AssetId(const U32& index) const { return m##name##Asset[index].getAssetId(); } \ + Resource get##name(const U32& index) { if (m##name##Asset[index].notNull()) return m##name##Asset[index]->getShapeResource(); else return ResourceManager::get().load( "" ); } \ + AssetPtr 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(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]->getShapeFile() : ""; } + +#define DECLARE_SHAPEASSET_ARRAY_NET_REFACTOR(className, name, max, mask) \ +private: \ + AssetPtr 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 || _in == StringTable->EmptyString()) \ + { \ + m##name##Asset[index] = NULL; \ + m##name##File[index] = ""; \ + setMaskBits(mask); \ + return; \ + } \ + if (!AssetDatabase.isDeclaredAsset(_in)) \ + { \ + StringTableEntry shapeAssetId = StringTable->EmptyString(); \ + AssetQuery query; \ + S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \ + if (foundAssetcount != 0) \ + { \ + shapeAssetId = query.mAssetList[0]; \ + } \ + else if (Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \ + { \ + shapeAssetId = ShapeAsset::getAssetIdByFilename(_in); \ + if (shapeAssetId == ShapeAsset::smNoShapeAssetFallback) \ + { \ + ShapeAsset* privateShape = new ShapeAsset(); \ + privateShape->setShapeFile(_in); \ + shapeAssetId = AssetDatabase.addPrivateAsset(privateShape); \ + } \ + } \ + else \ + { \ + Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \ + shapeAssetId = ShapeAsset::smNoShapeAssetFallback; \ + } \ + m##name##Asset[index] = shapeAssetId; \ + 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##AssetId(const U32& index) const { return m##name##Asset[index].getAssetId(); } \ + Resource get##name(const U32& index) { if (m##name##Asset[index].notNull()) return m##name##Asset[index]->getShapeResource(); else return ResourceManager::get().load( "" ); } \ + AssetPtr 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(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]->getShapeFile() : ""; } + +#define INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(name, arraySize, consoleClass, docs) \ + addProtectedField(assetText(name, Asset), TypeShapeAssetPtr, Offset(m##name##Asset, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));\ + addProtectedField(assetText(name, File), TypeFilename, Offset(m##name##File, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.)); #pragma endregion -#pragma region Arrayed Asset Macros - -#define DECLARE_SHAPEASSET_ARRAY(className,name,max,changeFunc) public: \ - static const U32 sm##name##Count = max;\ - Resourcem##name[max];\ - StringTableEntry m##name##Name[max]; \ - StringTableEntry m##name##AssetId[max];\ - AssetPtr m##name##Asset[max];\ -public: \ - const StringTableEntry get##name##File(const U32& index) const { return m##name##Name[index]; }\ - void set##name##Name(const FileName &_in, const U32& index) { m##name##Name[index] = _in;}\ - const AssetPtr & get##name##Asset(const U32& index) const { return m##name##Asset[index]; }\ - void set##name##Asset(const AssetPtr &_in, const U32& index) { m##name##Asset[index] = _in;}\ - \ - bool _set##name(StringTableEntry _in, const U32& index)\ - {\ - if (m##name##Asset[index].notNull())\ - {\ - m##name##Asset[index]->getChangedSignal().remove(this, &className::changeFunc);\ - }\ - if(m##name##AssetId[index] != _in || m##name##Name[index] != _in)\ - {\ - if(index >= sm##name##Count || index < 0)\ - return false;\ - if (_in == NULL || _in == StringTable->EmptyString())\ - {\ - m##name##Name[index] = StringTable->EmptyString();\ - m##name##AssetId[index] = StringTable->EmptyString();\ - m##name##Asset[index] = NULL;\ - m##name[index] = NULL;\ - return true;\ - }\ - \ - if (AssetDatabase.isDeclaredAsset(_in))\ - {\ - m##name##AssetId[index] = _in;\ - \ - U32 assetState = ShapeAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]);\ - \ - if (ShapeAsset::Ok == assetState)\ - {\ - m##name##Name[index] = StringTable->EmptyString();\ - }\ - }\ - else\ - {\ - StringTableEntry assetId = ShapeAsset::getAssetIdByFilename(_in);\ - if (assetId != StringTable->EmptyString())\ - {\ - m##name##AssetId[index] = assetId;\ - if (ShapeAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]) == ShapeAsset::Ok)\ - {\ - m##name##Name[index] = StringTable->EmptyString();\ - }\ - }\ - else\ - {\ - m##name##Name[index] = _in;\ - m##name##AssetId[index] = StringTable->EmptyString();\ - m##name##Asset[index] = NULL;\ - }\ - }\ - }\ - if (get##name(index) != StringTable->EmptyString() && m##name##Asset[index].notNull())\ - {\ - m##name[index] = m##name##Asset[index]->getShapeResource();\ - \ - m##name##Asset[index]->getChangedSignal().notify(this, &className::changeFunc);\ - }\ - else\ - {\ - m##name[index] = NULL;\ - }\ - \ - if(get##name(index) == StringTable->EmptyString())\ - return true;\ - \ - if (m##name##Asset[index].notNull() && m##name##Asset[index]->getStatus() != ShapeAsset::Ok)\ - {\ - Con::errorf("%s(%s)::_set%s(%i) - shape asset failure \"%s\" due to [%s]", macroText(className), getName(), macroText(name), index, _in, ShapeAsset::getAssetErrstrn(m##name##Asset[index]->getStatus()).c_str());\ - return false; \ - }\ - else if (!m##name[index])\ - {\ - Con::errorf("%s(%s)::_set%s(%i) - Couldn't load shape \"%s\"", macroText(className), getName(), macroText(name), index, _in);\ - return false; \ - }\ - return true;\ - }\ - \ - const StringTableEntry get##name(const U32& index) const\ - {\ - if (m##name##Asset[index] && (m##name##Asset[index]->getShapePath() != StringTable->EmptyString()))\ - return m##name##Asset[index]->getShapePath();\ - else if (m##name##AssetId[index] != StringTable->EmptyString())\ - return m##name##AssetId[index];\ - else if (m##name##Name[index] != StringTable->EmptyString())\ - return StringTable->insert(m##name##Name[index]);\ - else\ - return StringTable->EmptyString();\ - }\ - Resource get##name##Resource(const U32& index) \ - {\ - if(index >= sm##name##Count || index < 0)\ - return ResourceManager::get().load( "" );\ - return m##name[index];\ - }\ - bool is##name##Valid(const U32& id) {return (get##name(id) != StringTable->EmptyString() && m##name##Asset[id]->getStatus() == AssetBase::Ok); } - -#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS - -#define INITPERSISTFIELD_SHAPEASSET_ARRAY(name, arraySize, consoleClass, docs) \ - addProtectedField(assetText(name, File), TypeShapeFilename, Offset(m##name##Name, consoleClass), _set##name##Data, & defaultProtectedGetFn, arraySize, assetText(name, docs)); \ - addProtectedField(assetText(name, Asset), TypeShapeAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, & defaultProtectedGetFn, arraySize, assetText(name, asset reference.)); - -#else - -#define INITPERSISTFIELD_SHAPEASSET_ARRAY(name, arraySize, consoleClass, docs) \ - addProtectedField(assetText(name, File), TypeShapeFilename, Offset(m##name##Name, consoleClass), _set##name##Data, & defaultProtectedGetFn, arraySize, assetText(name, docs), AbstractClassRep::FIELD_HideInInspectors); \ - addProtectedField(assetText(name, Asset), TypeShapeAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, & defaultProtectedGetFn, arraySize,assetText(name, asset reference.)); - -#endif // SHOW_LEGACY_FILE_FIELDS - -#pragma endregion +//----------------------------------------------------------------------------- +// REFACTOR END +//----------------------------------------------------------------------------- #endif diff --git a/Engine/source/T3D/assets/assetImporter.cpp b/Engine/source/T3D/assets/assetImporter.cpp index eca044509..b6ce8b535 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); } } @@ -2825,29 +2826,18 @@ 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(); - 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 +2860,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; } @@ -3057,31 +3035,15 @@ Torque::Path AssetImporter::importShapeAsset(AssetImportObject* assetItem) StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str()); - String shapeFileName = assetItem->filePath.getFileName() + "." + assetItem->filePath.getExtension(); + String shapeFileName = "@" + assetItem->filePath.getFileName() + "." + assetItem->filePath.getExtension(); String constructorFileName = assetItem->filePath.getFileName() + "." TORQUE_SCRIPT_EXTENSION; String assetPath = targetPath + "/" + shapeFileName; String constructorPath = targetPath + "/" + constructorFileName; + constructorFileName = "@" + constructorFileName; String tamlPath = targetPath + "/" + assetName + ".asset.taml"; String originalPath = assetItem->filePath.getFullPath().c_str(); String originalConstructorPath = assetItem->filePath.getPath() + "/" + constructorFileName; - char qualifiedFromFile[2048]; - char qualifiedToFile[2048]; - char qualifiedFromCSFile[2048]; - char qualifiedToCSFile[2048]; - -#ifndef TORQUE_SECURE_VFS - Platform::makeFullPathName(originalPath.c_str(), qualifiedFromFile, sizeof(qualifiedFromFile)); - Platform::makeFullPathName(assetPath.c_str(), qualifiedToFile, sizeof(qualifiedToFile)); - Platform::makeFullPathName(originalConstructorPath.c_str(), qualifiedFromCSFile, sizeof(qualifiedFromCSFile)); - Platform::makeFullPathName(constructorPath.c_str(), qualifiedToCSFile, sizeof(qualifiedToCSFile)); -#else - dStrcpy(qualifiedFromFile, originalPath.c_str(), sizeof(qualifiedFromFile)); - dStrcpy(qualifiedToFile, assetPath.c_str(), sizeof(qualifiedToFile)); - dStrcpy(qualifiedFromCSFile, originalConstructorPath.c_str(), sizeof(qualifiedFromCSFile)); - dStrcpy(qualifiedToCSFile, constructorPath.c_str(), sizeof(qualifiedToCSFile)); -#endif - newAsset->setAssetName(assetName); newAsset->setShapeFile(shapeFileName.c_str()); newAsset->setShapeConstructorFile(constructorFileName.c_str()); @@ -3098,9 +3060,9 @@ Torque::Path AssetImporter::importShapeAsset(AssetImportObject* assetItem) //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 && Torque::FS::IsFile(originalPath)) { - newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile); + newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, originalPath.c_str()); } //iterate through and write out the material maps dependencies @@ -3140,8 +3102,8 @@ Torque::Path AssetImporter::importShapeAsset(AssetImportObject* assetItem) if (Con::getBoolVariable("$TSLastDetail::dumpImposters", false)) { - String imposterPath = assetItem->assetName + "_imposter.png"; - String normalsPath = assetItem->assetName + "_imposter_normals.png"; + String imposterPath = "@" + assetItem->assetName + "_imposter.png"; + String normalsPath = "@" + assetItem->assetName + "_imposter_normals.png"; newAsset->setDiffuseImposterFile(imposterPath.c_str()); newAsset->setNormalImposterFile(normalsPath.c_str()); @@ -3160,67 +3122,37 @@ Torque::Path AssetImporter::importShapeAsset(AssetImportObject* assetItem) bool makeNewConstructor = true; if (!isReimport) { - bool isInPlace = !String::compare(qualifiedFromFile, qualifiedToFile); - - if (!isInPlace && !Torque::FS::CopyFile(qualifiedFromFile, qualifiedToFile, !isReimport)) + //We're doing an in-place import, so double check we've already got a constructor file in the expected spot + if (Torque::FS::IsFile(constructorPath)) { - dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", qualifiedFromFile); + //Yup, found it, we're good to go + makeNewConstructor = false; + dSprintf(importLogBuffer, sizeof(importLogBuffer), "Existing TSShape Constructor file %s found", constructorPath.c_str()); activityLog.push_back(importLogBuffer); - return ""; - } - - if (!isInPlace) - { - if (Torque::FS::IsFile(qualifiedFromCSFile)) - { - if (!Torque::FS::CopyFile(qualifiedFromCSFile, qualifiedToCSFile, !isReimport)) - { - dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", qualifiedFromCSFile); - activityLog.push_back(importLogBuffer); - } - else - { - //We successfully copied the original constructor file, so no extra work required - makeNewConstructor = false; - dSprintf(importLogBuffer, sizeof(importLogBuffer), "Successfully copied original TSShape Constructor file %s", qualifiedFromCSFile); - activityLog.push_back(importLogBuffer); - } - } } else { - //We're doing an in-place import, so double check we've already got a constructor file in the expected spot - if (Torque::FS::IsFile(qualifiedFromCSFile)) + //Didn't work, but it's possible it's using the old .cs extension when our extension variable is set to something else, so check that one as well just to be sure + Torque::Path constrFilePath = constructorPath; + constrFilePath.setExtension("cs"); + + if (Torque::FS::IsFile(constrFilePath.getFullPath().c_str())) { //Yup, found it, we're good to go makeNewConstructor = false; - dSprintf(importLogBuffer, sizeof(importLogBuffer), "Existing TSShape Constructor file %s found", qualifiedFromCSFile); + dSprintf(importLogBuffer, sizeof(importLogBuffer), "Existing TSShape Constructor file %s found", constrFilePath.getFullPath().c_str()); activityLog.push_back(importLogBuffer); } - else - { - //Didn't work, but it's possible it's using the old .cs extension when our extension variable is set to something else, so check that one as well just to be sure - Torque::Path constrFilePath = qualifiedFromCSFile; - constrFilePath.setExtension("cs"); - - if (Torque::FS::IsFile(constrFilePath.getFullPath().c_str())) - { - //Yup, found it, we're good to go - makeNewConstructor = false; - dSprintf(importLogBuffer, sizeof(importLogBuffer), "Existing TSShape Constructor file %s found", constrFilePath.getFullPath().c_str()); - activityLog.push_back(importLogBuffer); - } - } } } if (makeNewConstructor) { - dSprintf(importLogBuffer, sizeof(importLogBuffer), "Beginning creation of new TSShapeConstructor file: %s", qualifiedToCSFile); + dSprintf(importLogBuffer, sizeof(importLogBuffer), "Beginning creation of new TSShapeConstructor file: %s", constructorPath.c_str()); activityLog.push_back(importLogBuffer); //find/create shape constructor - TSShapeConstructor* constructor = TSShapeConstructor::findShapeConstructorByFilename(Torque::Path(qualifiedToFile).getFullPath()); + TSShapeConstructor* constructor = TSShapeConstructor::findShapeConstructorByFilename(Torque::Path(constructorPath).getFullPath()); if (constructor == nullptr) { String fullAssetName = assetItem->moduleName + ":" + assetItem->assetName; @@ -3324,7 +3256,7 @@ Torque::Path AssetImporter::importShapeAsset(AssetImportObject* assetItem) PersistenceManager* constructorPersist = new PersistenceManager(); constructorPersist->registerObject(); - constructorPersist->setDirty(constructor, qualifiedToCSFile); + constructorPersist->setDirty(constructor, constructorPath); if (!constructorPersist->saveDirtyObject(constructor)) { diff --git a/Engine/source/T3D/debris.cpp b/Engine/source/T3D/debris.cpp index 78a1e53cc..b7566ab72 100644 --- a/Engine/source/T3D/debris.cpp +++ b/Engine/source/T3D/debris.cpp @@ -116,7 +116,7 @@ DebrisData::DebrisData() terminalVelocity = 0.0f; ignoreWater = true; - INIT_ASSET(Shape); + mShapeAsset.registerRefreshNotify(this); } //#define TRACK_DEBRIS_DATA_CLONES @@ -152,7 +152,7 @@ DebrisData::DebrisData(const DebrisData& other, bool temp_clone) : GameBaseData( terminalVelocity = other.terminalVelocity; ignoreWater = other.ignoreWater; - CLONE_ASSET(Shape); + mShapeAsset = other.mShapeAsset; textureName = other.textureName; explosionId = other.explosionId; // -- for pack/unpack of explosion ptr @@ -191,7 +191,7 @@ DebrisData* DebrisData::cloneAndPerformSubstitutions(const SimObject* owner, S32 void DebrisData::onPerformSubstitutions() { - _setShape(getShape()); + _setShape(_getShapeAssetId()); } bool DebrisData::onAdd() @@ -276,16 +276,16 @@ bool DebrisData::preload(bool server, String &errorStr) if (mShapeAsset.notNull()) { - if (!mShape) + if (!getShape()) { - errorStr = String::ToString("DebrisData::load: Couldn't load shape \"%s\"", mShapeAssetId); + errorStr = String::ToString("DebrisData::load: Couldn't load shape \"%s\"", _getShapeAssetId()); return false; } else { - TSShapeInstance* pDummy = new TSShapeInstance(mShape, !server); + TSShapeInstance* pDummy = new TSShapeInstance(getShape(), !server); delete pDummy; - if (!server && !mShape->preloadMaterialList(mShape.getPath()) && NetConnection::filesWereDownloaded()) + if (!server && !getShape()->preloadMaterialList(getShape().getPath()) && NetConnection::filesWereDownloaded()) return false; } } @@ -304,7 +304,7 @@ void DebrisData::initPersistFields() addGroup("Shapes"); addField("texture", TypeString, Offset(textureName, DebrisData), "@brief Texture imagemap to use for this debris object.\n\nNot used any more.\n", AbstractClassRep::FIELD_HideInInspectors); - INITPERSISTFIELD_SHAPEASSET(Shape, DebrisData, "Shape to use for this debris object."); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, DebrisData, "Shape to use for this debris object."); endGroup("Shapes"); addGroup("Particle Effects"); @@ -389,7 +389,7 @@ void DebrisData::packData(BitStream* stream) stream->writeString( textureName ); - PACKDATA_ASSET(Shape); + PACKDATA_ASSET_REFACTOR(Shape); for( S32 i=0; ireadSTString(); - UNPACKDATA_ASSET(Shape); + UNPACKDATA_ASSET_REFACTOR(Shape); for( S32 i=0; ifriction; // Setup our bounding box - if( mDataBlock->mShape ) + if( mDataBlock->getShape()) { - mObjBox = mDataBlock->mShape->mBounds; + mObjBox = mDataBlock->getShape()->mBounds; } else { mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1)); } - if( mDataBlock->mShape) + if( mDataBlock->getShape()) { - mShape = new TSShapeInstance( mDataBlock->mShape, true); + mShape = new TSShapeInstance( mDataBlock->getShape(), true); } if( mPart ) diff --git a/Engine/source/T3D/debris.h b/Engine/source/T3D/debris.h index 1d1116031..9d9065d0b 100644 --- a/Engine/source/T3D/debris.h +++ b/Engine/source/T3D/debris.h @@ -47,7 +47,7 @@ class TSShape; //************************************************************************** // Debris Data //************************************************************************** -struct DebrisData : public GameBaseData +struct DebrisData : public GameBaseData, protected AssetPtrCallback { typedef GameBaseData Parent; @@ -83,8 +83,7 @@ struct DebrisData : public GameBaseData F32 terminalVelocity; // max velocity magnitude bool ignoreWater; - DECLARE_SHAPEASSET(DebrisData, Shape, onShapeChanged); - DECLARE_ASSET_SETGET(DebrisData, Shape); + DECLARE_SHAPEASSET_REFACTOR(DebrisData, Shape) StringTableEntry textureName; @@ -111,7 +110,8 @@ public: void onPerformSubstitutions() override; bool allowSubstitutions() const override { return true; } - void onShapeChanged() +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { reloadOnLocalClient(); } diff --git a/Engine/source/T3D/examples/renderShapeExample.cpp b/Engine/source/T3D/examples/renderShapeExample.cpp index 731db472e..2762cfe9b 100644 --- a/Engine/source/T3D/examples/renderShapeExample.cpp +++ b/Engine/source/T3D/examples/renderShapeExample.cpp @@ -59,7 +59,6 @@ RenderShapeExample::RenderShapeExample() mTypeMask |= StaticObjectType | StaticShapeObjectType; // Make sure to initialize our TSShapeInstance to NULL - INIT_ASSET(Shape); mShapeInstance = NULL; } @@ -75,7 +74,7 @@ void RenderShapeExample::initPersistFields() docsURL; Parent::initPersistFields(); addGroup( "Shapes" ); - INITPERSISTFIELD_SHAPEASSET(Shape, RenderShapeExample, "The path to the shape file.") + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, RenderShapeExample, "The path to the shape file.") endGroup( "Shapes" ); // SceneObject already handles exposing the transform @@ -147,7 +146,7 @@ U32 RenderShapeExample::packUpdate( NetConnection *conn, U32 mask, BitStream *st // Write out any of the updated editable properties if ( stream->writeFlag( mask & UpdateMask ) ) { - PACK_ASSET(conn, Shape); + PACK_ASSET_REFACTOR(conn, Shape); // Allow the server object a chance to handle a new shape createShape(); @@ -171,7 +170,7 @@ void RenderShapeExample::unpackUpdate(NetConnection *conn, BitStream *stream) if ( stream->readFlag() ) // UpdateMask { - UNPACK_ASSET(conn, Shape); + UNPACK_ASSET_REFACTOR(conn, Shape); if ( isProperlyAdded() ) createShape(); @@ -183,11 +182,7 @@ void RenderShapeExample::unpackUpdate(NetConnection *conn, BitStream *stream) //----------------------------------------------------------------------------- void RenderShapeExample::createShape() { - if ( getShape() == StringTable->EmptyString() ) - return; - - // If this is the same shape then no reason to update it - if ( mShapeInstance && getShape() == StringTable->insert(mShape.getPath().getFullPath().c_str()) ) + if ( mShapeAsset.isNull() ) return; // Clean up our previous shape @@ -196,19 +191,19 @@ void RenderShapeExample::createShape() // Attempt to preload the Materials for this shape if ( isClientObject() && - !mShape->preloadMaterialList( mShape.getPath() ) && + !getShape()->preloadMaterialList(getShape().getPath() ) && NetConnection::filesWereDownloaded() ) { return; } // Update the bounding box - mObjBox = mShape->mBounds; + mObjBox = getShape()->mBounds; resetWorldBox(); setRenderTransform(mObjToWorld); // Create the TSShapeInstance - mShapeInstance = new TSShapeInstance( mShape, isClientObject() ); + mShapeInstance = new TSShapeInstance(getShape(), isClientObject() ); } void RenderShapeExample::prepRenderImage( SceneRenderState *state ) diff --git a/Engine/source/T3D/examples/renderShapeExample.h b/Engine/source/T3D/examples/renderShapeExample.h index 3f452c72a..8160044a6 100644 --- a/Engine/source/T3D/examples/renderShapeExample.h +++ b/Engine/source/T3D/examples/renderShapeExample.h @@ -61,14 +61,11 @@ class RenderShapeExample : public SceneObject //-------------------------------------------------------------------------- // Rendering variables //-------------------------------------------------------------------------- - DECLARE_SHAPEASSET(RenderShapeExample, Shape, onShapeChanged); - DECLARE_ASSET_SETGET(RenderShapeExample, Shape); + DECLARE_SHAPEASSET_REFACTOR(RenderShapeExample, Shape) // The actual shape instance TSShapeInstance* mShapeInstance; - void onShapeChanged() {} - public: RenderShapeExample(); virtual ~RenderShapeExample(); @@ -119,4 +116,4 @@ public: void prepRenderImage( SceneRenderState *state ) override; }; -#endif // _RENDERSHAPEEXAMPLE_H_ \ No newline at end of file +#endif // _RENDERSHAPEEXAMPLE_H_ diff --git a/Engine/source/T3D/fps/guiCrossHairHud.cpp b/Engine/source/T3D/fps/guiCrossHairHud.cpp index eaa318c53..052350be1 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() @@ -139,11 +151,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; + 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) + { + GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL; + 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 diff --git a/Engine/source/T3D/fx/explosion.cpp b/Engine/source/T3D/fx/explosion.cpp index 02676be26..f28a90b72 100644 --- a/Engine/source/T3D/fx/explosion.cpp +++ b/Engine/source/T3D/fx/explosion.cpp @@ -239,7 +239,7 @@ ExplosionData::ExplosionData() explosionScale.set(1.0f, 1.0f, 1.0f); playSpeed = 1.0f; - INIT_ASSET(ExplosionShape); + mExplosionShapeAsset.registerRefreshNotify(this); explosionAnimation = -1; @@ -315,7 +315,7 @@ ExplosionData::ExplosionData(const ExplosionData& other, bool temp_clone) : Game particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr explosionScale = other.explosionScale; playSpeed = other.playSpeed; - CLONE_ASSET(ExplosionShape); + mExplosionShapeAsset = other.mExplosionShapeAsset; explosionAnimation = other.explosionAnimation; // -- from explosionShape sequence "ambient" dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) ); dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs @@ -360,6 +360,8 @@ ExplosionData::~ExplosionData() if (!isTempClone()) return; + mExplosionShapeAsset.unregisterRefreshNotify(); + // particleEmitter, emitterList[*], debrisList[*], explosionList[*] will delete themselves #ifdef TRACK_EXPLOSION_DATA_CLONES @@ -393,7 +395,7 @@ void ExplosionData::initPersistFields() { docsURL; addGroup("Shapes"); - INITPERSISTFIELD_SHAPEASSET(ExplosionShape, ExplosionData, "@brief Optional shape asset to place at the center of the explosion.\n\n" + INITPERSISTFIELD_SHAPEASSET_REFACTOR(ExplosionShape, ExplosionData, "@brief Optional shape asset to place at the center of the explosion.\n\n" "The ambient animation of this model will be played automatically at the start of the explosion."); endGroup("Shapes"); @@ -668,7 +670,7 @@ void ExplosionData::packData(BitStream* stream) { Parent::packData(stream); - PACKDATA_ASSET(ExplosionShape); + PACKDATA_ASSET_REFACTOR(ExplosionShape); //PACKDATA_SOUNDASSET(Sound); PACKDATA_ASSET(Sound); @@ -773,7 +775,7 @@ void ExplosionData::unpackData(BitStream* stream) { Parent::unpackData(stream); - UNPACKDATA_ASSET(ExplosionShape); + UNPACKDATA_ASSET_REFACTOR(ExplosionShape); UNPACKDATA_ASSET(Sound); @@ -897,10 +899,10 @@ bool ExplosionData::preload(bool server, String &errorStr) if (mExplosionShapeAsset.notNull()) { // Resolve animations - explosionAnimation = mExplosionShape->findSequence("ambient"); + explosionAnimation = getExplosionShape()->findSequence("ambient"); // Preload textures with a dummy instance... - TSShapeInstance* pDummy = new TSShapeInstance(mExplosionShape, !server); + TSShapeInstance* pDummy = new TSShapeInstance(getExplosionShape(), !server); delete pDummy; } else { @@ -1392,8 +1394,8 @@ bool Explosion::explode() launchDebris( mInitialNormal ); spawnSubExplosions(); - if (bool(mDataBlock->mExplosionShape) && mDataBlock->explosionAnimation != -1) { - mExplosionInstance = new TSShapeInstance(mDataBlock->mExplosionShape, true); + if (bool(mDataBlock->getExplosionShape()) && mDataBlock->explosionAnimation != -1) { + mExplosionInstance = new TSShapeInstance(mDataBlock->getExplosionShape(), true); mExplosionThread = mExplosionInstance->addThread(); mExplosionInstance->setSequence(mExplosionThread, mDataBlock->explosionAnimation, 0); @@ -1403,7 +1405,7 @@ bool Explosion::explode() mEndingMS = U32(mExplosionInstance->getScaledDuration(mExplosionThread) * 1000.0f); mObjScale.convolve(mDataBlock->explosionScale); - mObjBox = mDataBlock->mExplosionShape->mBounds; + mObjBox = mDataBlock->getExplosionShape()->mBounds; resetWorldBox(); } diff --git a/Engine/source/T3D/fx/explosion.h b/Engine/source/T3D/fx/explosion.h index 0ea4c63d7..c00483625 100644 --- a/Engine/source/T3D/fx/explosion.h +++ b/Engine/source/T3D/fx/explosion.h @@ -52,7 +52,7 @@ struct DebrisData; class SFXProfile; //-------------------------------------------------------------------------- -class ExplosionData : public GameBaseData { +class ExplosionData : public GameBaseData, protected AssetPtrCallback { public: typedef GameBaseData Parent; @@ -79,8 +79,7 @@ class ExplosionData : public GameBaseData { Point3F explosionScale; F32 playSpeed; - DECLARE_SHAPEASSET(ExplosionData, ExplosionShape, onShapeChanged); - DECLARE_ASSET_SETGET(ExplosionData, ExplosionShape); + DECLARE_SHAPEASSET_REFACTOR(ExplosionData, ExplosionShape) S32 explosionAnimation; @@ -143,7 +142,8 @@ public: ExplosionData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0); bool allowSubstitutions() const override { return true; } - void onShapeChanged() +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { reloadOnLocalClient(); } diff --git a/Engine/source/T3D/fx/groundCover.cpp b/Engine/source/T3D/fx/groundCover.cpp index 9352deabf..bf53746cb 100644 --- a/Engine/source/T3D/fx/groundCover.cpp +++ b/Engine/source/T3D/fx/groundCover.cpp @@ -521,7 +521,7 @@ GroundCover::GroundCover() mBillboardRects[i].point.set( 0.0f, 0.0f ); mBillboardRects[i].extent.set( 1.0f, 1.0f ); - INIT_ASSET_ARRAY(Shape, i); + mShapeAsset[i].registerRefreshNotify(this); mShapeInstances[i] = NULL; @@ -563,8 +563,7 @@ void GroundCover::initPersistFields() addField( "billboardUVs", TypeRectUV, Offset( mBillboardRects, GroundCover ), MAX_COVERTYPES, "Subset material UV coordinates for this cover billboard." ); - addField("shapeFilename", TypeFilename, Offset(mShapeName, GroundCover), MAX_COVERTYPES, "The cover shape filename. [Optional]", AbstractClassRep::FIELD_HideInInspectors); - INITPERSISTFIELD_SHAPEASSET_ARRAY(Shape, MAX_COVERTYPES, GroundCover, "The cover shape. [Optional]"); + INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(Shape, MAX_COVERTYPES, GroundCover, "The cover shape. [Optional]"); addField( "layer", TypeTerrainMaterialAssetId, Offset( mLayer, GroundCover ), MAX_COVERTYPES, "Terrain material assetId to limit coverage to, or blank to not limit." ); @@ -767,10 +766,10 @@ U32 GroundCover::packUpdate( NetConnection *connection, U32 mask, BitStream *str stream->write( mBillboardRects[i].point.y ); stream->write( mBillboardRects[i].extent.x ); stream->write( mBillboardRects[i].extent.y ); - - PACK_ASSET_ARRAY(connection, Shape, i); } + PACK_ASSET_ARRAY_REFACTOR(connection, Shape, MAX_COVERTYPES) + stream->writeFlag( mDebugRenderCells ); stream->writeFlag( mDebugNoBillboards ); stream->writeFlag( mDebugNoShapes ); @@ -838,10 +837,10 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream ) stream->read( &mBillboardRects[i].point.y ); stream->read( &mBillboardRects[i].extent.x ); stream->read( &mBillboardRects[i].extent.y ); - - UNPACK_ASSET_ARRAY(connection, Shape, i); } + UNPACK_ASSET_ARRAY_REFACTOR(connection, Shape, MAX_COVERTYPES) + mDebugRenderCells = stream->readFlag(); mDebugNoBillboards = stream->readFlag(); mDebugNoShapes = stream->readFlag(); @@ -887,17 +886,17 @@ void GroundCover::_initShapes() for ( S32 i=0; i < MAX_COVERTYPES; i++ ) { - if ( mShapeAsset[i].isNull() || mShape[i] == nullptr) + if ( mShapeAsset[i].isNull() || getShape(i) == nullptr) continue; - if ( isClientObject() && !mShape[i]->preloadMaterialList(mShape[i].getPath()) && NetConnection::filesWereDownloaded() ) + if ( isClientObject() && !getShape(i)->preloadMaterialList(getShape(i).getPath()) && NetConnection::filesWereDownloaded() ) { - Con::warnf( "GroundCover::_initShapes() material preload failed for shape: %s", mShapeAssetId[i] ); + Con::warnf( "GroundCover::_initShapes() material preload failed for shape: %s", _getShapeAssetId(i)); continue; } // Create the shape instance. - mShapeInstances[i] = new TSShapeInstance(mShape[i], isClientObject() ); + mShapeInstances[i] = new TSShapeInstance(getShape(i), isClientObject() ); } } diff --git a/Engine/source/T3D/fx/groundCover.h b/Engine/source/T3D/fx/groundCover.h index af5d02858..af6a74d7e 100644 --- a/Engine/source/T3D/fx/groundCover.h +++ b/Engine/source/T3D/fx/groundCover.h @@ -111,7 +111,7 @@ public: }; -class GroundCover : public SceneObject +class GroundCover : public SceneObject, protected AssetPtrCallback { friend class GroundCoverShaderConstHandles; friend class GroundCoverCell; @@ -341,8 +341,7 @@ protected: RectF mBillboardRects[MAX_COVERTYPES]; /// The cover shape filenames. - DECLARE_SHAPEASSET_ARRAY(GroundCover, Shape, MAX_COVERTYPES, onShapeChanged); - DECLARE_ASSET_ARRAY_NET_SETGET(GroundCover, Shape, -1); + DECLARE_SHAPEASSET_ARRAY_NET_REFACTOR(GroundCover, Shape, MAX_COVERTYPES, -1) /// The cover shape instances. TSShapeInstance* mShapeInstances[MAX_COVERTYPES]; @@ -410,7 +409,8 @@ protected: void _debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); - void onShapeChanged() +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { _initShapes(); setMaskBits(U32(-1)); diff --git a/Engine/source/T3D/guiObjectView.cpp b/Engine/source/T3D/guiObjectView.cpp index cc29f453b..c086c85ac 100644 --- a/Engine/source/T3D/guiObjectView.cpp +++ b/Engine/source/T3D/guiObjectView.cpp @@ -119,8 +119,6 @@ GuiObjectView::GuiObjectView() // By default don't do dynamic reflection // updates for this viewport. mReflectPriority = 0.0f; - INIT_ASSET(Model); - INIT_ASSET(MountedModel); } //------------------------------------------------------------------------------ @@ -137,7 +135,7 @@ void GuiObjectView::initPersistFields() { docsURL; addGroup( "Model" ); - INITPERSISTFIELD_SHAPEASSET(Model, GuiObjectView, "The source shape asset."); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Model, GuiObjectView, "The source shape asset."); addField( "skin", TypeRealString, Offset( mSkinName, GuiObjectView ), "The skin to use on the object model." ); endGroup( "Model" ); @@ -150,7 +148,7 @@ void GuiObjectView::initPersistFields() endGroup( "Animation" ); addGroup( "Mounting" ); - INITPERSISTFIELD_SHAPEASSET(MountedModel, GuiObjectView, "The mounted shape asset."); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(MountedModel, GuiObjectView, "The mounted shape asset."); addField( "mountedSkin", TypeRealString, Offset( mMountSkinName, GuiObjectView ), "Skin name used on mounted shape file." ); addField( "mountedNode", TypeRealString, Offset( mMountNodeName, GuiObjectView ), @@ -335,19 +333,23 @@ bool GuiObjectView::setObjectModel( const String& modelName ) { mRunThread = 0; - // Load the shape. - _setModel(modelName); - if( !getModelResource()) + // Load the shape if its not the one already set. + if (modelName.c_str() != _getModelAssetId()) + _setModel(modelName.c_str()); + else + return true; + + if( !getModel()) { Con::warnf( "GuiObjectView::setObjectModel - Failed to load model '%s'", modelName.c_str() ); return false; } - if (!getModelResource()->preloadMaterialList(getModelResource().getPath())) return false; + if (!getModel()->preloadMaterialList(getModel().getPath())) return false; // Instantiate it. - mModelInstance = new TSShapeInstance(getModelResource(), true ); + mModelInstance = new TSShapeInstance(getModel(), true ); mModelInstance->resetMaterialList(); mModelInstance->cloneMaterialList(); @@ -355,12 +357,12 @@ bool GuiObjectView::setObjectModel( const String& modelName ) mModelInstance->reSkin( mSkinName ); TSMaterialList* pMatList = mModelInstance->getMaterialList(); - pMatList->setTextureLookupPath(mModelAsset->getShapeFileName()); + pMatList->setTextureLookupPath(mModelAsset->getShapeFile()); mModelInstance->initMaterialList(); // Initialize camera values. - mOrbitPos = getModelResource()->center; - mMinOrbitDist = getModelResource()->mRadius; + mOrbitPos = getModel()->center; + mMinOrbitDist = getModel()->mRadius; // Initialize animation. @@ -369,11 +371,6 @@ bool GuiObjectView::setObjectModel( const String& modelName ) return true; } -void GuiObjectView::onModelChanged() -{ - -} - //------------------------------------------------------------------------------ void GuiObjectView::setSkin( const String& name ) @@ -389,17 +386,21 @@ void GuiObjectView::setSkin( const String& name ) bool GuiObjectView::setMountedObject( const String& modelName ) { - // Load the model. - _setMountedModel(modelName); - if (!getMountedModelResource()) + // Load the model if it is not already the asset then set it.. + if (modelName.c_str() != _getMountedModelAssetId()) + _setMountedModel(modelName.c_str()); + else + return true; + + if (!getMountedModel()) { Con::warnf("GuiObjectView::setMountedObject - Failed to load model '%s'", modelName.c_str()); return false; } - if (!getMountedModelResource()->preloadMaterialList(getMountedModelResource().getPath())) return false; + if (!getMountedModel()->preloadMaterialList(getMountedModel().getPath())) return false; - mMountedModelInstance = new TSShapeInstance(getMountedModelResource(), true); + mMountedModelInstance = new TSShapeInstance(getMountedModel(), true); mMountedModelInstance->resetMaterialList(); mMountedModelInstance->cloneMaterialList(); @@ -413,11 +414,6 @@ bool GuiObjectView::setMountedObject( const String& modelName ) return true; } -void GuiObjectView::onMountedModelChanged() -{ - -} - //------------------------------------------------------------------------------ void GuiObjectView::setMountSkin(const String& name) @@ -632,7 +628,7 @@ void GuiObjectView::setLightDirection( const Point3F& direction ) void GuiObjectView::_initAnimation() { - AssertFatal(getModelResource(), "GuiObjectView::_initAnimation - No model loaded!" ); + AssertFatal(getModel(), "GuiObjectView::_initAnimation - No model loaded!" ); if( mAnimationSeqName.isEmpty() && mAnimationSeq == -1 ) return; @@ -641,13 +637,13 @@ void GuiObjectView::_initAnimation() if( !mAnimationSeqName.isEmpty() ) { - mAnimationSeq = getModelResource()->findSequence( mAnimationSeqName ); + mAnimationSeq = getModel()->findSequence( mAnimationSeqName ); if( mAnimationSeq == -1 ) { Con::errorf( "GuiObjectView::_initAnimation - Cannot find animation sequence '%s' on '%s'", mAnimationSeqName.c_str(), - mModelName + _getModelAssetId() ); return; @@ -658,11 +654,11 @@ void GuiObjectView::_initAnimation() if( mAnimationSeq != -1 ) { - if( mAnimationSeq >= getModelResource()->sequences.size() ) + if( mAnimationSeq >= getModel()->sequences.size() ) { Con::errorf( "GuiObjectView::_initAnimation - Sequence '%i' out of range for model '%s'", mAnimationSeq, - mModelName + _getModelAssetId() ); mAnimationSeq = -1; @@ -693,12 +689,12 @@ void GuiObjectView::_initMount() if( !mMountNodeName.isEmpty() ) { - mMountNode = getModelResource()->findNode( mMountNodeName ); + mMountNode = getModel()->findNode( mMountNodeName ); if( mMountNode == -1 ) { Con::errorf( "GuiObjectView::_initMount - No node '%s' on '%s'", mMountNodeName.c_str(), - mModelName + _getModelAssetId() ); return; @@ -707,11 +703,11 @@ void GuiObjectView::_initMount() // Make sure mount node is valid. - if( mMountNode != -1 && mMountNode >= getModelResource()->nodes.size() ) + if( mMountNode != -1 && mMountNode >= getModel()->nodes.size() ) { Con::errorf( "GuiObjectView::_initMount - Mount node index '%i' out of range for '%s'", mMountNode, - mModelName + _getModelAssetId() ); mMountNode = -1; @@ -720,11 +716,11 @@ void GuiObjectView::_initMount() // Look up node on the mounted model from // which to mount to the primary model's node. - if (!getMountedModelResource()) return; - S32 mountPoint = getMountedModelResource()->findNode( "mountPoint" ); + if (!getMountedModel()) return; + S32 mountPoint = getMountedModel()->findNode( "mountPoint" ); if( mountPoint != -1 ) { - getMountedModelResource()->getNodeWorldTransform(mountPoint, &mMountTransform), + getMountedModel()->getNodeWorldTransform(mountPoint, &mMountTransform), mMountTransform.inverse(); } } @@ -745,7 +741,7 @@ DefineEngineMethod( GuiObjectView, getModel, const char*, (),, "@return Name of the displayed model.\n\n" "@see GuiControl") { - return Con::getReturnBuffer( object->getModel() ); + return Con::getReturnBuffer( object->_getModelAssetId() ); } //----------------------------------------------------------------------------- @@ -775,7 +771,7 @@ DefineEngineMethod( GuiObjectView, getMountedModel, const char*, (),, "@return Name of the mounted model.\n\n" "@see GuiControl") { - return Con::getReturnBuffer( object->getMountedModel() ); + return Con::getReturnBuffer( object->_getMountedModelAssetId() ); } //----------------------------------------------------------------------------- diff --git a/Engine/source/T3D/guiObjectView.h b/Engine/source/T3D/guiObjectView.h index 887e32a41..a6e3535b9 100644 --- a/Engine/source/T3D/guiObjectView.h +++ b/Engine/source/T3D/guiObjectView.h @@ -37,7 +37,7 @@ class LightInfo; /// A control that displays a TSShape in its view. -class GuiObjectView : public GuiTSCtrl +class GuiObjectView : public GuiTSCtrl, protected AssetPtrCallback { public: @@ -70,15 +70,8 @@ class GuiObjectView : public GuiTSCtrl /// @{ ///Model loaded for display. - DECLARE_SHAPEASSET(GuiObjectView, Model, onModelChanged); - static bool _setModelData(void* obj, const char* index, const char* data)\ - { - bool ret = false; - GuiObjectView* object = static_cast(obj); - ret = object->setObjectModel(StringTable->insert(data)); - return ret; - } - void onModelChanged(); + DECLARE_SHAPEASSET_REFACTOR(GuiObjectView, Model) + TSShapeInstance* mModelInstance; /// Name of skin to use on model. String mSkinName; @@ -109,15 +102,7 @@ class GuiObjectView : public GuiTSCtrl /// @{ ///Model to mount to the primary model. - DECLARE_SHAPEASSET(GuiObjectView, MountedModel, onMountedModelChanged); - static bool _setMountedModelData(void* obj, const char* index, const char* data)\ - { - bool ret = false; - GuiObjectView* object = static_cast(obj); - ret = object->setMountedObject(StringTable->insert(data)); - return ret; - } - void onMountedModelChanged(); + DECLARE_SHAPEASSET_REFACTOR(GuiObjectView, MountedModel) TSShapeInstance* mMountedModelInstance; /// @@ -284,7 +269,17 @@ class GuiObjectView : public GuiTSCtrl static void initPersistFields(); DECLARE_CONOBJECT( GuiObjectView ); - DECLARE_DESCRIPTION( "A control that shows a TSShape model." ); + DECLARE_DESCRIPTION( "A control that shows a TSShape model." ); + +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override + { + if (mModelAsset.notNull()) + setObjectModel(_getModelAssetId()); + + if (mMountedModelAsset.notNull()) + setMountedObject(_getMountedModelAssetId()); + } }; #endif // !_GUIOBJECTVIEW_H_ diff --git a/Engine/source/T3D/missionMarker.cpp b/Engine/source/T3D/missionMarker.cpp index a18523ef7..7290ccc97 100644 --- a/Engine/source/T3D/missionMarker.cpp +++ b/Engine/source/T3D/missionMarker.cpp @@ -444,14 +444,14 @@ void SpawnSphere::unpackUpdate(NetConnection * con, BitStream * stream) { delete mShapeInstance; ShapeBaseData *spawnedDatablock = dynamic_cast(Sim::findObject(mSpawnDataBlock.c_str())); - if (spawnedDatablock && spawnedDatablock->mShape) + if (spawnedDatablock && spawnedDatablock->getShape()) { - mShapeInstance = new TSShapeInstance(spawnedDatablock->mShape); + mShapeInstance = new TSShapeInstance(spawnedDatablock->getShape()); } else if (mDataBlock) { - if (mDataBlock->mShape) - mShapeInstance = new TSShapeInstance(mDataBlock->mShape); + if (mDataBlock->getShape()) + mShapeInstance = new TSShapeInstance(mDataBlock->getShape()); } } stream->read(&mSpawnName); diff --git a/Engine/source/T3D/physics/physicsDebris.cpp b/Engine/source/T3D/physics/physicsDebris.cpp index d6d5eff8e..35fee7a34 100644 --- a/Engine/source/T3D/physics/physicsDebris.cpp +++ b/Engine/source/T3D/physics/physicsDebris.cpp @@ -74,7 +74,12 @@ PhysicsDebrisData::PhysicsDebrisData() lifetime = 5.0f; lifetimeVariance = 0.0f; - INIT_ASSET(Shape); + mShapeAsset.registerRefreshNotify(this); +} + +PhysicsDebrisData::~PhysicsDebrisData() +{ + mShapeAsset.unregisterRefreshNotify(); } bool PhysicsDebrisData::onAdd() @@ -96,12 +101,12 @@ bool PhysicsDebrisData::preload( bool server, String &errorStr ) { // Create a dummy shape to force the generation of shaders and materials // during the level load and not during gameplay. - TSShapeInstance *pDummy = new TSShapeInstance( mShape, !server ); + TSShapeInstance *pDummy = new TSShapeInstance( getShape(), !server); delete pDummy; } else { - errorStr = String::ToString("PhysicsDebrisData::load: Couldn't load shape asset \"%s\"", mShapeAssetId); + errorStr = String::ToString("PhysicsDebrisData::load: Couldn't load shape asset \"%s\"", _getShapeAssetId()); return false; } @@ -113,12 +118,9 @@ void PhysicsDebrisData::initPersistFields() docsURL; addGroup( "Shapes" ); - addProtectedField( "shapeFile", TypeShapeFilename, Offset( mShapeName, PhysicsDebrisData ), &_setShapeData, &defaultProtectedGetFn, - "@brief Path to the .DAE or .DTS file to use for this shape.\n\n" - "Compatable with Live-Asset Reloading.", AbstractClassRep::FIELD_HideInInspectors); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, PhysicsDebrisData, "@brief Shape to use with this debris.\n\n" + "Compatable with Live-Asset Reloading."); - INITPERSISTFIELD_SHAPEASSET(Shape, PhysicsDebrisData, "@brief Shape to use with this debris.\n\n" - "Compatable with Live-Asset Reloading."); endGroup( "Shapes" ); addGroup("Rendering"); @@ -216,7 +218,7 @@ void PhysicsDebrisData::packData(BitStream* stream) stream->write( waterDampingScale ); stream->write( buoyancyDensity ); - PACKDATA_ASSET(Shape); + PACKDATA_ASSET_REFACTOR(Shape); } void PhysicsDebrisData::unpackData(BitStream* stream) @@ -237,7 +239,7 @@ void PhysicsDebrisData::unpackData(BitStream* stream) stream->read( &waterDampingScale ); stream->read( &buoyancyDensity ); - UNPACKDATA_ASSET(Shape); + UNPACKDATA_ASSET_REFACTOR(Shape); } DefineEngineMethod( PhysicsDebrisData, preload, void, (), , @@ -248,7 +250,7 @@ DefineEngineMethod( PhysicsDebrisData, preload, void, (), , { String errorStr; - object->_setShape(object->getShape()); + object->_setShape(object->_getShapeAssetId()); if( !object->preload( false, errorStr ) ) Con::errorf( "PhsysicsDebrisData::preload - error: %s", errorStr.c_str() ); @@ -362,7 +364,7 @@ bool PhysicsDebris::onAdd() } // Setup our bounding box - mObjBox = mDataBlock->mShape->mBounds; + mObjBox = mDataBlock->getShape()->mBounds; resetWorldBox(); // Add it to the client scene. @@ -625,7 +627,7 @@ void PhysicsDebris::_createFragments() if ( !mWorld ) return; - TSShape *shape = mDataBlock->mShape; + TSShape *shape = mDataBlock->getShape(); mShapeInstance = new TSShapeInstance( shape, true ); mShapeInstance->animate(); @@ -699,7 +701,7 @@ void PhysicsDebris::_findNodes( U32 colNode, Vector &nodeIds ) // 1. Visible mesh nodes are siblings of the collision node under a common parent dummy node // 2. Collision node is a child of its visible mesh node - TSShape *shape = mDataBlock->mShape; + TSShape *shape = mDataBlock->getShape(); S32 itr = shape->nodes[colNode].parentIndex; itr = shape->nodes[itr].firstChild; diff --git a/Engine/source/T3D/physics/physicsDebris.h b/Engine/source/T3D/physics/physicsDebris.h index 9b9ae6861..3b5371647 100644 --- a/Engine/source/T3D/physics/physicsDebris.h +++ b/Engine/source/T3D/physics/physicsDebris.h @@ -42,7 +42,7 @@ class TSShape; //************************************************************************** // Debris Data //************************************************************************** -class PhysicsDebrisData : public GameBaseData +class PhysicsDebrisData : public GameBaseData, protected AssetPtrCallback { typedef GameBaseData Parent; @@ -86,10 +86,10 @@ public: /// Is rendererd during shadow passes. bool castShadows; - DECLARE_SHAPEASSET(PhysicsDebrisData, Shape, onShapeChanged); - DECLARE_ASSET_SETGET(PhysicsDebrisData, Shape); + DECLARE_SHAPEASSET_REFACTOR(PhysicsDebrisData, Shape) PhysicsDebrisData(); + virtual ~PhysicsDebrisData(); bool onAdd() override; bool preload( bool server, String &errorStr ) override; @@ -97,13 +97,14 @@ public: void packData( BitStream *stream ) override; void unpackData( BitStream *stream ) override; - void onShapeChanged() + DECLARE_CONOBJECT( PhysicsDebrisData ); + +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { reloadOnLocalClient(); } - DECLARE_CONOBJECT( PhysicsDebrisData ); - }; diff --git a/Engine/source/T3D/physics/physicsShape.cpp b/Engine/source/T3D/physics/physicsShape.cpp index 805531c8b..55e488009 100644 --- a/Engine/source/T3D/physics/physicsShape.cpp +++ b/Engine/source/T3D/physics/physicsShape.cpp @@ -78,11 +78,12 @@ PhysicsShapeData::PhysicsShapeData() buoyancyDensity( 0.0f ), simType( SimType_ClientServer ) { - INIT_ASSET(Shape); + mShapeAsset.registerRefreshNotify(this); } PhysicsShapeData::~PhysicsShapeData() { + mShapeAsset.unregisterRefreshNotify(); } void PhysicsShapeData::initPersistFields() @@ -90,7 +91,7 @@ void PhysicsShapeData::initPersistFields() docsURL; addGroup("Shapes"); - INITPERSISTFIELD_SHAPEASSET(Shape, PhysicsShapeData, "@brief Shape asset to be used with this physics object.\n\n" + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, PhysicsShapeData, "@brief Shape asset to be used with this physics object.\n\n" "Compatable with Live-Asset Reloading. ") addField( "debris", TYPEID< SimObjectRef >(), Offset( debris, PhysicsShapeData ), @@ -180,7 +181,7 @@ void PhysicsShapeData::packData( BitStream *stream ) { Parent::packData( stream ); - PACKDATA_ASSET(Shape); + PACKDATA_ASSET_REFACTOR(Shape); stream->write( mass ); stream->write( dynamicFriction ); @@ -204,7 +205,7 @@ void PhysicsShapeData::unpackData( BitStream *stream ) { Parent::unpackData(stream); - UNPACKDATA_ASSET(Shape); + UNPACKDATA_ASSET_REFACTOR(Shape); stream->read( &mass ); stream->read( &dynamicFriction ); @@ -246,22 +247,22 @@ void PhysicsShapeData::_onResourceChanged( const Torque::Path &path ) { return; } - if ( path != Path(mShapeAsset->getShapeFilePath()) ) + if ( path != Path(mShapeAsset->getShapeFile()) ) return; - _setShape(getShape()); + _setShape(_getShapeAssetId()); // Reload the changed shape. PhysicsCollisionRef reloadcolShape; - if ( !mShape ) + if ( !getShape()) { Con::warnf( ConsoleLogEntry::General, "PhysicsShapeData::_onResourceChanged: Could not reload %s.", path.getFileName().c_str() ); return; } // Reload the collision shape. - reloadcolShape = mShape->buildColShape( false, Point3F::One ); + reloadcolShape = getShape()->buildColShape( false, Point3F::One ); if ( bool(reloadcolShape)) colShape = reloadcolShape; @@ -286,31 +287,31 @@ bool PhysicsShapeData::preload( bool server, String &errorBuffer ) if (mShapeAsset.notNull()) { - if (bool(mShape) == false) + if (bool(getShape()) == false) { - errorBuffer = String::ToString("PhysicsShapeData: Couldn't load shape \"%s\"", mShapeAssetId); + errorBuffer = String::ToString("PhysicsShapeData: Couldn't load shape \"%s\"", _getShapeAssetId()); return false; } - if (!server && !mShape->preloadMaterialList(mShape.getPath()) && NetConnection::filesWereDownloaded()) + if (!server && !getShape()->preloadMaterialList(getShape().getPath()) && NetConnection::filesWereDownloaded()) shapeError = true; } // Prepare the shared physics collision shape. - if ( !colShape && mShape) + if ( !colShape && getShape()) { - colShape = mShape->buildColShape( false, Point3F::One ); + colShape = getShape()->buildColShape( false, Point3F::One ); // If we got here and didn't get a collision shape then // we need to fail... can't have a shape without collision. if ( !colShape ) { //no collision so we create a simple box collision shape from the shapes bounds and alert the user - Con::warnf( "PhysicsShapeData::preload - No collision found for shape '%s', auto-creating one", mShapeAssetId); - Point3F halfWidth = mShape->mBounds.getExtents() * 0.5f; + Con::warnf( "PhysicsShapeData::preload - No collision found for shape '%s', auto-creating one", _getShapeAssetId()); + Point3F halfWidth = getShape()->mBounds.getExtents() * 0.5f; colShape = PHYSICSMGR->createCollision(); MatrixF centerXfm(true); - centerXfm.setPosition(mShape->mBounds.getCenter()); + centerXfm.setPosition(getShape()->mBounds.getCenter()); colShape->addBox(halfWidth, centerXfm); return true; } @@ -703,11 +704,11 @@ bool PhysicsShape::_createShape() mAmbientSeq = -1; PhysicsShapeData *db = getDataBlock(); - if ( !db || !db->mShape) + if ( !db || !db->getShape()) return false; // Set the world box. - mObjBox = db->mShape->mBounds; + mObjBox = db->getShape()->mBounds; resetWorldBox(); // If this is the server and its a client only simulation @@ -721,11 +722,11 @@ bool PhysicsShape::_createShape() } // Create the shape instance. - mShapeInst = new TSShapeInstance( db->mShape, isClientObject() ); + mShapeInst = new TSShapeInstance( db->getShape(), isClientObject() ); if ( isClientObject() ) { - mAmbientSeq = db->mShape->findSequence( "ambient" ); + mAmbientSeq = db->getShape()->findSequence( "ambient" ); _initAmbient(); } diff --git a/Engine/source/T3D/physics/physicsShape.h b/Engine/source/T3D/physics/physicsShape.h index 466e39ebf..7419c2442 100644 --- a/Engine/source/T3D/physics/physicsShape.h +++ b/Engine/source/T3D/physics/physicsShape.h @@ -51,7 +51,7 @@ class PhysicsDebrisData; class ExplosionData; -class PhysicsShapeData : public GameBaseData +class PhysicsShapeData : public GameBaseData, protected AssetPtrCallback { typedef GameBaseData Parent; @@ -74,8 +74,7 @@ public: public: - DECLARE_SHAPEASSET(PhysicsShapeData, Shape, onShapeChanged); - DECLARE_ASSET_SETGET(PhysicsShapeData, Shape); + DECLARE_SHAPEASSET_REFACTOR(PhysicsShapeData, Shape) /// The shared unscaled collision shape. PhysicsCollisionRef colShape; @@ -135,7 +134,8 @@ public: SimObjectRef< ExplosionData > explosion; SimObjectRef< PhysicsShapeData > destroyedShape; - void onShapeChanged() +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { reloadOnLocalClient(); } diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index c736ff022..e6b779eb0 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -297,7 +297,7 @@ PlayerData::PlayerData() imageAnimPrefixFP = StringTable->EmptyString(); for (U32 i=0; iaddThread(); // Extract ground transform velocity from animations @@ -516,7 +516,7 @@ bool PlayerData::preload(bool server, String &errorStr) ActionAnimationDef *sp = &ActionAnimationList[i]; dp->name = sp->name; dp->dir.set(sp->dir.x,sp->dir.y,sp->dir.z); - dp->sequence = mShape->findSequence(sp->name); + dp->sequence = getShape()->findSequence(sp->name); // If this is a sprint action and is missing a sequence, attempt to use // the standard run ones. @@ -524,7 +524,7 @@ bool PlayerData::preload(bool server, String &errorStr) { S32 offset = i-SprintRootAnim; ActionAnimationDef *standDef = &ActionAnimationList[RootAnim+offset]; - dp->sequence = mShape->findSequence(standDef->name); + dp->sequence = getShape()->findSequence(standDef->name); } dp->velocityScale = true; @@ -532,12 +532,12 @@ bool PlayerData::preload(bool server, String &errorStr) if (dp->sequence != -1) getGroundInfo(si,thread,dp); } - for (S32 b = 0; b < mShape->sequences.size(); b++) + for (S32 b = 0; b < getShape()->sequences.size(); b++) { if (!isTableSequence(b)) { dp->sequence = b; - dp->name = mShape->getName(mShape->sequences[b].nameIndex); + dp->name = getShape()->getName(getShape()->sequences[b].nameIndex); dp->velocityScale = false; getGroundInfo(si,thread,dp++); } @@ -554,17 +554,17 @@ bool PlayerData::preload(bool server, String &errorStr) lookAction = c; // Resolve spine - spineNode[0] = mShape->findNode("Bip01 Pelvis"); - spineNode[1] = mShape->findNode("Bip01 Spine"); - spineNode[2] = mShape->findNode("Bip01 Spine1"); - spineNode[3] = mShape->findNode("Bip01 Spine2"); - spineNode[4] = mShape->findNode("Bip01 Neck"); - spineNode[5] = mShape->findNode("Bip01 Head"); + spineNode[0] = getShape()->findNode("Bip01 Pelvis"); + spineNode[1] = getShape()->findNode("Bip01 Spine"); + spineNode[2] = getShape()->findNode("Bip01 Spine1"); + spineNode[3] = getShape()->findNode("Bip01 Spine2"); + spineNode[4] = getShape()->findNode("Bip01 Neck"); + spineNode[5] = getShape()->findNode("Bip01 Head"); // Recoil animations - recoilSequence[0] = mShape->findSequence("light_recoil"); - recoilSequence[1] = mShape->findSequence("medium_recoil"); - recoilSequence[2] = mShape->findSequence("heavy_recoil"); + recoilSequence[0] = getShape()->findSequence("light_recoil"); + recoilSequence[1] = getShape()->findSequence("medium_recoil"); + recoilSequence[2] = getShape()->findSequence("heavy_recoil"); } // Convert pickupRadius to a delta of boundingBox @@ -607,26 +607,26 @@ bool PlayerData::preload(bool server, String &errorStr) { bool shapeError = false; - if (mShapeFPAssetId[i] != StringTable->EmptyString()) + if (mShapeFPAsset[i].notNull()) { - if (!mShapeFP[i]) + if (!getShapeFP(i)) { - errorStr = String::ToString("PlayerData: Couldn't load mounted image %d shape \"%s\"", i, mShapeFPAssetId[i]); + errorStr = String::ToString("PlayerData: Couldn't load mounted image %d shape \"%s\"", i, _getShapeFPAssetId(i)); return false; } - if (!server && !mShapeFP[i]->preloadMaterialList(mShapeFP[i].getPath()) && NetConnection::filesWereDownloaded()) + if (!server && !getShapeFP(i)->preloadMaterialList(getShapeFP(i).getPath()) && NetConnection::filesWereDownloaded()) shapeError = true; if (computeCRC) { - Con::printf("Validation required for mounted image %d shape: %s", i, mShapeFPAssetId[i]); + Con::printf("Validation required for mounted image %d shape: %s", i, _getShapeFPAssetId(i)); - Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShapeFP[i].getPath()); + Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(getShapeFP(i).getPath()); if (!fileRef) { - errorStr = String::ToString("PlayerData: Mounted image %d loading failed, shape \"%s\" is not found.", i, mShapeFP[i].getPath().getFullPath().c_str()); + errorStr = String::ToString("PlayerData: Mounted image %d loading failed, shape \"%s\" is not found.", i, getShapeFP(i).getPath().getFullPath().c_str()); return false; } @@ -634,7 +634,7 @@ bool PlayerData::preload(bool server, String &errorStr) mCRCFP[i] = fileRef->getChecksum(); else if (mCRCFP[i] != fileRef->getChecksum()) { - errorStr = String::ToString("PlayerData: Mounted image %d shape \"%s\" does not match version on server.", i, mShapeFPAssetId[i]); + errorStr = String::ToString("PlayerData: Mounted image %d shape \"%s\" does not match version on server.", i, _getShapeFPAssetId(i)); return false; } } @@ -1134,13 +1134,8 @@ void PlayerData::initPersistFields() // Mounted images arrays addArray( "Mounted Images", ShapeBase::MaxMountedImages ); - addProtectedField("shapeNameFP", TypeShapeFilename, Offset(mShapeFPName, PlayerData), &_setShapeFPData, &defaultProtectedGetFn, ShapeBase::MaxMountedImages, - "@brief File name of this player's shape that will be used in conjunction with the corresponding mounted image.\n\n" - "These optional parameters correspond to each mounted image slot to indicate a shape that is rendered " - "in addition to the mounted image shape. Typically these are a player's arms (or arm) that is " - "animated along with the mounted image's state animation sequences.\n", AbstractClassRep::FIELD_HideInInspectors); - INITPERSISTFIELD_SHAPEASSET_ARRAY(ShapeFP, ShapeBase::MaxMountedImages, PlayerData, "@brief File name of this player's shape that will be used in conjunction with the corresponding mounted image.\n\n" + INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages, PlayerData, "@brief File name of this player's shape that will be used in conjunction with the corresponding mounted image.\n\n" "These optional parameters correspond to each mounted image slot to indicate a shape that is rendered " "in addition to the mounted image shape. Typically these are a player's arms (or arm) that is " "animated along with the mounted image's state animation sequences.\n"); @@ -1340,14 +1335,14 @@ void PlayerData::packData(BitStream* stream) stream->writeString(imageAnimPrefixFP); for (U32 i=0; iwrite(mCRCFP[i]); } } + + PACKDATA_ASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages) } void PlayerData::unpackData(BitStream* stream) @@ -1520,14 +1515,14 @@ void PlayerData::unpackData(BitStream* stream) imageAnimPrefixFP = stream->readSTString(); for (U32 i=0; iread(&(mCRCFP[i])); } } + + UNPACKDATA_ASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages) } @@ -1863,9 +1858,9 @@ bool Player::onNewDataBlock( GameBaseData *dptr, bool reload ) { for (U32 i=0; imShapeFP[i])) + if (bool(mDataBlock->getShapeFP(i))) { - mShapeFPInstance[i] = new TSShapeInstance(mDataBlock->mShapeFP[i], isClientObject()); + mShapeFPInstance[i] = new TSShapeInstance(mDataBlock->getShapeFP(i), isClientObject()); mShapeFPInstance[i]->cloneMaterialList(); @@ -7511,8 +7506,8 @@ F32 Player::getAnimationDurationByID(U32 anim_id) if (anim_id == BAD_ANIM_ID) return 0.0f; S32 seq_id = mDataBlock->actionList[anim_id].sequence; - if (seq_id >= 0 && seq_id < mDataBlock->mShape->sequences.size()) - return mDataBlock->mShape->sequences[seq_id].duration; + if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size()) + return mDataBlock->getShape()->sequences[seq_id].duration; return 0.0f; } @@ -7524,8 +7519,8 @@ bool Player::isBlendAnimation(const char* name) return false; S32 seq_id = mDataBlock->actionList[anim_id].sequence; - if (seq_id >= 0 && seq_id < mDataBlock->mShape->sequences.size()) - return mDataBlock->mShape->sequences[seq_id].isBlend(); + if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size()) + return mDataBlock->getShape()->sequences[seq_id].isBlend(); return false; } diff --git a/Engine/source/T3D/player.h b/Engine/source/T3D/player.h index f1f10e29a..a3a426a14 100644 --- a/Engine/source/T3D/player.h +++ b/Engine/source/T3D/player.h @@ -58,7 +58,7 @@ class OpenVRTrackedObject; //---------------------------------------------------------------------------- -struct PlayerData: public ShapeBaseData { +struct PlayerData: public ShapeBaseData /*protected AssetPtrCallback < already in shapebasedata. */ { typedef ShapeBaseData Parent; enum Constants { RecoverDelayBits = 7, @@ -82,8 +82,7 @@ struct PlayerData: public ShapeBaseData { /// that we don't create a TSThread on the player if we don't /// need to. - DECLARE_SHAPEASSET_ARRAY(PlayerData, ShapeFP, ShapeBase::MaxMountedImages, onShapeChanged); ///< Used to render with mounted images in first person [optional] - DECLARE_ASSET_ARRAY_SETGET(PlayerData, ShapeFP); + DECLARE_SHAPEASSET_ARRAY_REFACTOR(PlayerData, ShapeFP, ShapeBase::MaxMountedImages) StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify /// animation sequences played in first person. [optional] @@ -391,6 +390,11 @@ struct PlayerData: public ShapeBaseData { DECLARE_CALLBACK( void, onEnterMissionArea, ( Player* obj ) ); DECLARE_CALLBACK( void, onLeaveMissionArea, ( Player* obj ) ); /// @} +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override + { + reloadOnLocalClient(); + } }; diff --git a/Engine/source/T3D/projectile.cpp b/Engine/source/T3D/projectile.cpp index 58c6f3aa6..cf8df1065 100644 --- a/Engine/source/T3D/projectile.cpp +++ b/Engine/source/T3D/projectile.cpp @@ -145,7 +145,7 @@ U32 Projectile::smProjectileWarpTicks = 5; // ProjectileData::ProjectileData() { - INIT_ASSET(ProjectileShape); + mProjectileShapeAsset.registerRefreshNotify(this); INIT_ASSET(ProjectileSound); @@ -223,7 +223,7 @@ ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : G CLONE_ASSET(ProjectileSound); lightDesc = other.lightDesc; lightDescId = other.lightDescId; // -- for pack/unpack of lightDesc ptr - CLONE_ASSET(ProjectileShape);// -- TSShape loads using mProjectileShapeName + mProjectileShapeAsset = other.mProjectileShapeAsset;// -- TSShape loads using mProjectileShapeName activateSeq = other.activateSeq; // -- from projectileShape sequence "activate" maintainSeq = other.maintainSeq; // -- from projectileShape sequence "maintain" particleEmitter = other.particleEmitter; @@ -237,9 +237,7 @@ void ProjectileData::initPersistFields() { docsURL; addGroup("Shapes"); - addProtectedField("projectileShapeName", TypeShapeFilename, Offset(mProjectileShapeName, ProjectileData), &_setProjectileShapeData, &defaultProtectedGetFn, - "@brief File path to the model of the projectile.\n\n", AbstractClassRep::FIELD_HideInInspectors); - INITPERSISTFIELD_SHAPEASSET(ProjectileShape, ProjectileData, "@brief The model of the projectile.\n\n"); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(ProjectileShape, ProjectileData, "@brief The model of the projectile.\n\n"); addField("scale", TypePoint3F, Offset(scale, ProjectileData), "@brief Scale to apply to the projectile's size.\n\n" "@note This is applied after SceneObject::scale\n"); @@ -383,20 +381,20 @@ bool ProjectileData::preload(bool server, String &errorStr) Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockid(lightDesc): %d", lightDescId); } - if (mProjectileShapeAssetId != StringTable->EmptyString()) + if (mProjectileShapeAsset.notNull()) { //If we've got a shapeAsset assigned for our projectile, but we failed to load the shape data itself, report the error - if (!mProjectileShape) + if (!getProjectileShape()) { - errorStr = String::ToString("ProjectileData::load: Couldn't load shape \"%s\"", mProjectileShapeAssetId); + errorStr = String::ToString("ProjectileData::load: Couldn't load shape \"%s\"", _getProjectileShapeAssetId()); return false; } else { - activateSeq = mProjectileShape->findSequence("activate"); - maintainSeq = mProjectileShape->findSequence("maintain"); + activateSeq = getProjectileShape()->findSequence("activate"); + maintainSeq = getProjectileShape()->findSequence("maintain"); - TSShapeInstance* pDummy = new TSShapeInstance(mProjectileShape, !server); + TSShapeInstance* pDummy = new TSShapeInstance(getProjectileShape(), !server); delete pDummy; } } @@ -409,7 +407,7 @@ void ProjectileData::packData(BitStream* stream) { Parent::packData(stream); - PACKDATA_ASSET(ProjectileShape); + PACKDATA_ASSET_REFACTOR(ProjectileShape); stream->writeFlag(faceViewer); if(stream->writeFlag(scale.x != 1 || scale.y != 1 || scale.z != 1)) @@ -474,7 +472,7 @@ void ProjectileData::unpackData(BitStream* stream) { Parent::unpackData(stream); - UNPACKDATA_ASSET(ProjectileShape); + UNPACKDATA_ASSET_REFACTOR(ProjectileShape); faceViewer = stream->readFlag(); if(stream->readFlag()) @@ -800,9 +798,9 @@ bool Projectile::onAdd() } else { - if (bool(mDataBlock->mProjectileShape)) + if (bool(mDataBlock->getProjectileShape())) { - mProjectileShape = new TSShapeInstance(mDataBlock->mProjectileShape, isClientObject()); + mProjectileShape = new TSShapeInstance(mDataBlock->getProjectileShape(), isClientObject()); if (mDataBlock->activateSeq != -1) { @@ -841,8 +839,8 @@ bool Projectile::onAdd() processAfter(mSourceObject); // Setup our bounding box - if (bool(mDataBlock->mProjectileShape) == true) - mObjBox = mDataBlock->mProjectileShape->mBounds; + if (bool(mDataBlock->getProjectileShape()) == true) + mObjBox = mDataBlock->getProjectileShape()->mBounds; else mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0)); diff --git a/Engine/source/T3D/projectile.h b/Engine/source/T3D/projectile.h index 2ca827ea7..af1b3e8d3 100644 --- a/Engine/source/T3D/projectile.h +++ b/Engine/source/T3D/projectile.h @@ -63,7 +63,7 @@ class Projectile; //-------------------------------------------------------------------------- /// Datablock for projectiles. This class is the base class for all other projectiles. -class ProjectileData : public GameBaseData +class ProjectileData : public GameBaseData, protected AssetPtrCallback { typedef GameBaseData Parent; @@ -71,8 +71,7 @@ protected: bool onAdd() override; public: - DECLARE_SHAPEASSET(ProjectileData, ProjectileShape, onShapeChanged); - DECLARE_ASSET_SETGET(ProjectileData, ProjectileShape); + DECLARE_SHAPEASSET_REFACTOR(ProjectileData, ProjectileShape) /// Set to true if it is a billboard and want it to always face the viewer, false otherwise bool faceViewer; @@ -154,7 +153,8 @@ public: ProjectileData(const ProjectileData&, bool = false); bool allowSubstitutions() const override { return true; } - void onShapeChanged() +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { reloadOnLocalClient(); } diff --git a/Engine/source/T3D/proximityMine.cpp b/Engine/source/T3D/proximityMine.cpp index fd02fc091..86c9807b6 100644 --- a/Engine/source/T3D/proximityMine.cpp +++ b/Engine/source/T3D/proximityMine.cpp @@ -144,11 +144,11 @@ bool ProximityMineData::preload( bool server, String& errorStr ) } } - if ( mShape ) + if ( getShape() ) { // Lookup animation sequences - armingSequence = mShape->findSequence( "armed" ); - triggerSequence = mShape->findSequence( "triggered" ); + armingSequence = getShape()->findSequence( "armed" ); + triggerSequence = getShape()->findSequence( "triggered" ); } return true; diff --git a/Engine/source/T3D/rigidShape.cpp b/Engine/source/T3D/rigidShape.cpp index 8a453b065..b87bcc056 100644 --- a/Engine/source/T3D/rigidShape.cpp +++ b/Engine/source/T3D/rigidShape.cpp @@ -310,7 +310,7 @@ bool RigidShapeData::preload(bool server, String &errorStr) if (!collisionDetails.size() || collisionDetails[0] == -1) { Con::errorf("RigidShapeData::preload failed: Rigid shapes must define a collision-1 detail"); - errorStr = String::ToString("RigidShapeData: Couldn't load shape asset \"%s\"", mShapeAsset.getAssetId()); + errorStr = String::ToString("RigidShapeData: Couldn't load shape asset \"%s\"", getShapeAsset().getAssetId()); return false; } diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 92f5f4da6..af078b2e2 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -201,13 +201,12 @@ ShapeBaseData::ShapeBaseData() inheritEnergyFromMount( false ), mAIControllData(NULL) { - INIT_ASSET(Shape); - INIT_ASSET(DebrisShape); - dMemset( mountPointNode, -1, sizeof( S32 ) * SceneObject::NumMountPoints ); remap_txr_tags = NULL; remap_buffer = NULL; silent_bbox_check = false; + mShapeAsset.registerRefreshNotify(this); + mDebrisShapeAsset.registerRefreshNotify(this); } ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : GameBaseData(other, temp_clone) @@ -217,13 +216,13 @@ ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : Game shadowProjectionDistance = other.shadowProjectionDistance; shadowSphereAdjust = other.shadowSphereAdjust; cloakTexName = other.cloakTexName; - CLONE_ASSET(Shape); + mShapeAsset = other.mShapeAsset; cubeDescName = other.cubeDescName; cubeDescId = other.cubeDescId; reflectorDesc = other.reflectorDesc; debris = other.debris; debrisID = other.debrisID; // -- for pack/unpack of debris ptr - CLONE_ASSET(DebrisShape); + mDebrisShapeAsset = other.mDebrisShapeAsset; explosion = other.explosion; explosionID = other.explosionID; // -- for pack/unpack of explosion ptr underwaterExplosion = other.underwaterExplosion; @@ -245,7 +244,6 @@ ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : Game cameraMaxFov = other.cameraMaxFov; cameraCanBank = other.cameraCanBank; mountedImagesBank = other.mountedImagesBank; - mShape = other.mShape; // -- TSShape loaded using shapeName mCRC = other.mCRC; // -- from shape, used to verify client shape computeCRC = other.computeCRC; eyeNode = other.eyeNode; // -- from shape node "eye" @@ -304,6 +302,9 @@ ShapeBaseData::~ShapeBaseData() if (remap_buffer && !isTempClone()) dFree(remap_buffer); + + mShapeAsset.unregisterRefreshNotify(); + mDebrisShapeAsset.unregisterRefreshNotify(); } bool ShapeBaseData::preload(bool server, String &errorStr) @@ -342,156 +343,159 @@ bool ShapeBaseData::preload(bool server, String &errorStr) "ShapeBaseData::preload: invalid debris data"); } - if( bool(mDebrisShape)) + if(mDebrisShapeAsset.notNull()) { - TSShapeInstance* pDummy = new TSShapeInstance(mDebrisShape, !server); + TSShapeInstance* pDummy = new TSShapeInstance(getDebrisShape(), !server); delete pDummy; } } S32 i; - U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset); - if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback) + if (mShapeAsset.notNull()) { - if (!server && !mShape->preloadMaterialList(mShape.getPath()) && NetConnection::filesWereDownloaded()) - shapeError = true; - - if(computeCRC) + U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset); + if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback) { - Con::printf("Validation required for shape asset: %s", mShapeAsset.getAssetId()); + if (!server && !getShape()->preloadMaterialList(getShape().getPath()) && NetConnection::filesWereDownloaded()) + shapeError = true; - Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShapeAsset->getShapePath()); - - if (!fileRef) + if (computeCRC) { - errorStr = String::ToString("ShapeBaseData: Couldn't load shape asset \"%s\"", mShapeAsset.getAssetId()); - return false; - } + Con::printf("Validation required for shape asset: %s", mShapeAsset.getAssetId()); - if(server) - mCRC = fileRef->getChecksum(); - else if(mCRC != fileRef->getChecksum()) - { - errorStr = String::ToString("Shape asset \"%s\" does not match version on server.", mShapeAsset.getAssetId()); - return false; - } - } - // Resolve details and camera node indexes. - static const String sCollisionStr( "collision-" ); + Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShapeAsset->getShapeFile()); - for (i = 0; i < mShape->details.size(); i++) - { - const String &name = mShape->names[mShape->details[i].nameIndex]; - - if (name.compare( sCollisionStr, sCollisionStr.length(), String::NoCase ) == 0) - { - collisionDetails.push_back(i); - collisionBounds.increment(); - - mShape->computeBounds(collisionDetails.last(), collisionBounds.last()); - mShape->getAccelerator(collisionDetails.last()); - - if (!mShape->mBounds.isContained(collisionBounds.last())) + if (!fileRef) { - if (!silent_bbox_check) - Con::warnf("Warning: shape asset %s collision detail %d (Collision-%d) bounds exceed that of shape.", mShapeAsset.getAssetId(), collisionDetails.size() - 1, collisionDetails.last()); - collisionBounds.last() = mShape->mBounds; - } - else if (collisionBounds.last().isValidBox() == false) - { - if (!silent_bbox_check) - Con::errorf("Error: shape asset %s-collision detail %d (Collision-%d) bounds box invalid!", mShapeAsset.getAssetId(), collisionDetails.size() - 1, collisionDetails.last()); - collisionBounds.last() = mShape->mBounds; + errorStr = String::ToString("ShapeBaseData: Couldn't load shape asset \"%s\"", mShapeAsset.getAssetId()); + return false; } - // The way LOS works is that it will check to see if there is a LOS detail that matches - // the the collision detail + 1 + MaxCollisionShapes (this variable name should change in - // the future). If it can't find a matching LOS it will simply use the collision instead. - // We check for any "unmatched" LOS's further down - LOSDetails.increment(); - - String buff = String::ToString("LOS-%d", i + 1 + MaxCollisionShapes); - U32 los = mShape->findDetail(buff); - if (los == -1) - LOSDetails.last() = i; - else - LOSDetails.last() = los; - } - } - - // Snag any "unmatched" LOS details - static const String sLOSStr( "LOS-" ); - - for (i = 0; i < mShape->details.size(); i++) - { - const String &name = mShape->names[mShape->details[i].nameIndex]; - - if (name.compare( sLOSStr, sLOSStr.length(), String::NoCase ) == 0) - { - // See if we already have this LOS - bool found = false; - for (U32 j = 0; j < LOSDetails.size(); j++) + if (server) + mCRC = fileRef->getChecksum(); + else if (mCRC != fileRef->getChecksum()) { - if (LOSDetails[j] == i) + errorStr = String::ToString("Shape asset \"%s\" does not match version on server.", mShapeAsset.getAssetId()); + return false; + } + } + // Resolve details and camera node indexes. + static const String sCollisionStr("collision-"); + + for (i = 0; i < getShape()->details.size(); i++) + { + const String& name = getShape()->names[getShape()->details[i].nameIndex]; + + if (name.compare(sCollisionStr, sCollisionStr.length(), String::NoCase) == 0) + { + collisionDetails.push_back(i); + collisionBounds.increment(); + + getShape()->computeBounds(collisionDetails.last(), collisionBounds.last()); + getShape()->getAccelerator(collisionDetails.last()); + + if (!getShape()->mBounds.isContained(collisionBounds.last())) { + if (!silent_bbox_check) + Con::warnf("Warning: shape asset %s collision detail %d (Collision-%d) bounds exceed that of shape.", mShapeAsset.getAssetId(), collisionDetails.size() - 1, collisionDetails.last()); + collisionBounds.last() = getShape()->mBounds; + } + else if (collisionBounds.last().isValidBox() == false) + { + if (!silent_bbox_check) + Con::errorf("Error: shape asset %s-collision detail %d (Collision-%d) bounds box invalid!", mShapeAsset.getAssetId(), collisionDetails.size() - 1, collisionDetails.last()); + collisionBounds.last() = getShape()->mBounds; + } + + // The way LOS works is that it will check to see if there is a LOS detail that matches + // the the collision detail + 1 + MaxCollisionShapes (this variable name should change in + // the future). If it can't find a matching LOS it will simply use the collision instead. + // We check for any "unmatched" LOS's further down + LOSDetails.increment(); + + String buff = String::ToString("LOS-%d", i + 1 + MaxCollisionShapes); + U32 los = getShape()->findDetail(buff); + if (los == -1) + LOSDetails.last() = i; + else + LOSDetails.last() = los; + } + } + + // Snag any "unmatched" LOS details + static const String sLOSStr("LOS-"); + + for (i = 0; i < getShape()->details.size(); i++) + { + const String& name = getShape()->names[getShape()->details[i].nameIndex]; + + if (name.compare(sLOSStr, sLOSStr.length(), String::NoCase) == 0) + { + // See if we already have this LOS + bool found = false; + for (U32 j = 0; j < LOSDetails.size(); j++) + { + if (LOSDetails[j] == i) + { found = true; break; + } } - } - if (!found) - LOSDetails.push_back(i); + if (!found) + LOSDetails.push_back(i); + } } - } - debrisDetail = mShape->findDetail("Debris-17"); - eyeNode = mShape->findNode("eye"); - earNode = mShape->findNode( "ear" ); - if( earNode == -1 ) - earNode = eyeNode; - cameraNode = mShape->findNode("cam"); - if (cameraNode == -1) - cameraNode = eyeNode; + debrisDetail = getShape()->findDetail("Debris-17"); + eyeNode = getShape()->findNode("eye"); + earNode = getShape()->findNode("ear"); + if (earNode == -1) + earNode = eyeNode; + cameraNode = getShape()->findNode("cam"); + if (cameraNode == -1) + cameraNode = eyeNode; - // Resolve mount point node indexes - for (i = 0; i < SceneObject::NumMountPoints; i++) { - char fullName[256]; - dSprintf(fullName,sizeof(fullName),"mount%d",i); - mountPointNode[i] = mShape->findNode(fullName); - } + // Resolve mount point node indexes + for (i = 0; i < SceneObject::NumMountPoints; i++) { + char fullName[256]; + dSprintf(fullName, sizeof(fullName), "mount%d", i); + mountPointNode[i] = getShape()->findNode(fullName); + } - // find the AIRepairNode - hardcoded to be the last node in the array... - mountPointNode[AIRepairNode] = mShape->findNode("AIRepairNode"); + // find the AIRepairNode - hardcoded to be the last node in the array... + mountPointNode[AIRepairNode] = getShape()->findNode("AIRepairNode"); - // - hulkSequence = mShape->findSequence("Visibility"); - damageSequence = mShape->findSequence("Damage"); + // + hulkSequence = getShape()->findSequence("Visibility"); + damageSequence = getShape()->findSequence("Damage"); - // - F32 w = mShape->mBounds.len_y() / 2; - if (cameraMaxDist < w) - cameraMaxDist = w; - // just parse up the string and collect the remappings in txr_tag_remappings. - if (!server && remap_txr_tags != NULL && remap_txr_tags != StringTable->insert("")) - { - txr_tag_remappings.clear(); - if (remap_buffer) - dFree(remap_buffer); - - remap_buffer = dStrdup(remap_txr_tags); - - char* remap_token = dStrtok(remap_buffer, " \t"); - while (remap_token != NULL) + // + F32 w = getShape()->mBounds.len_y() / 2; + if (cameraMaxDist < w) + cameraMaxDist = w; + // just parse up the string and collect the remappings in txr_tag_remappings. + if (!server && remap_txr_tags != NULL && remap_txr_tags != StringTable->insert("")) { - char* colon = dStrchr(remap_token, ':'); - if (colon) + txr_tag_remappings.clear(); + if (remap_buffer) + dFree(remap_buffer); + + remap_buffer = dStrdup(remap_txr_tags); + + char* remap_token = dStrtok(remap_buffer, " \t"); + while (remap_token != NULL) { - *colon = '\0'; - txr_tag_remappings.increment(); - txr_tag_remappings.last().old_tag = remap_token; - txr_tag_remappings.last().new_tag = colon+1; + char* colon = dStrchr(remap_token, ':'); + if (colon) + { + *colon = '\0'; + txr_tag_remappings.increment(); + txr_tag_remappings.last().old_tag = remap_token; + txr_tag_remappings.last().new_tag = colon + 1; + } + remap_token = dStrtok(NULL, " \t"); } - remap_token = dStrtok(NULL, " \t"); } } } @@ -543,12 +547,12 @@ void ShapeBaseData::initPersistFields() { docsURL; addGroup( "Shapes" ); - INITPERSISTFIELD_SHAPEASSET(Shape, ShapeBaseData, "The source shape asset."); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, ShapeBaseData, "The source shape asset."); addField("computeCRC", TypeBool, Offset(computeCRC, ShapeBaseData), "If true, verify that the CRC of the client's shape model matches the " "server's CRC for the shape model when loaded by the client."); addField("silentBBoxValidation", TypeBool, Offset(silent_bbox_check, ShapeBaseData)); - INITPERSISTFIELD_SHAPEASSET(DebrisShape, ShapeBaseData, "The shape asset to use for auto-generated breakups via blowup(). @note may not be functional."); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(DebrisShape, ShapeBaseData, "The shape asset to use for auto-generated breakups via blowup(). @note may not be functional."); endGroup( "Shapes" ); addGroup("Movement"); addField("aiControllerData", TYPEID< AIControllerData >(), Offset(mAIControllData, ShapeBaseData), @@ -677,12 +681,12 @@ DefineEngineMethod( ShapeBaseData, checkDeployPos, bool, ( TransformF txfm ),, "@note This is a server side only check, and is not actually limited to spawning.\n") { - if (bool(object->mShape) == false) + if (bool(object->getShape()) == false) return false; MatrixF mat = txfm.getMatrix(); - Box3F objBox = object->mShape->mBounds; + Box3F objBox = object->getShape()->mBounds; Point3F boxCenter = (objBox.minExtents + objBox.maxExtents) * 0.5f; objBox.minExtents = boxCenter + (objBox.minExtents - boxCenter) * 0.9f; objBox.maxExtents = boxCenter + (objBox.maxExtents - boxCenter) * 0.9f; @@ -752,8 +756,8 @@ void ShapeBaseData::packData(BitStream* stream) stream->write(shadowProjectionDistance); stream->write(shadowSphereAdjust); - PACKDATA_ASSET(Shape); - PACKDATA_ASSET(DebrisShape); + PACKDATA_ASSET_REFACTOR(Shape); + PACKDATA_ASSET_REFACTOR(DebrisShape); stream->writeString(cloakTexName); if(stream->writeFlag(mass != gShapeBaseDataProto.mass)) @@ -829,8 +833,8 @@ void ShapeBaseData::unpackData(BitStream* stream) stream->read(&shadowProjectionDistance); stream->read(&shadowSphereAdjust); - UNPACKDATA_ASSET(Shape); - UNPACKDATA_ASSET(DebrisShape); + UNPACKDATA_ASSET_REFACTOR(Shape); + UNPACKDATA_ASSET_REFACTOR(DebrisShape); cloakTexName = stream->readSTString(); if(stream->readFlag()) @@ -918,17 +922,6 @@ void ShapeBaseData::unpackData(BitStream* stream) silent_bbox_check = stream->readFlag(); } -// -// -void ShapeBaseData::onShapeChanged() -{ - reloadOnLocalClient(); -} - -void ShapeBaseData::onDebrisChanged() -{ - reloadOnLocalClient(); -} //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- @@ -1210,12 +1203,12 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload ) // Even if loadShape succeeds, there may not actually be // a shape assigned to this object. - if (bool(mDataBlock->mShape)) { + if (bool(mDataBlock->getShape())) { delete mShapeInstance; if (isClientObject() && mDataBlock->txr_tag_remappings.size() > 0) { // temporarily substitute material tags with alternates - TSMaterialList* mat_list = mDataBlock->mShape->materialList; + TSMaterialList* mat_list = mDataBlock->getShape()->materialList; if (mat_list) { for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++) @@ -1235,7 +1228,7 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload ) } } } - mShapeInstance = new TSShapeInstance(mDataBlock->mShape, isClientObject()); + mShapeInstance = new TSShapeInstance(mDataBlock->getShape(), isClientObject()); if (isClientObject()) { mShapeInstance->cloneMaterialList(); @@ -1243,7 +1236,7 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload ) // restore the material tags to original form if (mDataBlock->txr_tag_remappings.size() > 0) { - TSMaterialList* mat_list = mDataBlock->mShape->materialList; + TSMaterialList* mat_list = mDataBlock->getShape()->materialList; if (mat_list) { for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++) @@ -1269,11 +1262,11 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload ) } } - mObjBox = mDataBlock->mShape->mBounds; + mObjBox = mDataBlock->getShape()->mBounds; resetWorldBox(); // Set the initial mesh hidden state. - mMeshHidden.setSize(mDataBlock->mShape->objects.size()); + mMeshHidden.setSize(mDataBlock->getShape()->objects.size()); mMeshHidden.clear(); // Initialize the threads @@ -1297,11 +1290,11 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload ) AssertFatal(prevDB != NULL, "ShapeBase::onNewDataBlock - how did you have a sequence playing without a prior datablock?"); - const TSShape* prevShape = prevDB->mShape; + const TSShape* prevShape = prevDB->getShape(); const TSShape::Sequence& prevSeq = prevShape->sequences[st.sequence]; const String& prevSeqName = prevShape->names[prevSeq.nameIndex]; - st.sequence = mDataBlock->mShape->findSequence(prevSeqName); + st.sequence = mDataBlock->getShape()->findSequence(prevSeqName); if (st.sequence != -1) { @@ -1971,13 +1964,13 @@ void ShapeBase::blowUp() TSShapeInstance *debShape = NULL; - if( mDataBlock->mDebrisShape == NULL ) + if( mDataBlock->getDebrisShape() == NULL) { return; } else { - debShape = new TSShapeInstance( mDataBlock->mDebrisShape, true); + debShape = new TSShapeInstance( mDataBlock->getDebrisShape(), true); } @@ -2049,7 +2042,7 @@ Point3F ShapeBase::getAIRepairPoint() //---------------------------------------------------------------------------- void ShapeBase::getNodeTransform(const char* nodeName, MatrixF* outMat) { - S32 nodeIDx = mDataBlock->getShapeResource()->findNode(nodeName); + S32 nodeIDx = mDataBlock->getShape()->findNode(nodeName); const MatrixF& xfm = isMounted() ? mMount.xfm : MatrixF::Identity; MatrixF nodeTransform(xfm); @@ -2216,7 +2209,7 @@ void ShapeBase::getNodeTransform(const char* nodeName, const MatrixF& xfm, Matri if (!mShapeInstance) return; - S32 nodeIDx = mDataBlock->getShapeResource()->findNode(nodeName); + S32 nodeIDx = mDataBlock->getShape()->findNode(nodeName); MatrixF nodeTransform(xfm); const Point3F& scale = getScale(); @@ -5027,7 +5020,7 @@ void ShapeBase::_updateHiddenMeshes() void ShapeBase::setMeshHidden( const char *meshName, bool forceHidden ) { - setMeshHidden( mDataBlock->mShape->findObject( meshName ), forceHidden ); + setMeshHidden( mDataBlock->getShape()->findObject(meshName), forceHidden); } void ShapeBase::setMeshHidden( S32 meshIndex, bool forceHidden ) @@ -5096,7 +5089,7 @@ void ShapeBase::dumpMeshVisibility() { const TSShapeInstance::MeshObjectInstance &mesh = meshes[i]; - const String &meshName = mDataBlock->mShape->getMeshName( i ); + const String &meshName = mDataBlock->getShape()->getMeshName( i ); Con::printf( "%d - %s - forceHidden = %s, visibility = %f", i, @@ -5378,8 +5371,8 @@ F32 ShapeBase::getAnimationDurationByID(U32 anim_id) return 0.0f; S32 seq_id = (S32) anim_id; - if (seq_id >= 0 && seq_id < mDataBlock->mShape->sequences.size()) - return mDataBlock->mShape->sequences[seq_id].duration; + if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size()) + return mDataBlock->getShape()->sequences[seq_id].duration; return 0.0f; } @@ -5391,8 +5384,8 @@ bool ShapeBase::isBlendAnimation(const char* name) return false; S32 seq_id = (S32) anim_id; - if (seq_id >= 0 && seq_id < mDataBlock->mShape->sequences.size()) - return mDataBlock->mShape->sequences[seq_id].isBlend(); + if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size()) + return mDataBlock->getShape()->sequences[seq_id].isBlend(); return false; } @@ -5404,11 +5397,11 @@ const char* ShapeBase::getLastClipName(U32 clip_tag) S32 seq_id = (S32) last_anim_id; - S32 idx = mDataBlock->mShape->sequences[seq_id].nameIndex; - if (idx < 0 || idx >= mDataBlock->mShape->names.size()) + S32 idx = mDataBlock->getShape()->sequences[seq_id].nameIndex; + if (idx < 0 || idx >= mDataBlock->getShape()->names.size()) return 0; - return mDataBlock->mShape->names[idx]; + return mDataBlock->getShape()->names[idx]; } // diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index 46f9a3270..a8807a026 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -140,7 +140,8 @@ class ShapeBaseConvex : public Convex //-------------------------------------------------------------------------- -struct ShapeBaseImageData: public GameBaseData { +struct ShapeBaseImageData: public GameBaseData, protected AssetPtrCallback +{ private: typedef GameBaseData Parent; @@ -380,11 +381,7 @@ struct ShapeBaseImageData: public GameBaseData { F32 scriptAnimTransitionTime; ///< The amount of time to transition between the previous sequence and new sequence ///< when the script prefix has changed. - DECLARE_SHAPEASSET_ARRAY(ShapeBaseImageData, Shape, MaxShapes, onShapeChanged); ///< Name of shape to render. - DECLARE_ASSET_ARRAY_SETGET(ShapeBaseImageData, Shape); - - //DECLARE_SHAPEASSET(ShapeBaseImageData, ShapeFP); ///< Name of shape to render in first person (optional). - //DECLARE_ASSET_SETGET(ShapeBaseImageData, ShapeFP); + DECLARE_SHAPEASSET_ARRAY_REFACTOR(ShapeBaseImageData, Shape, MaxShapes) ///< Name of shape to render. StringTableEntry imageAnimPrefix; ///< Passed along to the mounting shape to modify /// animation sequences played in 3rd person. [optional] @@ -519,6 +516,12 @@ struct ShapeBaseImageData: public GameBaseData { DECLARE_CALLBACK( void, onMount, ( SceneObject* obj, S32 slot, F32 dt ) ); DECLARE_CALLBACK( void, onUnmount, ( SceneObject* obj, S32 slot, F32 dt ) ); /// @} + +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override + { + reloadOnLocalClient(); + } }; typedef ShapeBaseImageData::LightType ShapeBaseImageLightType; @@ -533,7 +536,7 @@ DefineEnumType( ShapeBaseImageRecoilState ); //-------------------------------------------------------------------------- /// @nosubgrouping -struct ShapeBaseData : public GameBaseData { +struct ShapeBaseData : public GameBaseData, protected AssetPtrCallback { private: typedef GameBaseData Parent; @@ -553,8 +556,7 @@ public: F32 shadowProjectionDistance; F32 shadowSphereAdjust; - DECLARE_SHAPEASSET(ShapeBaseData, Shape, onShapeChanged); - DECLARE_ASSET_SETGET(ShapeBaseData, Shape); + DECLARE_SHAPEASSET_REFACTOR(ShapeBaseData, Shape) StringTableEntry cloakTexName; @@ -570,8 +572,7 @@ public: DebrisData * debris; S32 debrisID; - DECLARE_SHAPEASSET(ShapeBaseData, DebrisShape, onDebrisChanged); - DECLARE_ASSET_SETGET(ShapeBaseData, DebrisShape); + DECLARE_SHAPEASSET_REFACTOR(ShapeBaseData, DebrisShape) ExplosionData* explosion; S32 explosionID; @@ -691,10 +692,14 @@ public: Vector txr_tag_remappings; bool silent_bbox_check; - void onShapeChanged(); - void onDebrisChanged(); public: ShapeBaseData(const ShapeBaseData&, bool = false); + +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override + { + reloadOnLocalClient(); + } }; diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index bf1687649..95281cbd6 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/Engine/source/T3D/shapeImage.cpp @@ -293,8 +293,7 @@ ShapeBaseImageData::ShapeBaseImageData() isAnimated[i] = false; hasFlash[i] = false; shapeIsValid[i] = false; - - INIT_ASSET_ARRAY(Shape, i); + mShapeAsset[i].registerRefreshNotify(this); } shakeCamera = false; @@ -454,10 +453,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) if (!mShapeAsset[i].isNull()) { - // Resolve shapename - mShape[i] = mShapeAsset[i]->getShapeResource(); - - if (!bool(mShape[i])) { + if (!bool(getShape(i))) { errorStr = String::ToString("Unable to load shape asset: %s", mShapeAsset[i]->getAssetId()); return false; } @@ -465,7 +461,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) { Con::printf("Validation required for shape asset: %s", mShapeAsset[i]->getAssetId()); - Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShape[i].getPath()); + Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(getShape(i).getPath()); if (!fileRef) { @@ -485,23 +481,23 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) } // Resolve nodes & build mount transform - eyeMountNode[i] = mShape[i]->findNode("eyeMount"); - eyeNode[i] = mShape[i]->findNode("eye"); + eyeMountNode[i] = getShape(i)->findNode("eyeMount"); + eyeNode[i] = getShape(i)->findNode("eye"); if (eyeNode[i] == -1) eyeNode[i] = eyeMountNode[i]; - ejectNode[i] = mShape[i]->findNode("ejectPoint"); - muzzleNode[i] = mShape[i]->findNode("muzzlePoint"); - retractNode[i] = mShape[i]->findNode("retractionPoint"); + ejectNode[i] = getShape(i)->findNode("ejectPoint"); + muzzleNode[i] = getShape(i)->findNode("muzzlePoint"); + retractNode[i] = getShape(i)->findNode("retractionPoint"); mountTransform[i] = mountOffset; - S32 node = mShape[i]->findNode("mountPoint"); + S32 node = getShape(i)->findNode("mountPoint"); if (node != -1) { MatrixF total(1); do { MatrixF nmat; QuatF q; - TSTransform::setMatrix(mShape[i]->defaultRotations[node].getQuatF(&q), mShape[i]->defaultTranslations[node],&nmat); + TSTransform::setMatrix(getShape(i)->defaultRotations[node].getQuatF(&q), getShape(i)->defaultTranslations[node],&nmat); total.mul(nmat); - node = mShape[i]->nodes[node].parentIndex; + node = getShape(i)->nodes[node].parentIndex; } while(node != -1); total.inverse(); @@ -514,7 +510,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) for (U32 j = 0; j < MaxStates; j++) { StateData& s = state[j]; if (stateSequence[j] && stateSequence[j][0]) - s.sequence[i] = mShape[i]->findSequence(stateSequence[j]); + s.sequence[i] = getShape(i)->findSequence(stateSequence[j]); if (s.sequence[i] != -1) { // This state has an animation sequence @@ -525,7 +521,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) char bufferVis[128]; dStrncpy(bufferVis, stateSequence[j], 100); dStrcat(bufferVis, "_vis", 128); - s.sequenceVis[i] = mShape[i]->findSequence(bufferVis); + s.sequenceVis[i] = getShape(i)->findSequence(bufferVis); } if (s.sequenceVis[i] != -1) { @@ -537,13 +533,13 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) s.ignoreLoadedForReady = stateIgnoreLoadedForReady[j]; if (stateEmitterNode[j] && stateEmitterNode[j][0]) - s.emitterNode[i] = mShape[i]->findNode(stateEmitterNode[j]); + s.emitterNode[i] = getShape(i)->findNode(stateEmitterNode[j]); if (s.emitterNode[i] == -1) s.emitterNode[i] = muzzleNode[i]; } - ambientSequence[i] = mShape[i]->findSequence("ambient"); - spinSequence[i] = mShape[i]->findSequence("spin"); + ambientSequence[i] = getShape(i)->findSequence("ambient"); + spinSequence[i] = getShape(i)->findSequence("spin"); shapeIsValid[i] = true; } @@ -567,7 +563,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) { if( shapeIsValid[i] ) { - TSShapeInstance* pDummy = new TSShapeInstance(mShape[i], !server); + TSShapeInstance* pDummy = new TSShapeInstance(getShape(i), !server); delete pDummy; } } @@ -628,8 +624,8 @@ void ShapeBaseImageData::initPersistFields() { docsURL; addGroup("Shapes"); - INITPERSISTFIELD_SHAPEASSET_ARRAY(Shape, MaxShapes, ShapeBaseImageData, "The shape asset to use for this image in the third person") - //addProtectedField("shapeFileFP", TypeShapeFilename, Offset(mShapeName[1], ShapeBaseImageData), _setShapeData, defaultProtectedGetFn, "deprecated alias for ShapeFPFile/Asset", AbstractClassRep::FIELD_HideInInspectors); + INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(Shape, MaxShapes, ShapeBaseImageData, "The shape assets for this shape image") + addField("casing", TYPEID< DebrisData >(), Offset(casing, ShapeBaseImageData), "@brief DebrisData datablock to use for ejected casings.\n\n" "@see stateEjectShell"); @@ -1002,10 +998,7 @@ void ShapeBaseImageData::packData(BitStream* stream) } } - for (U32 j = 0; j < MaxShapes; ++j) - { - PACKDATA_ASSET_ARRAY(Shape, j); // shape 0 for normal use, shape 1 for first person use (optional) - } + PACKDATA_ASSET_ARRAY_REFACTOR(Shape, MaxShapes); // shape 0 for normal use, shape 1 for first person use (optional) stream->writeString(imageAnimPrefix); stream->writeString(imageAnimPrefixFP); @@ -1186,10 +1179,7 @@ void ShapeBaseImageData::unpackData(BitStream* stream) } } - for (U32 j = 0; j < MaxShapes; ++j) - { - UNPACKDATA_ASSET_ARRAY(Shape, j); // shape 0 for normal use, shape 1 for first person use (optional) - } + UNPACKDATA_ASSET_ARRAY_REFACTOR(Shape, MaxShapes); // shape 0 for normal use, shape 1 for first person use (optional) imageAnimPrefix = stream->readSTString(); imageAnimPrefixFP = stream->readSTString(); @@ -2148,7 +2138,7 @@ S32 ShapeBase::getNodeIndex(U32 imageSlot,StringTableEntry nodeName) { MountedImage& image = mMountedImageList[imageSlot]; if (image.dataBlock) - return image.dataBlock->mShape[getImageShapeIndex(image)]->findNode(nodeName); + return image.dataBlock->getShape(getImageShapeIndex(image))->findNode(nodeName); else return -1; } @@ -2338,7 +2328,7 @@ void ShapeBase::setImage( U32 imageSlot, for (U32 i=0; ishapeIsValid[i]) - image.shapeInstance[i] = new TSShapeInstance(image.dataBlock->mShape[i], isClientObject()); + image.shapeInstance[i] = new TSShapeInstance(image.dataBlock->getShape(i), isClientObject()); } if (isClientObject()) diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 6bfd7e127..2d9f61477 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -151,13 +151,14 @@ TSStatic::TSStatic() mAnimOffset = 0.0f; mAnimSpeed = 1.0f; - INIT_ASSET(Shape); + mShapeAsset.registerRefreshNotify(this); } TSStatic::~TSStatic() { delete mConvexList; mConvexList = NULL; + mShapeAsset.unregisterRefreshNotify(); } ImplementEnumType(TSMeshType, @@ -180,11 +181,7 @@ void TSStatic::initPersistFields() docsURL; addGroup("Shape"); - INITPERSISTFIELD_SHAPEASSET(Shape, TSStatic, "Model to use for this TSStatic"); - - addProtectedField("shapeName", TypeShapeFilename, Offset(mShapeName, TSStatic), - &TSStatic::_setShapeData, &defaultProtectedGetFn, - "%Path and filename of the model file (.DTS, .DAE) to use for this TSStatic. Legacy field. Any loose files assigned here will attempt to be auto-imported in as an asset.", AbstractClassRep::FIELD_HideInInspectors); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, TSStatic, "Model to use for this TSStatic"); endGroup("Shape"); @@ -393,59 +390,55 @@ bool TSStatic::_createShape() mAmbientThread = NULL; //mShape = NULL; - U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset); - if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback) + if (mShapeAsset.notNull()) { - //Special-case handling, usually because we set noShape - mShape = mShapeAsset->getShapeResource(); - } + if (!getShape()) + { + Con::errorf("TSStatic::_createShape() - Shape Asset %s had no valid shape!", mShapeAsset.getAssetId()); + return false; + } - if (!mShape) - { - Con::errorf("TSStatic::_createShape() - Shape Asset %s had no valid shape!", mShapeAsset.getAssetId()); - return false; - } + if (isClientObject() && + !getShape()->preloadMaterialList(getShape().getPath()) && + NetConnection::filesWereDownloaded()) + return false; - if (isClientObject() && - !mShape->preloadMaterialList(mShape.getPath()) && - NetConnection::filesWereDownloaded()) - return false; + mObjBox = getShape()->mBounds; + resetWorldBox(); - mObjBox = mShape->mBounds; - resetWorldBox(); + mShapeInstance = new TSShapeInstance(getShape(), isClientObject()); + mShapeInstance->resetMaterialList(); + mShapeInstance->cloneMaterialList(); - mShapeInstance = new TSShapeInstance(mShape, isClientObject()); - mShapeInstance->resetMaterialList(); - mShapeInstance->cloneMaterialList(); + if (isGhost()) + { + // Reapply the current skin + mAppliedSkinName = ""; + reSkin(); - if (isGhost()) - { - // Reapply the current skin - mAppliedSkinName = ""; - reSkin(); + updateMaterials(); + } - updateMaterials(); - } + prepCollision(); - prepCollision(); + // Find the "ambient" animation if it exists + S32 ambientSeq = getShape()->findSequence("ambient"); - // Find the "ambient" animation if it exists - S32 ambientSeq = mShape->findSequence("ambient"); + if (ambientSeq > -1 && !mAmbientThread) + mAmbientThread = mShapeInstance->addThread(); - if (ambientSeq > -1 && !mAmbientThread) - mAmbientThread = mShapeInstance->addThread(); + if ( mAmbientThread ) + mShapeInstance->setSequence(mAmbientThread, ambientSeq, mAnimOffset); - if ( mAmbientThread ) - mShapeInstance->setSequence(mAmbientThread, ambientSeq, mAnimOffset); - - // Resolve CubeReflectorDesc. - if (cubeDescName.isNotEmpty()) - { - Sim::findObject(cubeDescName, reflectorDesc); - } - else if (cubeDescId > 0) - { - Sim::findObject(cubeDescId, reflectorDesc); + // Resolve CubeReflectorDesc. + if (cubeDescName.isNotEmpty()) + { + Sim::findObject(cubeDescName, reflectorDesc); + } + else if (cubeDescId > 0) + { + Sim::findObject(cubeDescId, reflectorDesc); + } } //Set up the material slot vars for easy manipulation @@ -533,20 +526,20 @@ void TSStatic::prepCollision() if (mCollisionType == CollisionMesh || mCollisionType == VisibleMesh) { - mShape->findColDetails(mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails, mCollisionLOD); + getShape()->findColDetails(mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails, mCollisionLOD); if (mDecalType == mCollisionType) { mDecalDetailsPtr = &mCollisionDetails; } else if (mDecalType == CollisionMesh || mDecalType == VisibleMesh) { - mShape->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD); + getShape()->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD); mDecalDetailsPtr = &mDecalDetails; } } else if (mDecalType == CollisionMesh || mDecalType == VisibleMesh) { - mShape->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD); + getShape()->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD); mDecalDetailsPtr = &mDecalDetails; } @@ -564,12 +557,12 @@ void TSStatic::_updatePhysics() if (mCollisionType == Bounds) { MatrixF offset(true); - offset.setPosition(mShape->center); + offset.setPosition(getShape()->center); colShape = PHYSICSMGR->createCollision(); colShape->addBox(getObjBox().getExtents() * 0.5f * mObjScale, offset); } else - colShape = mShape->buildColShape(mCollisionType == VisibleMesh, getScale()); + colShape = getShape()->buildColShape(mCollisionType == VisibleMesh, getScale()); if (colShape) { @@ -958,7 +951,7 @@ U32 TSStatic::packUpdate(NetConnection* con, U32 mask, BitStream* stream) if (stream->writeFlag(mask & AdvancedStaticOptionsMask)) { - PACK_ASSET(con, Shape); + PACK_ASSET_REFACTOR(con, Shape); stream->write((U32)mDecalType); @@ -1075,7 +1068,7 @@ void TSStatic::unpackUpdate(NetConnection* con, BitStream* stream) if (stream->readFlag()) // AdvancedStaticOptionsMask { - UNPACK_ASSET(con, Shape); + UNPACK_ASSET_REFACTOR(con, Shape); stream->read((U32*)&mDecalType); @@ -1597,9 +1590,9 @@ void TSStatic::updateMaterials() String path; if (mShapeAsset->isAssetValid()) - path = mShapeAsset->getShapeFileName(); + path = mShapeAsset->getShapeFile(); else - path = mShapeName; + path = mShapeFile; pMatList->setTextureLookupPath(path); @@ -1781,7 +1774,7 @@ DefineEngineMethod(TSStatic, changeMaterial, void, (const char* mapTo, Material* return; } - TSMaterialList* shapeMaterialList = object->getShapeResource()->materialList; + TSMaterialList* shapeMaterialList = object->getShape()->materialList; // Check the mapTo name exists for this shape S32 matIndex = shapeMaterialList->getMaterialNameList().find_next(String(mapTo)); @@ -1821,7 +1814,7 @@ DefineEngineMethod(TSStatic, getModelFile, const char*, (), , "@endtsexample\n" ) { - return object->getShape(); + return object->getShapeFile(); } void TSStatic::set_special_typing() @@ -1866,14 +1859,14 @@ void TSStatic::setSelectionFlags(U8 flags) bool TSStatic::hasNode(const char* nodeName) { - S32 nodeIDx = getShapeResource()->findNode(nodeName); + S32 nodeIDx = getShape()->findNode(nodeName); return nodeIDx >= 0; } void TSStatic::getNodeTransform(const char *nodeName, const MatrixF &xfm, MatrixF *outMat) { - S32 nodeIDx = getShapeResource()->findNode(nodeName); + S32 nodeIDx = getShape()->findNode(nodeName); MatrixF nodeTransform(xfm); const Point3F& scale = getScale(); diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index fef5ed0bb..150aa59cf 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -101,7 +101,7 @@ public: /// A simple mesh shape with optional ambient animation. -class TSStatic : public SceneObject +class TSStatic : public SceneObject, protected AssetPtrCallback { typedef SceneObject Parent; @@ -186,12 +186,17 @@ protected: ReflectorDesc* reflectorDesc; CubeReflector mCubeReflector; + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override + { + _createShape(); + _updateShouldTick(); + } + protected: Convex* mConvexList; - DECLARE_SHAPEASSET(TSStatic, Shape, onShapeChanged); - DECLARE_ASSET_NET_SETGET(TSStatic, Shape, AdvancedStaticOptionsMask); + DECLARE_SHAPEASSET_NET_REFACTOR(TSStatic, Shape, AdvancedStaticOptionsMask) U32 mShapeHash; Vector mCollisionDetails; @@ -239,7 +244,7 @@ public: DECLARE_CATEGORY("Object \t Simple"); static void initPersistFields(); /// returns the shape asset used for this object - StringTableEntry getTypeHint() const override { return (getShapeAsset()) ? getShapeAsset()->getAssetName(): StringTable->EmptyString(); } + StringTableEntry getTypeHint() const override { return (mShapeAsset.notNull()) ? mShapeAsset->getAssetName(): StringTable->EmptyString(); } static void consoleInit(); static bool _setFieldSkin(void* object, const char* index, const char* data); static const char* _getFieldSkin(void* object, const char* data); diff --git a/Engine/source/T3D/turret/aiTurretShape.cpp b/Engine/source/T3D/turret/aiTurretShape.cpp index 5ad3df020..cedb51af2 100644 --- a/Engine/source/T3D/turret/aiTurretShape.cpp +++ b/Engine/source/T3D/turret/aiTurretShape.cpp @@ -246,8 +246,8 @@ bool AITurretShapeData::preload(bool server, String &errorStr) return false; // We have mShape at this point. Resolve nodes. - scanNode = mShape->findNode("scanPoint"); - aimNode = mShape->findNode("aimPoint"); + scanNode = getShape()->findNode("scanPoint"); + aimNode = getShape()->findNode("aimPoint"); if (scanNode == -1) scanNode = pitchNode; if (scanNode == -1) scanNode = headingNode; @@ -259,7 +259,7 @@ bool AITurretShapeData::preload(bool server, String &errorStr) for (U32 j = 0; j < MaxStates; j++) { StateData& s = state[j]; if (stateSequence[j] && stateSequence[j][0]) - s.sequence = mShape->findSequence(stateSequence[j]); + s.sequence = getShape()->findSequence(stateSequence[j]); if (s.sequence != -1) { // This state has an animation sequence diff --git a/Engine/source/T3D/turret/turretShape.cpp b/Engine/source/T3D/turret/turretShape.cpp index e155663aa..08380da6a 100644 --- a/Engine/source/T3D/turret/turretShape.cpp +++ b/Engine/source/T3D/turret/turretShape.cpp @@ -217,35 +217,35 @@ bool TurretShapeData::preload(bool server, String &errorStr) return false; // We have mShape at this point. Resolve nodes. - headingNode = mShape->findNode("heading"); - pitchNode = mShape->findNode("pitch"); + headingNode = getShape()->findNode("heading"); + pitchNode = getShape()->findNode("pitch"); // Find any mirror pitch nodes for (U32 i = 0; i < NumMirrorDirectionNodes; ++i) { char name[32]; dSprintf(name, 31, "pitch%d", i+1); - pitchNodes[i] = mShape->findNode(name); + pitchNodes[i] = getShape()->findNode(name); dSprintf(name, 31, "heading%d", i+1); - headingNodes[i] = mShape->findNode(name); + headingNodes[i] = getShape()->findNode(name); } // Resolve weapon mount point node indexes for (U32 i = 0; i < ShapeBase::MaxMountedImages; i++) { char fullName[256]; dSprintf(fullName,sizeof(fullName),"weaponMount%d",i); - weaponMountNode[i] = mShape->findNode(fullName); + weaponMountNode[i] = getShape()->findNode(fullName); } // Recoil animations - recoilSequence[0] = mShape->findSequence("light_recoil"); - recoilSequence[1] = mShape->findSequence("medium_recoil"); - recoilSequence[2] = mShape->findSequence("heavy_recoil"); + recoilSequence[0] = getShape()->findSequence("light_recoil"); + recoilSequence[1] = getShape()->findSequence("medium_recoil"); + recoilSequence[2] = getShape()->findSequence("heavy_recoil"); // Optional sequences used when the turret rotates - pitchSequence = mShape->findSequence("pitch"); - headingSequence = mShape->findSequence("heading"); + pitchSequence = getShape()->findSequence("pitch"); + headingSequence = getShape()->findSequence("heading"); return true; } diff --git a/Engine/source/T3D/vehicles/flyingVehicle.cpp b/Engine/source/T3D/vehicles/flyingVehicle.cpp index 24cf33490..4e10c4b2a 100644 --- a/Engine/source/T3D/vehicles/flyingVehicle.cpp +++ b/Engine/source/T3D/vehicles/flyingVehicle.cpp @@ -135,7 +135,7 @@ bool FlyingVehicleData::preload(bool server, String &errorStr) if (!Parent::preload(server, errorStr)) return false; - TSShapeInstance* si = new TSShapeInstance(mShape, false); + TSShapeInstance* si = new TSShapeInstance(getShape(), false); // Resolve objects transmitted from server if (!server) { @@ -164,7 +164,7 @@ bool FlyingVehicleData::preload(bool server, String &errorStr) // Resolve jet nodes for (S32 j = 0; j < MaxJetNodes; j++) - jetNode[j] = mShape->findNode(sJetNode[j]); + jetNode[j] = getShape()->findNode(sJetNode[j]); // maxSpeed = maneuveringForce / minDrag; diff --git a/Engine/source/T3D/vehicles/hoverVehicle.cpp b/Engine/source/T3D/vehicles/hoverVehicle.cpp index 482364bd3..9f536454c 100644 --- a/Engine/source/T3D/vehicles/hoverVehicle.cpp +++ b/Engine/source/T3D/vehicles/hoverVehicle.cpp @@ -332,7 +332,7 @@ bool HoverVehicleData::preload(bool server, String &errorStr) } // Resolve jet nodes for (S32 j = 0; j < MaxJetNodes; j++) - jetNode[j] = mShape->findNode(sJetNode[j]); + jetNode[j] = getShape()->findNode(sJetNode[j]); return true; } diff --git a/Engine/source/T3D/vehicles/vehicle.cpp b/Engine/source/T3D/vehicles/vehicle.cpp index 9ad0abdbf..167ea203a 100644 --- a/Engine/source/T3D/vehicles/vehicle.cpp +++ b/Engine/source/T3D/vehicles/vehicle.cpp @@ -163,7 +163,7 @@ bool VehicleData::preload(bool server, String &errorStr) if (!collisionDetails.size() || collisionDetails[0] == -1) { Con::errorf("VehicleData::preload failed: Vehicle models must define a collision-1 detail"); - errorStr = String::ToString("VehicleData: Couldn't load shape asset \"%s\"", mShapeAsset.getAssetId()); + errorStr = String::ToString("VehicleData: Couldn't load shape asset \"%s\"", getShapeAsset().getAssetId()); return false; } diff --git a/Engine/source/T3D/vehicles/wheeledVehicle.cpp b/Engine/source/T3D/vehicles/wheeledVehicle.cpp index 9f3febd13..ec107eedc 100644 --- a/Engine/source/T3D/vehicles/wheeledVehicle.cpp +++ b/Engine/source/T3D/vehicles/wheeledVehicle.cpp @@ -75,8 +75,6 @@ ConsoleDocClass( WheeledVehicleTire, WheeledVehicleTire::WheeledVehicleTire() { - INIT_ASSET(Shape); - staticFriction = 1; kineticFriction = 0.5f; restitution = 1; @@ -88,15 +86,16 @@ WheeledVehicleTire::WheeledVehicleTire() longitudinalDamping = 1; longitudinalRelaxation = 1; mass = 1.f; + mShapeAsset.registerRefreshNotify(this); } bool WheeledVehicleTire::preload(bool server, String &errorStr) { // Load up the tire shape. ShapeBase has an option to force a // CRC check, this is left out here, but could be easily added. - if (!mShape) + if (!getShape()) { - errorStr = String::ToString("WheeledVehicleTire: Couldn't load shape \"%s\"", mShapeAssetId); + errorStr = String::ToString("WheeledVehicleTire: Couldn't load shape \"%s\"", _getShapeAssetId()); return false; } else @@ -104,7 +103,7 @@ bool WheeledVehicleTire::preload(bool server, String &errorStr) // Determinw wheel radius from the shape's bounding box. // The tire should be built with it's hub axis along the // object's Y axis. - radius = mShape->mBounds.len_z() / 2; + radius = getShape()->mBounds.len_z() / 2; } return true; @@ -113,7 +112,7 @@ bool WheeledVehicleTire::preload(bool server, String &errorStr) void WheeledVehicleTire::initPersistFields() { docsURL; - INITPERSISTFIELD_SHAPEASSET(Shape, WheeledVehicleTire, "The shape to use for the wheel."); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, WheeledVehicleTire, "The shape to use for the wheel."); addFieldV( "mass", TypeRangedF32, Offset(mass, WheeledVehicleTire), &CommonValidators::PositiveFloat, "The mass of the wheel.\nCurrently unused." ); @@ -178,7 +177,7 @@ void WheeledVehicleTire::packData(BitStream* stream) { Parent::packData(stream); - PACKDATA_ASSET(Shape); + PACKDATA_ASSET_REFACTOR(Shape); stream->write(mass); stream->write(staticFriction); @@ -197,7 +196,7 @@ void WheeledVehicleTire::unpackData(BitStream* stream) { Parent::unpackData(stream); - UNPACKDATA_ASSET(Shape); + UNPACKDATA_ASSET_REFACTOR(Shape); stream->read(&mass); stream->read(&staticFriction); @@ -343,7 +342,7 @@ bool WheeledVehicleData::preload(bool server, String &errorStr) // A temporary shape instance is created so that we can // animate the shape and extract wheel information. - TSShapeInstance* si = new TSShapeInstance(mShape, false); + TSShapeInstance* si = new TSShapeInstance(getShape(), false); // Resolve objects transmitted from server if (!server) { @@ -367,14 +366,14 @@ bool WheeledVehicleData::preload(bool server, String &errorStr) // The wheel must have a hub node to operate at all. dSprintf(buff,sizeof(buff),"hub%d",i); - wp->springNode = mShape->findNode(buff); + wp->springNode = getShape()->findNode(buff); if (wp->springNode != -1) { // Check for spring animation.. If there is none we just grab // the current position of the hub. Otherwise we'll animate // and get the position at time 0. dSprintf(buff,sizeof(buff),"spring%d",i); - wp->springSequence = mShape->findSequence(buff); + wp->springSequence = getShape()->findSequence(buff); if (wp->springSequence == -1) si->mNodeTransforms[wp->springNode].getColumn(3, &wp->pos); else { @@ -403,17 +402,17 @@ bool WheeledVehicleData::preload(bool server, String &errorStr) // Check for steering. Should think about normalizing the // steering animation the way the suspension is, but I don't // think it's as critical. - steeringSequence = mShape->findSequence("steering"); + steeringSequence = getShape()->findSequence("steering"); // Brakes - brakeLightSequence = mShape->findSequence("brakelight"); + brakeLightSequence = getShape()->findSequence("brakelight"); // Extract collision planes from shape collision detail level if (collisionDetails[0] != -1) { MatrixF imat(1); SphereF sphere; - sphere.center = mShape->center; - sphere.radius = mShape->mRadius; + sphere.center = getShape()->center; + sphere.radius = getShape()->mRadius; PlaneExtractorPolyList polyList; polyList.mPlaneList = &rigidBody.mPlaneList; polyList.setTransform(&imat, Point3F(1,1,1)); @@ -1579,8 +1578,8 @@ void WheeledVehicle::unpackUpdate(NetConnection *con, BitStream *stream) // Create an instance of the tire for rendering delete wheel->shapeInstance; - wheel->shapeInstance = (wheel->tire->mShape == NULL) ? 0: - new TSShapeInstance(wheel->tire->mShape); + wheel->shapeInstance = (wheel->tire->getShape() == NULL) ? 0: + new TSShapeInstance(wheel->tire->getShape()); } } } diff --git a/Engine/source/T3D/vehicles/wheeledVehicle.h b/Engine/source/T3D/vehicles/wheeledVehicle.h index f208fbf5b..17164a286 100644 --- a/Engine/source/T3D/vehicles/wheeledVehicle.h +++ b/Engine/source/T3D/vehicles/wheeledVehicle.h @@ -39,12 +39,11 @@ class ParticleEmitterData; //---------------------------------------------------------------------------- -struct WheeledVehicleTire: public SimDataBlock +struct WheeledVehicleTire: public SimDataBlock, protected AssetPtrCallback { typedef SimDataBlock Parent; - DECLARE_SHAPEASSET(WheeledVehicleTire, Shape, onShapeChanged); - DECLARE_ASSET_SETGET(WheeledVehicleTire, Shape); + DECLARE_SHAPEASSET_REFACTOR(WheeledVehicleTire, Shape) // Physical properties F32 mass; // Mass of the whole wheel @@ -74,7 +73,8 @@ struct WheeledVehicleTire: public SimDataBlock void packData(BitStream* stream) override; void unpackData(BitStream* stream) override; - void onShapeChanged() +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { reloadOnLocalClient(); } diff --git a/Engine/source/afx/afxMagicMissile.cpp b/Engine/source/afx/afxMagicMissile.cpp index d77ead423..46a8d6371 100644 --- a/Engine/source/afx/afxMagicMissile.cpp +++ b/Engine/source/afx/afxMagicMissile.cpp @@ -141,7 +141,6 @@ U32 Projectile::smProjectileWarpTicks = 5; // afxMagicMissileData::afxMagicMissileData() { - INIT_ASSET(ProjectileShape); INIT_ASSET(ProjectileSound); /* From stock Projectile code... @@ -241,11 +240,13 @@ afxMagicMissileData::afxMagicMissileData() reverse_targeting = false; caster_safety_time = U32_MAX; + + mProjectileShapeAsset.registerRefreshNotify(this); } afxMagicMissileData::afxMagicMissileData(const afxMagicMissileData& other, bool temp_clone) : GameBaseData(other, temp_clone) { - CLONE_ASSET(ProjectileShape); + mProjectileShapeAsset = other.mProjectileShapeAsset; projectileShape = other.projectileShape; // -- TSShape loads using projectileShapeName CLONE_ASSET(ProjectileSound); splash = other.splash; @@ -305,6 +306,8 @@ afxMagicMissileData::~afxMagicMissileData() { if (wiggle_axis) delete [] wiggle_axis; + + mProjectileShapeAsset.unregisterRefreshNotify(); } afxMagicMissileData* afxMagicMissileData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index) @@ -334,7 +337,7 @@ void afxMagicMissileData::initPersistFields() static IRangeValidatorScaled ticksFromMS(TickMs, 0, MaxLifetimeTicks); addGroup("Shapes"); - INITPERSISTFIELD_SHAPEASSET(ProjectileShape, afxMagicMissileData, "Shape for the projectile"); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(ProjectileShape, afxMagicMissileData, "Shape for the projectile"); addField("scale", TypePoint3F, Offset(scale, afxMagicMissileData)); addField("missileShapeScale", TypePoint3F, myOffset(scale)); endGroup("Shapes"); @@ -531,10 +534,10 @@ bool afxMagicMissileData::preload(bool server, String &errorStr) U32 assetStatus = ShapeAsset::getAssetErrCode(mProjectileShapeAsset); if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback) { - projectileShape = mProjectileShapeAsset->getShapeResource(); + projectileShape = getProjectileShape(); if (bool(projectileShape) == false) { - errorStr = String::ToString("afxMagicMissileData::preload: Couldn't load shape \"%s\"", mProjectileShapeAssetId); + errorStr = String::ToString("afxMagicMissileData::preload: Couldn't load shape \"%s\"", _getProjectileShapeAssetId()); return false; } /* From stock Projectile code... @@ -586,7 +589,7 @@ void afxMagicMissileData::packData(BitStream* stream) { Parent::packData(stream); - PACKDATA_ASSET(ProjectileShape); + PACKDATA_ASSET_REFACTOR(ProjectileShape); /* From stock Projectile code... stream->writeFlag(faceViewer); @@ -697,7 +700,7 @@ void afxMagicMissileData::unpackData(BitStream* stream) { Parent::unpackData(stream); - UNPACKDATA_ASSET(ProjectileShape); + UNPACKDATA_ASSET_REFACTOR(ProjectileShape); /* From stock Projectile code... faceViewer = stream->readFlag(); */ diff --git a/Engine/source/afx/afxMagicMissile.h b/Engine/source/afx/afxMagicMissile.h index 8aa8f8084..26f731ae3 100644 --- a/Engine/source/afx/afxMagicMissile.h +++ b/Engine/source/afx/afxMagicMissile.h @@ -56,7 +56,7 @@ class SFXSource; //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// // afxMagicMissileData -class afxMagicMissileData : public GameBaseData +class afxMagicMissileData : public GameBaseData, protected AssetPtrCallback { typedef GameBaseData Parent; @@ -66,16 +66,10 @@ protected: public: enum { MaxLifetimeTicks = 4095 }; - void onShapeChanged() - { - reloadOnLocalClient(); - } - public: // variables set in datablock definition: // Shape related - DECLARE_SHAPEASSET(afxMagicMissileData, ProjectileShape, onShapeChanged); - DECLARE_ASSET_SETGET(afxMagicMissileData, ProjectileShape); + DECLARE_SHAPEASSET_REFACTOR(afxMagicMissileData, ProjectileShape) //StringTableEntry projectileShapeName; //bool hasLight; @@ -228,6 +222,12 @@ public: afxMagicMissileData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0); bool allowSubstitutions() const override { return true; } void gather_cons_defs(Vector& defs); + +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override + { + reloadOnLocalClient(); + } }; //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// diff --git a/Engine/source/afx/ce/afxModel.cpp b/Engine/source/afx/ce/afxModel.cpp index 97746493d..00a2e0f71 100644 --- a/Engine/source/afx/ce/afxModel.cpp +++ b/Engine/source/afx/ce/afxModel.cpp @@ -54,7 +54,6 @@ ConsoleDocClass( afxModelData, afxModelData::afxModelData() { - INIT_ASSET(Shape); sequence = ST_NULLSTRING; seq_rate = 1.0f; seq_offset = 0.0f; @@ -79,11 +78,13 @@ afxModelData::afxModelData() shadowMaxVisibleDistance = 80.0f; shadowProjectionDistance = 10.0f; shadowSphereAdjust = 1.0; + + mShapeAsset.registerRefreshNotify(this); } afxModelData::afxModelData(const afxModelData& other, bool temp_clone) : GameBaseData(other, temp_clone) { - CLONE_ASSET(Shape); + mShapeAsset = other.mShapeAsset; sequence = other.sequence; seq_rate = other.seq_rate; seq_offset = other.seq_offset; @@ -113,6 +114,8 @@ afxModelData::~afxModelData() { if (remap_buffer) dFree(remap_buffer); + + mShapeAsset.unregisterRefreshNotify(); } bool afxModelData::preload(bool server, String &errorStr) @@ -126,9 +129,9 @@ bool afxModelData::preload(bool server, String &errorStr) if (mShapeAsset.notNull()) { - if (!mShape) + if (!getShape()) { - errorStr = String::ToString("afxModelData::load: Failed to load shape \"%s\"", mShapeAssetId); + errorStr = String::ToString("afxModelData::load: Failed to load shape \"%s\"", _getShapeAssetId()); return false; } @@ -160,7 +163,7 @@ bool afxModelData::preload(bool server, String &errorStr) if (txr_tag_remappings.size() == 0) { // this little hack forces the textures to preload - TSShapeInstance* pDummy = new TSShapeInstance(mShape); + TSShapeInstance* pDummy = new TSShapeInstance(getShape()); delete pDummy; } } @@ -174,7 +177,7 @@ void afxModelData::initPersistFields() { docsURL; addGroup("Shapes"); - INITPERSISTFIELD_SHAPEASSET(Shape, afxModelData, "The name of a .dts format file to use for the model."); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, afxModelData, "The name of a .dts format file to use for the model."); endGroup("Shapes"); addGroup("Animation"); @@ -258,7 +261,7 @@ void afxModelData::packData(BitStream* stream) { Parent::packData(stream); - PACKDATA_ASSET(Shape); + PACKDATA_ASSET_REFACTOR(Shape); stream->writeString(sequence); stream->write(seq_rate); stream->write(seq_offset); @@ -289,7 +292,7 @@ void afxModelData::unpackData(BitStream* stream) { Parent::unpackData(stream); - UNPACKDATA_ASSET(Shape); + UNPACKDATA_ASSET_REFACTOR(Shape); sequence = stream->readSTString(); stream->read(&seq_rate); stream->read(&seq_offset); @@ -318,21 +321,10 @@ void afxModelData::unpackData(BitStream* stream) void afxModelData::onPerformSubstitutions() { - if (mShapeAssetId != StringTable->EmptyString()) + if (!getShape()) { - mShapeAsset = mShapeAssetId; - if (mShapeAsset.notNull()) - { - mShape = mShapeAsset->getShapeResource(); - } - - if (!mShape) - { - Con::errorf("afxModelData::onPerformSubstitutions: Failed to load shape \"%s\"", mShapeAssetId); - return; - } - - // REMAP-TEXTURE-TAGS ISSUES? + Con::errorf("afxModelData::onPerformSubstitutions: Failed to load shape \"%s\"", _getShapeAssetId()); + return; } } @@ -406,18 +398,18 @@ bool afxModel::onAdd() return false; // setup our bounding box - if (mDataBlock->mShape) - mObjBox = mDataBlock->mShape->mBounds; + if (mDataBlock->getShape()) + mObjBox = mDataBlock->getShape()->mBounds; else mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1)); // setup the shape instance and sequence - if (mDataBlock->mShape) + if (mDataBlock->getShape()) { if (/*isClientObject() && */mDataBlock->txr_tag_remappings.size() > 0) { // temporarily substitute material tags with alternates - TSMaterialList* mat_list = mDataBlock->mShape->materialList; + TSMaterialList* mat_list = mDataBlock->getShape()->materialList; if (mat_list) { for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++) @@ -438,7 +430,7 @@ bool afxModel::onAdd() } } - shape_inst = new TSShapeInstance(mDataBlock->mShape); + shape_inst = new TSShapeInstance(mDataBlock->getShape()); if (true) // isClientObject()) { @@ -447,7 +439,7 @@ bool afxModel::onAdd() // restore the material tags to original form if (mDataBlock->txr_tag_remappings.size() > 0) { - TSMaterialList* mat_list = mDataBlock->mShape->materialList; + TSMaterialList* mat_list = mDataBlock->getShape()->materialList; if (mat_list) { for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++) @@ -513,14 +505,14 @@ bool afxModel::onAdd() resetWorldBox(); - if (mDataBlock->mShape) + if (mDataBlock->getShape()) { // Scan out the collision hulls... static const String sCollisionStr( "collision-" ); - for (U32 i = 0; i < mDataBlock->mShape->details.size(); i++) + for (U32 i = 0; i < mDataBlock->getShape()->details.size(); i++) { - const String &name = mDataBlock->mShape->names[mDataBlock->mShape->details[i].nameIndex]; + const String &name = mDataBlock->getShape()->names[mDataBlock->getShape()->details[i].nameIndex]; if (name.compare( sCollisionStr, sCollisionStr.length(), String::NoCase ) == 0) { @@ -534,7 +526,7 @@ bool afxModel::onAdd() char buff[128]; dSprintf(buff, sizeof(buff), "LOS-%d", i + 1 + 8/*MaxCollisionShapes*/); - U32 los = mDataBlock->mShape->findDetail(buff); + U32 los = mDataBlock->getShape()->findDetail(buff); if (los == -1) mLOSDetails.last() = i; else @@ -545,9 +537,9 @@ bool afxModel::onAdd() // Snag any "unmatched" LOS details static const String sLOSStr( "LOS-" ); - for (U32 i = 0; i < mDataBlock->mShape->details.size(); i++) + for (U32 i = 0; i < mDataBlock->getShape()->details.size(); i++) { - const String &name = mDataBlock->mShape->names[mDataBlock->mShape->details[i].nameIndex]; + const String &name = mDataBlock->getShape()->names[mDataBlock->getShape()->details[i].nameIndex]; if (name.compare( sLOSStr, sLOSStr.length(), String::NoCase ) == 0) { diff --git a/Engine/source/afx/ce/afxModel.h b/Engine/source/afx/ce/afxModel.h index de2656b8f..ce7fb19ac 100644 --- a/Engine/source/afx/ce/afxModel.h +++ b/Engine/source/afx/ce/afxModel.h @@ -39,12 +39,11 @@ class TSShape; //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// // afxModel Data -struct afxModelData : public GameBaseData +struct afxModelData : public GameBaseData, protected AssetPtrCallback { typedef GameBaseData Parent; - DECLARE_SHAPEASSET(afxModelData, Shape, onShapeChanged); - DECLARE_ASSET_SETGET(afxModelData, Shape); + DECLARE_SHAPEASSET_REFACTOR(afxModelData, Shape) StringTableEntry sequence; @@ -94,13 +93,15 @@ public: static void initPersistFields(); - void onShapeChanged() - { - reloadOnLocalClient(); - } void onSequenceChanged() {} DECLARE_CONOBJECT(afxModelData); + +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override + { + reloadOnLocalClient(); + } }; //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// @@ -154,9 +155,9 @@ public: void setSequenceRateFactor(F32 factor); void setSortPriority(S8 priority) { sort_priority = priority; } - const char* getShapeFileName() const { return mDataBlock->getShape(); } + const char* getShapeFileName() const { return mDataBlock->getShapeFile(); } void setVisibility(bool flag) { is_visible = flag; } - TSShape* getTSShape() { return mDataBlock->getShapeResource(); } + TSShape* getTSShape() { return mDataBlock->getShape(); } TSShapeInstance* getTSShapeInstance() { return shape_inst; } U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans); diff --git a/Engine/source/afx/ce/afxStaticShape.h b/Engine/source/afx/ce/afxStaticShape.h index 3d0e3f2d9..fce335f90 100644 --- a/Engine/source/afx/ce/afxStaticShape.h +++ b/Engine/source/afx/ce/afxStaticShape.h @@ -85,7 +85,7 @@ public: U32 packUpdate(NetConnection*, U32, BitStream*) override; void unpackUpdate(NetConnection*, BitStream*) override; - const char* getShapeFileName() const { return mDataBlock->mShapeAsset->getShapeFileName(); } + const char* getShapeFileName() const { return mDataBlock->getShapeFile(); } void setVisibility(bool flag) { mIs_visible = flag; } DECLARE_CONOBJECT(afxStaticShape); 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/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/Engine/source/environment/VolumetricFog.cpp b/Engine/source/environment/VolumetricFog.cpp index 875982015..be8b8a2cc 100644 --- a/Engine/source/environment/VolumetricFog.cpp +++ b/Engine/source/environment/VolumetricFog.cpp @@ -135,8 +135,6 @@ VolumetricFog::VolumetricFog() mTexTiles = 1.0f; mSpeed1.set(0.5f, 0.0f); mSpeed2.set(0.1f, 0.1f); - - INIT_ASSET(Shape); } VolumetricFog::~VolumetricFog() @@ -164,7 +162,7 @@ void VolumetricFog::initPersistFields() docsURL; Parent::initPersistFields(); addGroup("Shapes"); - INITPERSISTFIELD_SHAPEASSET(Shape, VolumetricFog, "The source shape asset."); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, VolumetricFog, "The source shape asset."); endGroup("Shapes"); addGroup("VolumetricFogData"); @@ -342,7 +340,7 @@ void VolumetricFog::handleResize(VolumetricFogRTManager *RTM, bool resize) bool VolumetricFog::setShapeAsset(const StringTableEntry shapeAssetId) { - mShapeAssetId = shapeAssetId; + _setShape(shapeAssetId); LoadShape(); return true; @@ -358,20 +356,20 @@ bool VolumetricFog::LoadShape() return false; } - if (!mShape) + if (!getShape()) { Con::errorf("VolumetricFog::_createShape() - Shape Asset had no valid shape!"); return false; } - mObjBox = mShape->mBounds; - mRadius = mShape->mRadius; + mObjBox = getShape()->mBounds; + mRadius = getShape()->mRadius; resetWorldBox(); if (!isClientObject()) return false; - TSShapeInstance *mShapeInstance = new TSShapeInstance(mShape, false); + TSShapeInstance *mShapeInstance = new TSShapeInstance(getShape(), false); meshes mesh_detail; for (S32 i = 0; i < det_size.size(); i++) @@ -387,9 +385,9 @@ bool VolumetricFog::LoadShape() // browsing model for detail levels - for (U32 i = 0; i < mShape->details.size(); i++) + for (U32 i = 0; i < getShape()->details.size(); i++) { - const TSDetail *detail = &mShape->details[i]; + const TSDetail *detail = &getShape()->details[i]; mesh_detail.det_size = detail->size; mesh_detail.sub_shape = detail->subShapeNum; mesh_detail.obj_det = detail->objectDetailNum; @@ -405,8 +403,8 @@ bool VolumetricFog::LoadShape() const S32 ss = det_size[i].sub_shape; if (ss >= 0) { - const S32 start = mShape->subShapeFirstObject[ss]; - const S32 end = start + mShape->subShapeNumObjects[ss]; + const S32 start = getShape()->subShapeFirstObject[ss]; + const S32 end = start + getShape()->subShapeNumObjects[ss]; for (S32 j = start; j < end; j++) { // Loading shape, only the first mesh for each detail will be used! @@ -568,7 +566,7 @@ U32 VolumetricFog::packUpdate(NetConnection *con, U32 mask, BitStream *stream) } if (stream->writeFlag(mask & FogShapeMask)) { - PACK_ASSET(con, Shape); + PACK_ASSET_REFACTOR(con, Shape); mathWrite(*stream, getTransform()); mathWrite(*stream, getScale()); @@ -597,8 +595,8 @@ void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream) VectorF scale; VectorF mOldScale = getScale(); StringTableEntry oldTextureName = mTextureAsset.getAssetId(); - StringTableEntry oldShapeAsset = mShapeAssetId; - StringTableEntry oldShape = mShapeName; + StringTableEntry oldShapeAsset = _getShapeAssetId(); + StringTableEntry oldShape = getShapeFile(); if (stream->readFlag())// Fog color stream->read(&mFogColor); @@ -667,11 +665,11 @@ void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream) } if (stream->readFlag())//Fog shape { - UNPACK_ASSET(con, Shape); + UNPACK_ASSET_REFACTOR(con, Shape); mathRead(*stream, &mat); mathRead(*stream, &scale); - if (strcmp(oldShapeAsset, mShapeAssetId) != 0 || strcmp(oldShape, mShapeName) != 0) + if (strcmp(oldShapeAsset, _getShapeAssetId()) != 0 || strcmp(oldShape, getShapeFile()) != 0) { mIsVBDirty = true; mShapeLoaded = LoadShape(); diff --git a/Engine/source/environment/VolumetricFog.h b/Engine/source/environment/VolumetricFog.h index 42f085eab..76519f654 100644 --- a/Engine/source/environment/VolumetricFog.h +++ b/Engine/source/environment/VolumetricFog.h @@ -84,8 +84,7 @@ class VolumetricFog : public SceneObject Vector *indices; }; - DECLARE_SHAPEASSET(VolumetricFog, Shape, onShapeChanged); - DECLARE_ASSET_NET_SETGET(VolumetricFog, Shape, FogShapeMask); + DECLARE_SHAPEASSET_REFACTOR(VolumetricFog, Shape) protected: // Rendertargets; @@ -203,6 +202,7 @@ class VolumetricFog : public SceneObject void ResizeRT(PlatformWindow *win, bool resize); protected: + // Protected methods bool onAdd() override; void onRemove() override; @@ -246,8 +246,6 @@ class VolumetricFog : public SceneObject bool isInsideFog(); bool setShapeAsset(const StringTableEntry shapeAssetId); - - void onShapeChanged() {} DECLARE_CONOBJECT(VolumetricFog); DECLARE_CATEGORY("Environment \t Weather"); diff --git a/Engine/source/forest/forestItem.cpp b/Engine/source/forest/forestItem.cpp index 239919a91..36c12e8a7 100644 --- a/Engine/source/forest/forestItem.cpp +++ b/Engine/source/forest/forestItem.cpp @@ -53,7 +53,8 @@ ForestItemData::ForestItemData() mTightnessCoefficient( 0.4f ), mDampingCoefficient( 0.7f ) { - INIT_ASSET(Shape); + mShape = NULL; + mShapeAsset.registerRefreshNotify(this); } void ForestItemData::initPersistFields() @@ -61,10 +62,8 @@ void ForestItemData::initPersistFields() docsURL; addGroup( "Shapes" ); - INITPERSISTFIELD_SHAPEASSET(Shape, ForestItemData, "Shape asset for this item type"); - - addProtectedField( "shapeFile", TypeShapeFilename, Offset( mShapeName, ForestItemData ), &_setShapeData, &defaultProtectedGetFn, - "Shape file for this item type", AbstractClassRep::FIELD_HideInInspectors ); + INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, ForestItemData, "Shape asset for this item type"); + endGroup( "Shapes" ); addGroup("Physics"); @@ -164,7 +163,7 @@ void ForestItemData::packData(BitStream* stream) stream->write( localName ); - PACKDATA_ASSET(Shape); + PACKDATA_ASSET_REFACTOR(Shape); stream->writeFlag( mCollidable ); @@ -190,7 +189,7 @@ void ForestItemData::unpackData(BitStream* stream) stream->read( &localName ); setInternalName( localName ); - UNPACKDATA_ASSET(Shape); + UNPACKDATA_ASSET_REFACTOR(Shape); mCollidable = stream->readFlag(); diff --git a/Engine/source/forest/forestItem.h b/Engine/source/forest/forestItem.h index 28d9f4248..2b7337593 100644 --- a/Engine/source/forest/forestItem.h +++ b/Engine/source/forest/forestItem.h @@ -48,7 +48,7 @@ struct RayInfo; class AbstractPolyList; -class ForestItemData : public SimDataBlock +class ForestItemData : public SimDataBlock, protected AssetPtrCallback { protected: @@ -62,8 +62,7 @@ protected: public: - DECLARE_SHAPEASSET(ForestItemData, Shape, onShapeChanged); - DECLARE_ASSET_SETGET(ForestItemData, Shape); + DECLARE_SHAPEASSET_REFACTOR(ForestItemData, Shape) /// This is the radius used during placement to ensure /// the element isn't crowded up against other trees. @@ -144,7 +143,10 @@ public: return theSignal; } - void onShapeChanged() + Resource mShape; + +protected: + void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { reloadOnLocalClient(); } diff --git a/Engine/source/forest/ts/tsForestItemData.cpp b/Engine/source/forest/ts/tsForestItemData.cpp index 5c88cf0ef..292ca564d 100644 --- a/Engine/source/forest/ts/tsForestItemData.cpp +++ b/Engine/source/forest/ts/tsForestItemData.cpp @@ -99,13 +99,13 @@ void TSForestItemData::inspectPostApply() void TSForestItemData::_onResourceChanged( const Torque::Path &path ) { - U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset); + U32 assetStatus = ShapeAsset::getAssetErrCode(_getShapeAssetId()); if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback) { return; } - if ( path != Path(mShapeAsset->getShapeFilePath()) ) + if ( path != Path(getShapeFile()) ) return; SAFE_DELETE( mShapeInstance ); @@ -116,18 +116,18 @@ void TSForestItemData::_onResourceChanged( const Torque::Path &path ) void TSForestItemData::_loadShape() { - U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset); + mShape = getShape(); + U32 assetStatus = ShapeAsset::getAssetErrCode(_getShapeAssetId()); if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback) { return; } - _setShape(mShapeAssetId); if ( !(bool)mShape ) return; if ( mIsClientObject && - !mShape->preloadMaterialList(mShapeAsset->getShapeFilePath()) ) + !mShape->preloadMaterialList(mShape.getPath()) ) return; // Lets add an autobillboard detail if don't have one. @@ -165,7 +165,7 @@ TSShapeInstance* TSForestItemData::_getShapeInstance() const void TSForestItemData::_checkLastDetail() { - U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset); + U32 assetStatus = ShapeAsset::getAssetErrCode(_getShapeAssetId()); if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback) { return; @@ -177,7 +177,7 @@ void TSForestItemData::_checkLastDetail() // TODO: Expose some real parameters to the datablock maybe? if ( detail->subShapeNum != -1 ) { - mShape->addImposter(mShapeAsset->getShapeFilePath(), 10, 4, 0, 0, 256, 0, 0 ); + mShape->addImposter(mShape.getPath(), 10, 4, 0, 0, 256, 0, 0); // HACK: If i don't do this it crashes! while ( mShape->detailCollisionAccelerators.size() < mShape->details.size() ) diff --git a/Engine/source/gui/buttons/guiBitmapButtonCtrl.h b/Engine/source/gui/buttons/guiBitmapButtonCtrl.h index 773f7eb2c..ec96e9344 100644 --- a/Engine/source/gui/buttons/guiBitmapButtonCtrl.h +++ b/Engine/source/gui/buttons/guiBitmapButtonCtrl.h @@ -123,6 +123,12 @@ private: String mBitmapFile; public: void _setBitmap(StringTableEntry _in) { + if (_in == NULL || _in == StringTable->EmptyString() || _in == "") + { + mBitmapAsset = NULL; + mBitmapFile = ""; + return; + } if (mBitmapAsset.getAssetId() == _in) return; if (!AssetDatabase.isDeclaredAsset(_in)) { StringTableEntry imageAssetId = ImageAsset::smNoImageAssetFallback; AssetQuery query; S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); if (foundAssetcount != 0) { imageAssetId = query.mAssetList[0]; diff --git a/Engine/source/gui/controls/guiBitmapCtrl.cpp b/Engine/source/gui/controls/guiBitmapCtrl.cpp index 52955f90d..fe7aa7862 100644 --- a/Engine/source/gui/controls/guiBitmapCtrl.cpp +++ b/Engine/source/gui/controls/guiBitmapCtrl.cpp @@ -121,16 +121,19 @@ void GuiBitmapCtrl::setBitmap(const char* name, bool resize) if (assetId != StringTable->EmptyString()) _setBitmap(assetId); else - _setBitmap(name); + _setBitmap(StringTable->EmptyString()); } - mBitmap = mBitmapAsset->getTexture(&GFXDefaultGUIProfile); - - if (getBitmap() && resize) + if (mBitmapAsset.notNull()) { - - setExtent(mBitmap->getWidth(), mBitmap->getHeight()); - updateSizing(); + mBitmap = mBitmapAsset->getTexture(&GFXDefaultGUIProfile); + + if (getBitmap() && resize) + { + + setExtent(mBitmap->getWidth(), mBitmap->getHeight()); + updateSizing(); + } } setUpdate(); diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index d00c3024a..c9f603d05 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -690,6 +690,15 @@ 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)) + { + 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)) { 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/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/Engine/source/gui/editor/guiShapeEdPreview.cpp b/Engine/source/gui/editor/guiShapeEdPreview.cpp index 1724db214..ff1c8a884 100644 --- a/Engine/source/gui/editor/guiShapeEdPreview.cpp +++ b/Engine/source/gui/editor/guiShapeEdPreview.cpp @@ -420,7 +420,7 @@ bool GuiShapeEdPreview::setObjectShapeAsset(const char* assetId) if (assetType == StringTable->insert("ShapeAsset")) { ShapeAsset* asset = AssetDatabase.acquireAsset(id); - modelName = asset->getShapeFilePath(); + modelName = asset->getShapeFile(); AssetDatabase.releaseAsset(id); } else if (assetType == StringTable->insert("ShapeAnimationAsset")) diff --git a/Engine/source/gui/editor/inspector/group.cpp b/Engine/source/gui/editor/inspector/group.cpp index 6bd243d60..13953ead5 100644 --- a/Engine/source/gui/editor/inspector/group.cpp +++ b/Engine/source/gui/editor/inspector/group.cpp @@ -665,7 +665,7 @@ void GuiInspectorGroup::addInspectorField(StringTableEntry name, StringTableEntr else if (typeName == StringTable->insert("image")) fieldType = TypeImageAssetPtr; else if (typeName == StringTable->insert("shape")) - fieldType = TypeShapeAssetId; + fieldType = TypeShapeAssetPtr; else if (typeName == StringTable->insert("sound")) fieldType = TypeSoundAssetId; else if (typeName == StringTable->insert("bool")) diff --git a/Engine/source/gui/editor/inspector/variableInspector.cpp b/Engine/source/gui/editor/inspector/variableInspector.cpp index 41a165d32..fc78e76b3 100644 --- a/Engine/source/gui/editor/inspector/variableInspector.cpp +++ b/Engine/source/gui/editor/inspector/variableInspector.cpp @@ -205,7 +205,7 @@ void GuiVariableInspector::addField(const char* name, const char* label, const c else if (newField->mFieldTypeName == StringTable->insert("image")) fieldTypeMask = TypeImageAssetPtr; else if (newField->mFieldTypeName == StringTable->insert("shape")) - fieldTypeMask = TypeShapeAssetId; + fieldTypeMask = TypeShapeAssetPtr; else if (newField->mFieldTypeName == StringTable->insert("bool")) fieldTypeMask = TypeBool; else if (newField->mFieldTypeName == StringTable->insert("object")) diff --git a/Engine/source/ts/assimp/assimpShapeLoader.cpp b/Engine/source/ts/assimp/assimpShapeLoader.cpp index c261f11cd..a8c5e0079 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.cpp +++ b/Engine/source/ts/assimp/assimpShapeLoader.cpp @@ -993,6 +993,23 @@ TSShape* assimpLoadShape(const Torque::Path &path) tss->write(&dtsStream); } + Torque::Path dsqPath(cachedPath); + dsqPath.setExtension("dsq"); + FileStream animOutStream; + for (S32 i = 0; i < tss->sequences.size(); i++) + { + const String& seqName = tss->getName(tss->sequences[i].nameIndex); + Con::printf("Writing DSQ Animation File for sequence '%s'", seqName.c_str()); + + dsqPath.setFileName(cachedPath.getFileName() + "_" + seqName); + if (animOutStream.open(dsqPath.getFullPath(), Torque::FS::File::Write)) + { + tss->exportSequence(&animOutStream, tss->sequences[i], false); + animOutStream.close(); + } + + } + loader.updateMaterialsScript(path); } loader.releaseImport(); diff --git a/Engine/source/ts/collada/colladaShapeLoader.cpp b/Engine/source/ts/collada/colladaShapeLoader.cpp index 817ca3a6e..f9bc763ba 100644 --- a/Engine/source/ts/collada/colladaShapeLoader.cpp +++ b/Engine/source/ts/collada/colladaShapeLoader.cpp @@ -737,6 +737,23 @@ TSShape* loadColladaShape(const Torque::Path &path) tss->write(&dtsStream); } + Torque::Path dsqPath(cachedPath); + dsqPath.setExtension("dsq"); + FileStream animOutStream; + for (S32 i = 0; i < tss->sequences.size(); i++) + { + const String& seqName = tss->getName(tss->sequences[i].nameIndex); + Con::printf("Writing DSQ Animation File for sequence '%s'", seqName.c_str()); + + dsqPath.setFileName(cachedPath.getFileName() + "_" + seqName); + if (animOutStream.open(dsqPath.getFullPath(), Torque::FS::File::Write)) + { + tss->exportSequence(&animOutStream, tss->sequences[i], false); + animOutStream.close(); + } + + } + #endif // DAE2DTS_TOOL // Add collada materials to materials.tscript diff --git a/Engine/source/ts/tsShapeConstruct.cpp b/Engine/source/ts/tsShapeConstruct.cpp index 65eafc637..f3f540f8a 100644 --- a/Engine/source/ts/tsShapeConstruct.cpp +++ b/Engine/source/ts/tsShapeConstruct.cpp @@ -2138,7 +2138,7 @@ DefineTSShapeConstructorMethod(addSequence, bool, if (assetType == StringTable->insert("ShapeAsset")) { ShapeAsset* asset = AssetDatabase.acquireAsset(assetId); - srcPath = asset->getShapeFilePath(); + srcPath = asset->getShapeFile(); AssetDatabase.releaseAsset(assetId); } else if (assetType == StringTable->insert("ShapeAnimationAsset")) diff --git a/Engine/source/ts/tsShapeConstruct.h b/Engine/source/ts/tsShapeConstruct.h index df04078de..f4f8dfbff 100644 --- a/Engine/source/ts/tsShapeConstruct.h +++ b/Engine/source/ts/tsShapeConstruct.h @@ -236,7 +236,7 @@ public: StringTableEntry getShapePath() const { if (mShapeAsset.notNull()) - return mShapeAsset->getShapeFilePath(); + return mShapeAsset->getShapeFile(); else return StringTable->EmptyString(); } 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/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..6267d5871 --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml @@ -0,0 +1,14 @@ + + + + + + + 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 000000000..3acc77e04 Binary files /dev/null and b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.fbx differ 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..14e0fffea --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.tscript @@ -0,0 +1,20 @@ + +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"); +} 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"; }; } diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript index 536ef79d5..37490772f 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript @@ -278,7 +278,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/"; } @@ -1633,7 +1633,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..eb29fb365 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 = "@" @ %this.assetName @ "_Preview.png"; + }; + + 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 eeb4fa1ef..6795387f4 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 = "@" @ %this.assetName @ "_Preview.png"; + }; + + 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..be6d0087e 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 = "@" @ %this.assetName @ "_Preview.png"; + }; + + 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; 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)