mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-14 16:14:38 +00:00
Cleans up ShapeAsset of some unnecessary/redundant elements like extra material and animations tracking
Removed the old SHAPE_ASSET macros Implements AssetRef struct that acts as a universal wrapper for an templated AssetPtr and AssetId pair Adds Type handling for AssetRef for ShapeAsset to unify handling in classes that utilize a shapeAsset, so assigning an assetPtr or an assetId will keep a record of the assignment in the event the assetPtr is invalid. Update all classes that utilized the old SHAPE_ASSET macros to utilize the AssetRef struct and updated the class code to utilize it to provide much more clean and concise code that isn't blocked behind macro definitions Added a new example class: shapeDatablockExample which allows render of a simple shape object utilizing a simple example datablock.
This commit is contained in:
parent
c2c5674fe9
commit
b44158cb89
52 changed files with 1860 additions and 1086 deletions
|
|
@ -55,16 +55,12 @@
|
||||||
#include "gfx/bitmap/imageUtils.h"
|
#include "gfx/bitmap/imageUtils.h"
|
||||||
|
|
||||||
StringTableEntry ShapeAsset::smNoShapeAssetFallback = NULL;
|
StringTableEntry ShapeAsset::smNoShapeAssetFallback = NULL;
|
||||||
|
AssetPtr<ShapeAsset> ShapeAsset::smNoShapeAssetFallbackAssetPtr = NULL;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
IMPLEMENT_CONOBJECT(ShapeAsset);
|
IMPLEMENT_CONOBJECT(ShapeAsset);
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// REFACTOR
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
IMPLEMENT_STRUCT(AssetPtr<ShapeAsset>, AssetPtrShapeAsset, , "")
|
IMPLEMENT_STRUCT(AssetPtr<ShapeAsset>, AssetPtrShapeAsset, , "")
|
||||||
END_IMPLEMENT_STRUCT
|
END_IMPLEMENT_STRUCT
|
||||||
|
|
||||||
|
|
@ -131,8 +127,50 @@ ConsoleSetType(TypeShapeAssetId)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// REFACTOR END
|
IMPLEMENT_STRUCT(AssetRef<ShapeAsset>, AssetRefShapeAsset, , "")
|
||||||
//-----------------------------------------------------------------------------
|
END_IMPLEMENT_STRUCT
|
||||||
|
|
||||||
|
ConsoleType(ShapeAssetRef, TypeShapeAssetRef, AssetRef<ShapeAsset>, ASSET_ID_FIELD_PREFIX)
|
||||||
|
|
||||||
|
|
||||||
|
ConsoleGetType(TypeShapeAssetRef)
|
||||||
|
{
|
||||||
|
AssetRef<ShapeAsset>& ref = *((AssetRef<ShapeAsset>*)dptr);
|
||||||
|
|
||||||
|
if (ref.assetPtr.isNull())
|
||||||
|
return ref.assetId;
|
||||||
|
else
|
||||||
|
return ref.assetPtr.getAssetId();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleSetType(TypeShapeAssetRef)
|
||||||
|
{
|
||||||
|
// Was a single argument specified?
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
|
// Yes, so fetch field value.
|
||||||
|
const char* pFieldValue = argv[0];
|
||||||
|
|
||||||
|
// Fetch asset pointer.
|
||||||
|
AssetRef<ShapeAsset>* pAssetRef = (AssetRef<ShapeAsset>*)(dptr);
|
||||||
|
|
||||||
|
// Is the asset pointer the correct type?
|
||||||
|
if (pAssetRef == NULL)
|
||||||
|
{
|
||||||
|
Con::warnf("(TypeShapeAssetRef) - Failed to set asset Id '%d'.", pFieldValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set asset.
|
||||||
|
*pAssetRef = pFieldValue;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn.
|
||||||
|
Con::warnf("(TypeShapeAssetRef) - Cannot set multiple args to a single asset.");
|
||||||
|
}
|
||||||
|
|
||||||
const String ShapeAsset::mErrCodeStrings[] =
|
const String ShapeAsset::mErrCodeStrings[] =
|
||||||
{
|
{
|
||||||
|
|
@ -194,20 +232,6 @@ void ShapeAsset::initPersistFields()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeAsset::setDataField(StringTableEntry slotName, StringTableEntry array, StringTableEntry value)
|
|
||||||
{
|
|
||||||
Parent::setDataField(slotName, array, value);
|
|
||||||
|
|
||||||
//Now, if it's a material slot of some fashion, set it up
|
|
||||||
StringTableEntry matSlotName = StringTable->insert("materialAsset");
|
|
||||||
if (String(slotName).startsWith(matSlotName))
|
|
||||||
{
|
|
||||||
StringTableEntry matId = StringTable->insert(value);
|
|
||||||
|
|
||||||
mMaterialAssetIds.push_back(matId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShapeAsset::initializeAsset()
|
void ShapeAsset::initializeAsset()
|
||||||
{
|
{
|
||||||
// Call parent.
|
// Call parent.
|
||||||
|
|
@ -239,6 +263,16 @@ void ShapeAsset::initializeAsset()
|
||||||
String normalPath = String(mShapeFile) + "_imposter_normals.dds";
|
String normalPath = String(mShapeFile) + "_imposter_normals.dds";
|
||||||
mNormalImposterFileName = StringTable->insert(normalPath.c_str());
|
mNormalImposterFileName = StringTable->insert(normalPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Make sure our fallback is valid
|
||||||
|
if (smNoShapeAssetFallbackAssetPtr.isNull())
|
||||||
|
{
|
||||||
|
smNoShapeAssetFallbackAssetPtr = smNoShapeAssetFallback;
|
||||||
|
if (smNoShapeAssetFallbackAssetPtr.isNull())
|
||||||
|
Con::errorf("ShapeAsset::initializeAsset could not find fallback asset %s!", smNoShapeAssetFallback);
|
||||||
|
else
|
||||||
|
smNoShapeAssetFallbackAssetPtr->load();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeAsset::setShapeFile(const char* pShapeFile)
|
void ShapeAsset::setShapeFile(const char* pShapeFile)
|
||||||
|
|
@ -313,9 +347,9 @@ void ShapeAsset::setNormalImposterFile(const char* pImageFile)
|
||||||
refreshAsset();
|
refreshAsset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeAsset::_onResourceChanged(const Torque::Path &path)
|
void ShapeAsset::_onResourceChanged(const Torque::Path& path)
|
||||||
{
|
{
|
||||||
if (path != Torque::Path(mShapeFile) )
|
if (path != Torque::Path(mShapeFile))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
refreshAsset();
|
refreshAsset();
|
||||||
|
|
@ -325,117 +359,64 @@ U32 ShapeAsset::load()
|
||||||
{
|
{
|
||||||
if (mLoadedState == AssetErrCode::Ok) return mLoadedState;
|
if (mLoadedState == AssetErrCode::Ok) return mLoadedState;
|
||||||
|
|
||||||
mMaterialAssets.clear();
|
|
||||||
mMaterialAssetIds.clear();
|
|
||||||
|
|
||||||
//First, load any material, animation, etc assets we may be referencing in our asset
|
|
||||||
// Find any asset dependencies.
|
|
||||||
AssetManager::typeAssetDependsOnHash::Iterator assetDependenciesItr = mpOwningAssetManager->getDependedOnAssets()->find(mpAssetDefinition->mAssetId);
|
|
||||||
|
|
||||||
// Does the asset have any dependencies?
|
|
||||||
if (assetDependenciesItr != mpOwningAssetManager->getDependedOnAssets()->end())
|
|
||||||
{
|
|
||||||
// Iterate all dependencies.
|
|
||||||
while (assetDependenciesItr != mpOwningAssetManager->getDependedOnAssets()->end() && assetDependenciesItr->key == mpAssetDefinition->mAssetId)
|
|
||||||
{
|
|
||||||
StringTableEntry assetType = mpOwningAssetManager->getAssetType(assetDependenciesItr->value);
|
|
||||||
|
|
||||||
if (assetType == StringTable->insert("MaterialAsset"))
|
|
||||||
{
|
|
||||||
mMaterialAssetIds.push_front(assetDependenciesItr->value);
|
|
||||||
|
|
||||||
//Force the asset to become initialized if it hasn't been already
|
|
||||||
AssetPtr<MaterialAsset> matAsset = assetDependenciesItr->value;
|
|
||||||
|
|
||||||
mMaterialAssets.push_front(matAsset);
|
|
||||||
}
|
|
||||||
else if (assetType == StringTable->insert("ShapeAnimationAsset"))
|
|
||||||
{
|
|
||||||
mAnimationAssetIds.push_back(assetDependenciesItr->value);
|
|
||||||
|
|
||||||
//Force the asset to become initialized if it hasn't been already
|
|
||||||
AssetPtr<ShapeAnimationAsset> animAsset = assetDependenciesItr->value;
|
|
||||||
|
|
||||||
mAnimationAssets.push_back(animAsset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next dependency.
|
|
||||||
assetDependenciesItr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mShape = ResourceManager::get().load(mShapeFile);
|
mShape = ResourceManager::get().load(mShapeFile);
|
||||||
|
|
||||||
if (!mShape)
|
if (!mShape)
|
||||||
{
|
{
|
||||||
mLoadedState = BadFileReference;
|
mLoadedState = BadFileReference;
|
||||||
|
|
||||||
return mLoadedState; //if it failed to load, bail out
|
return mLoadedState; //if it failed to load, bail out
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct billboards if not done already
|
// Construct billboards if not done already
|
||||||
if (GFXDevice::devicePresent())
|
if (GFXDevice::devicePresent())
|
||||||
mShape->setupBillboardDetails(mShapeFile, mDiffuseImposterFileName, mNormalImposterFileName);
|
mShape->setupBillboardDetails(mShapeFile, mDiffuseImposterFileName, mNormalImposterFileName);
|
||||||
|
|
||||||
//If they exist, grab our imposters here and bind them to our shapeAsset
|
|
||||||
|
|
||||||
bool hasBlends = false;
|
|
||||||
|
|
||||||
//Now that we've successfully loaded our shape and have any materials and animations loaded
|
|
||||||
//we need to set up the animations we're using on our shape
|
|
||||||
for (S32 i = mAnimationAssets.size()-1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
String srcName = mAnimationAssets[i]->getAnimationName();
|
|
||||||
String srcPath(mAnimationAssets[i]->getAnimationFilename());
|
|
||||||
//SplitSequencePathAndName(srcPath, srcName);
|
|
||||||
|
|
||||||
if (!mShape->addSequence(srcPath, mAnimationAssets[i]->getAssetId(), srcName, srcName,
|
|
||||||
mAnimationAssets[i]->getStartFrame(), mAnimationAssets[i]->getEndFrame(), mAnimationAssets[i]->getPadRotation(), mAnimationAssets[i]->getPadTransforms()))
|
|
||||||
{
|
|
||||||
mLoadedState = MissingAnimatons;
|
|
||||||
return mLoadedState;
|
|
||||||
}
|
|
||||||
if (mAnimationAssets[i]->isBlend())
|
|
||||||
hasBlends = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if any of our animations are blends, set those up now
|
|
||||||
if (hasBlends)
|
|
||||||
{
|
|
||||||
for (U32 i=0; i < mAnimationAssets.size(); ++i)
|
|
||||||
{
|
|
||||||
if (mAnimationAssets[i]->isBlend() && mAnimationAssets[i]->getBlendAnimationName() != StringTable->EmptyString())
|
|
||||||
{
|
|
||||||
//gotta do a bit of logic here.
|
|
||||||
//First, we need to make sure the anim asset we depend on for our blend is loaded
|
|
||||||
AssetPtr<ShapeAnimationAsset> blendAnimAsset = mAnimationAssets[i]->getBlendAnimationName();
|
|
||||||
|
|
||||||
U32 assetStatus = ShapeAnimationAsset::getAssetErrCode(blendAnimAsset);
|
|
||||||
if (assetStatus != AssetBase::Ok)
|
|
||||||
{
|
|
||||||
Con::errorf("ShapeAsset::initializeAsset - Unable to acquire reference animation asset %s for asset %s to blend!", mAnimationAssets[i]->getBlendAnimationName(), mAnimationAssets[i]->getAssetName());
|
|
||||||
{
|
|
||||||
mLoadedState = MissingAnimatons;
|
|
||||||
return mLoadedState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String refAnimName = blendAnimAsset->getAnimationName();
|
|
||||||
if (!mShape->setSequenceBlend(mAnimationAssets[i]->getAnimationName(), true, blendAnimAsset->getAnimationName(), mAnimationAssets[i]->getBlendFrame()))
|
|
||||||
{
|
|
||||||
Con::errorf("ShapeAnimationAsset::initializeAsset - Unable to set animation clip %s for asset %s to blend!", mAnimationAssets[i]->getAnimationName(), mAnimationAssets[i]->getAssetName());
|
|
||||||
{
|
|
||||||
mLoadedState = MissingAnimatons;
|
|
||||||
return mLoadedState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mLoadedState = Ok;
|
mLoadedState = Ok;
|
||||||
|
|
||||||
return mLoadedState;
|
return mLoadedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShapeAsset::preloadMaterialList()
|
||||||
|
{
|
||||||
|
if (!mShape)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return mShape->preloadMaterialList(getShapeFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
TSShape* ShapeAsset::getShape()
|
||||||
|
{
|
||||||
|
AssetErrCode result = static_cast<AssetErrCode>(load());
|
||||||
|
|
||||||
|
if (mShape)
|
||||||
|
{
|
||||||
|
return mShape;
|
||||||
|
}
|
||||||
|
else if (smNoShapeAssetFallbackAssetPtr.notNull())
|
||||||
|
{
|
||||||
|
return smNoShapeAssetFallbackAssetPtr->getShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource<TSShape> ShapeAsset::getShapeResource()
|
||||||
|
{
|
||||||
|
AssetErrCode result = static_cast<AssetErrCode>(load());
|
||||||
|
|
||||||
|
if (mShape)
|
||||||
|
{
|
||||||
|
return mShape;
|
||||||
|
}
|
||||||
|
else if (smNoShapeAssetFallbackAssetPtr.notNull())
|
||||||
|
{
|
||||||
|
return smNoShapeAssetFallbackAssetPtr->getShapeResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Resource<TSShape>(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//Utility function to 'fill out' bindings and resources with a matching asset if one exists
|
//Utility function to 'fill out' bindings and resources with a matching asset if one exists
|
||||||
U32 ShapeAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAsset>* shapeAsset)
|
U32 ShapeAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAsset>* shapeAsset)
|
||||||
|
|
@ -560,6 +541,44 @@ U32 ShapeAsset::getAssetById(StringTableEntry assetId, AssetPtr<ShapeAsset>* sha
|
||||||
return AssetErrCode::UsingFallback;
|
return AssetErrCode::UsingFallback;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringTableEntry ShapeAsset::getMaterial(const S32& index)
|
||||||
|
{
|
||||||
|
if (!mShape)
|
||||||
|
return StringTable->EmptyString();
|
||||||
|
|
||||||
|
if (index < 0 || index >= mShape->materialList->size())
|
||||||
|
return StringTable->EmptyString();
|
||||||
|
|
||||||
|
return mShape->materialList->getMaterialName(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 ShapeAsset::getMaterialCount()
|
||||||
|
{
|
||||||
|
if (!mShape)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return mShape->materialList->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTableEntry ShapeAsset::getAnimation(const S32& index)
|
||||||
|
{
|
||||||
|
if (!mShape)
|
||||||
|
return StringTable->EmptyString();
|
||||||
|
|
||||||
|
if (index < 0 || index >= mShape->sequences.size())
|
||||||
|
return StringTable->EmptyString();
|
||||||
|
|
||||||
|
return mShape->getName(mShape->sequences[index].nameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 ShapeAsset::getAnimationCount()
|
||||||
|
{
|
||||||
|
if (!mShape)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return mShape->sequences.size();
|
||||||
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void ShapeAsset::copyTo(SimObject* object)
|
void ShapeAsset::copyTo(SimObject* object)
|
||||||
|
|
@ -589,10 +608,10 @@ void ShapeAsset::onTamlPreWrite(void)
|
||||||
Parent::onTamlPreWrite();
|
Parent::onTamlPreWrite();
|
||||||
|
|
||||||
// ensure paths are collapsed.
|
// ensure paths are collapsed.
|
||||||
mShapeFile = collapseAssetFilePath(mShapeFile);
|
mShapeFile = collapseAssetFilePath(mShapeFile);
|
||||||
mConstructorFileName = collapseAssetFilePath(mConstructorFileName);
|
mConstructorFileName = collapseAssetFilePath(mConstructorFileName);
|
||||||
mDiffuseImposterFileName = collapseAssetFilePath(mDiffuseImposterFileName);
|
mDiffuseImposterFileName = collapseAssetFilePath(mDiffuseImposterFileName);
|
||||||
mNormalImposterFileName = collapseAssetFilePath(mNormalImposterFileName);
|
mNormalImposterFileName = collapseAssetFilePath(mNormalImposterFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeAsset::onTamlPostWrite(void)
|
void ShapeAsset::onTamlPostWrite(void)
|
||||||
|
|
@ -601,42 +620,10 @@ void ShapeAsset::onTamlPostWrite(void)
|
||||||
Parent::onTamlPostWrite();
|
Parent::onTamlPostWrite();
|
||||||
|
|
||||||
// ensure paths are expanded.
|
// ensure paths are expanded.
|
||||||
mShapeFile = expandAssetFilePath(mShapeFile);
|
mShapeFile = expandAssetFilePath(mShapeFile);
|
||||||
mConstructorFileName = expandAssetFilePath(mConstructorFileName);
|
mConstructorFileName = expandAssetFilePath(mConstructorFileName);
|
||||||
mDiffuseImposterFileName = expandAssetFilePath(mDiffuseImposterFileName);
|
mDiffuseImposterFileName = expandAssetFilePath(mDiffuseImposterFileName);
|
||||||
mNormalImposterFileName = expandAssetFilePath(mNormalImposterFileName);
|
mNormalImposterFileName = expandAssetFilePath(mNormalImposterFileName);
|
||||||
}
|
|
||||||
|
|
||||||
void ShapeAsset::SplitSequencePathAndName(String& srcPath, String& srcName)
|
|
||||||
{
|
|
||||||
srcName = "";
|
|
||||||
|
|
||||||
// Determine if there is a sequence name at the end of the source string, and
|
|
||||||
// if so, split the filename from the sequence name
|
|
||||||
S32 split = srcPath.find(' ', 0, String::Right);
|
|
||||||
S32 split2 = srcPath.find('\t', 0, String::Right);
|
|
||||||
if ((split == String::NPos) || (split2 > split))
|
|
||||||
split = split2;
|
|
||||||
if (split != String::NPos)
|
|
||||||
{
|
|
||||||
split2 = split + 1;
|
|
||||||
while ((srcPath[split2] != '\0') && dIsspace(srcPath[split2]))
|
|
||||||
split2++;
|
|
||||||
|
|
||||||
// now 'split' is at the end of the path, and 'split2' is at the start of the sequence name
|
|
||||||
srcName = srcPath.substr(split2);
|
|
||||||
srcPath = srcPath.erase(split, srcPath.length() - split);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ShapeAnimationAsset* ShapeAsset::getAnimation(S32 index)
|
|
||||||
{
|
|
||||||
if (index < mAnimationAssets.size())
|
|
||||||
{
|
|
||||||
return mAnimationAssets[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TORQUE_TOOLS
|
#ifdef TORQUE_TOOLS
|
||||||
|
|
@ -655,7 +642,7 @@ const char* ShapeAsset::generateCachedPreviewImage(S32 resolution, String overri
|
||||||
|
|
||||||
if (overrideMaterial.isNotEmpty())
|
if (overrideMaterial.isNotEmpty())
|
||||||
{
|
{
|
||||||
Material *tMat = dynamic_cast<Material*>(Sim::findObject(overrideMaterial));
|
Material* tMat = dynamic_cast<Material*>(Sim::findObject(overrideMaterial));
|
||||||
if (tMat)
|
if (tMat)
|
||||||
shape->reSkin(tMat->mMapTo, mShape->materialList->getMaterialName(0));
|
shape->reSkin(tMat->mMapTo, mShape->materialList->getMaterialName(0));
|
||||||
}
|
}
|
||||||
|
|
@ -714,6 +701,13 @@ const char* ShapeAsset::generateCachedPreviewImage(S32 resolution, String overri
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DefineEngineMethod(ShapeAsset, getMaterial, const char*, (S32 index), (0),
|
||||||
|
"Gets the number of materials for this shape asset.\n"
|
||||||
|
"@return Material count.\n")
|
||||||
|
{
|
||||||
|
return object->getMaterial(index);
|
||||||
|
}
|
||||||
|
|
||||||
DefineEngineMethod(ShapeAsset, getMaterialCount, S32, (), ,
|
DefineEngineMethod(ShapeAsset, getMaterialCount, S32, (), ,
|
||||||
"Gets the number of materials for this shape asset.\n"
|
"Gets the number of materials for this shape asset.\n"
|
||||||
"@return Material count.\n")
|
"@return Material count.\n")
|
||||||
|
|
@ -721,14 +715,7 @@ DefineEngineMethod(ShapeAsset, getMaterialCount, S32, (), ,
|
||||||
return object->getMaterialCount();
|
return object->getMaterialCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
DefineEngineMethod(ShapeAsset, getAnimationCount, S32, (), ,
|
DefineEngineMethod(ShapeAsset, getAnimation, const char*, (S32 index), (0),
|
||||||
"Gets the number of animations for this shape asset.\n"
|
|
||||||
"@return Animation count.\n")
|
|
||||||
{
|
|
||||||
return object->getAnimationCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
DefineEngineMethod(ShapeAsset, getAnimation, ShapeAnimationAsset*, (S32 index), (0),
|
|
||||||
"Gets a particular shape animation asset for this shape.\n"
|
"Gets a particular shape animation asset for this shape.\n"
|
||||||
"@param animation asset index.\n"
|
"@param animation asset index.\n"
|
||||||
"@return Shape Animation Asset.\n")
|
"@return Shape Animation Asset.\n")
|
||||||
|
|
@ -736,6 +723,13 @@ DefineEngineMethod(ShapeAsset, getAnimation, ShapeAnimationAsset*, (S32 index),
|
||||||
return object->getAnimation(index);
|
return object->getAnimation(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(ShapeAsset, getAnimationCount, S32, (), ,
|
||||||
|
"Gets the number of animations for this shape asset.\n"
|
||||||
|
"@return Animation count.\n")
|
||||||
|
{
|
||||||
|
return object->getAnimationCount();
|
||||||
|
}
|
||||||
|
|
||||||
DefineEngineMethod(ShapeAsset, getShapePath, const char*, (), ,
|
DefineEngineMethod(ShapeAsset, getShapePath, const char*, (), ,
|
||||||
"Gets the shape's file path\n"
|
"Gets the shape's file path\n"
|
||||||
"@return The filename of the shape file")
|
"@return The filename of the shape file")
|
||||||
|
|
@ -784,7 +778,7 @@ ConsoleDocClass(GuiInspectorTypeShapeAssetPtr,
|
||||||
"@brief Inspector field type for Shapes\n\n"
|
"@brief Inspector field type for Shapes\n\n"
|
||||||
"Editor use only.\n\n"
|
"Editor use only.\n\n"
|
||||||
"@internal"
|
"@internal"
|
||||||
);
|
);
|
||||||
|
|
||||||
void GuiInspectorTypeShapeAssetPtr::consoleInit()
|
void GuiInspectorTypeShapeAssetPtr::consoleInit()
|
||||||
{
|
{
|
||||||
|
|
@ -940,7 +934,7 @@ void GuiInspectorTypeShapeAssetPtr::updatePreviewImage()
|
||||||
//if what we're working with isn't even a valid asset, don't present like we found a good one
|
//if what we're working with isn't even a valid asset, don't present like we found a good one
|
||||||
if (!AssetDatabase.isDeclaredAsset(previewImage))
|
if (!AssetDatabase.isDeclaredAsset(previewImage))
|
||||||
{
|
{
|
||||||
mPreviewImage->_setBitmap(StringTable->EmptyString());
|
mPreviewImage->setBitmap(StringTable->EmptyString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -953,7 +947,7 @@ void GuiInspectorTypeShapeAssetPtr::updatePreviewImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPreviewImage->getBitmapAsset().isNull())
|
if (mPreviewImage->getBitmapAsset().isNull())
|
||||||
mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
mPreviewImage->setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiInspectorTypeShapeAssetPtr::setPreviewImage(StringTableEntry assetId)
|
void GuiInspectorTypeShapeAssetPtr::setPreviewImage(StringTableEntry assetId)
|
||||||
|
|
@ -961,7 +955,7 @@ void GuiInspectorTypeShapeAssetPtr::setPreviewImage(StringTableEntry assetId)
|
||||||
//if what we're working with isn't even a valid asset, don't present like we found a good one
|
//if what we're working with isn't even a valid asset, don't present like we found a good one
|
||||||
if (!AssetDatabase.isDeclaredAsset(assetId))
|
if (!AssetDatabase.isDeclaredAsset(assetId))
|
||||||
{
|
{
|
||||||
mPreviewImage->_setBitmap(StringTable->EmptyString());
|
mPreviewImage->setBitmap(StringTable->EmptyString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -974,7 +968,7 @@ void GuiInspectorTypeShapeAssetPtr::setPreviewImage(StringTableEntry assetId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPreviewImage->getBitmapAsset().isNull())
|
if (mPreviewImage->getBitmapAsset().isNull())
|
||||||
mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
mPreviewImage->setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeShapeAssetId);
|
IMPLEMENT_CONOBJECT(GuiInspectorTypeShapeAssetId);
|
||||||
|
|
@ -991,4 +985,204 @@ void GuiInspectorTypeShapeAssetId::consoleInit()
|
||||||
|
|
||||||
ConsoleBaseType::getType(TypeShapeAssetId)->setInspectorFieldType("GuiInspectorTypeShapeAssetId");
|
ConsoleBaseType::getType(TypeShapeAssetId)->setInspectorFieldType("GuiInspectorTypeShapeAssetId");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(GuiInspectorTypeShapeAssetRef);
|
||||||
|
|
||||||
|
ConsoleDocClass(GuiInspectorTypeShapeAssetRef,
|
||||||
|
"@brief Inspector field type for Shapes\n\n"
|
||||||
|
"Editor use only.\n\n"
|
||||||
|
"@internal"
|
||||||
|
);
|
||||||
|
|
||||||
|
void GuiInspectorTypeShapeAssetRef::consoleInit()
|
||||||
|
{
|
||||||
|
Parent::consoleInit();
|
||||||
|
|
||||||
|
ConsoleBaseType::getType(TypeShapeAssetRef)->setInspectorFieldType("GuiInspectorTypeShapeAssetRef");
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiControl* GuiInspectorTypeShapeAssetRef::constructEditControl()
|
||||||
|
{
|
||||||
|
// Create base filename edit controls
|
||||||
|
GuiControl* retCtrl = Parent::constructEditControl();
|
||||||
|
if (retCtrl == NULL)
|
||||||
|
return retCtrl;
|
||||||
|
|
||||||
|
// Change filespec
|
||||||
|
char szBuffer[512];
|
||||||
|
|
||||||
|
const char* previewImage;
|
||||||
|
|
||||||
|
if (mInspector->getInspectObject() != NULL)
|
||||||
|
{
|
||||||
|
StringBuilder varNameStr;
|
||||||
|
varNameStr.append(mCaption);
|
||||||
|
if (mFieldArrayIndex != NULL)
|
||||||
|
{
|
||||||
|
varNameStr.append("[");
|
||||||
|
varNameStr.append(mFieldArrayIndex);
|
||||||
|
varNameStr.append("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ShapeAsset\", \"AssetBrowser.changeAsset\", %s, \"%s\");",
|
||||||
|
mInspector->getIdString(), varNameStr.end().c_str());
|
||||||
|
mBrowseButton->setField("Command", szBuffer);
|
||||||
|
|
||||||
|
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
|
||||||
|
|
||||||
|
previewImage = mInspector->getInspectObject()->getDataField(varNameStr.end().c_str(), NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if we don't have a target object, we'll be manipulating the desination value directly
|
||||||
|
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ShapeAsset\", \"AssetBrowser.changeAsset\", %s, \"%s\");",
|
||||||
|
mInspector->getIdString(), mVariableName);
|
||||||
|
mBrowseButton->setField("Command", szBuffer);
|
||||||
|
|
||||||
|
previewImage = Con::getVariable(mVariableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
mLabel = new GuiTextCtrl();
|
||||||
|
mLabel->registerObject();
|
||||||
|
mLabel->setControlProfile(mProfile);
|
||||||
|
mLabel->setText(mCaption);
|
||||||
|
addObject(mLabel);
|
||||||
|
|
||||||
|
//
|
||||||
|
GuiTextEditCtrl* editTextCtrl = static_cast<GuiTextEditCtrl*>(retCtrl);
|
||||||
|
GuiControlProfile* toolEditProfile;
|
||||||
|
if (Sim::findObject("ToolsGuiTextEditProfile", toolEditProfile))
|
||||||
|
editTextCtrl->setControlProfile(toolEditProfile);
|
||||||
|
|
||||||
|
GuiControlProfile* toolDefaultProfile = NULL;
|
||||||
|
Sim::findObject("ToolsGuiDefaultProfile", toolDefaultProfile);
|
||||||
|
|
||||||
|
//
|
||||||
|
mPreviewImage = new GuiBitmapCtrl();
|
||||||
|
mPreviewImage->registerObject();
|
||||||
|
|
||||||
|
if (toolDefaultProfile)
|
||||||
|
mPreviewImage->setControlProfile(toolDefaultProfile);
|
||||||
|
|
||||||
|
updatePreviewImage();
|
||||||
|
|
||||||
|
addObject(mPreviewImage);
|
||||||
|
|
||||||
|
//
|
||||||
|
mPreviewBorderButton = new GuiBitmapButtonCtrl();
|
||||||
|
mPreviewBorderButton->registerObject();
|
||||||
|
|
||||||
|
if (toolDefaultProfile)
|
||||||
|
mPreviewBorderButton->setControlProfile(toolDefaultProfile);
|
||||||
|
|
||||||
|
mPreviewBorderButton->_setBitmap(StringTable->insert("ToolsModule:cubemapBtnBorder_n_image"));
|
||||||
|
|
||||||
|
mPreviewBorderButton->setField("Command", szBuffer); //clicking the preview does the same thing as the edit button, for simplicity
|
||||||
|
addObject(mPreviewBorderButton);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create "Open in Editor" button
|
||||||
|
mEditButton = new GuiBitmapButtonCtrl();
|
||||||
|
|
||||||
|
dSprintf(szBuffer, sizeof(szBuffer), "ShapeEditorPlugin.openShapeAssetId(%d.getText());", retCtrl->getId());
|
||||||
|
mEditButton->setField("Command", szBuffer);
|
||||||
|
|
||||||
|
mEditButton->setText("Edit");
|
||||||
|
mEditButton->setSizing(horizResizeLeft, vertResizeAspectTop);
|
||||||
|
|
||||||
|
mEditButton->setDataField(StringTable->insert("Profile"), NULL, "ToolsGuiButtonProfile");
|
||||||
|
mEditButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||||
|
mEditButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||||
|
mEditButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this asset in the Shape Editor");
|
||||||
|
|
||||||
|
mEditButton->registerObject();
|
||||||
|
addObject(mEditButton);
|
||||||
|
|
||||||
|
//
|
||||||
|
mUseHeightOverride = true;
|
||||||
|
mHeightOverride = 72;
|
||||||
|
|
||||||
|
return retCtrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiInspectorTypeShapeAssetRef::updateRects()
|
||||||
|
{
|
||||||
|
S32 rowSize = 18;
|
||||||
|
S32 dividerPos, dividerMargin;
|
||||||
|
mInspector->getDivider(dividerPos, dividerMargin);
|
||||||
|
Point2I fieldExtent = getExtent();
|
||||||
|
Point2I fieldPos = getPosition();
|
||||||
|
|
||||||
|
mEditCtrlRect.set(0, 0, fieldExtent.x, fieldExtent.y);
|
||||||
|
mLabel->resize(Point2I(mProfile->mTextOffset.x, 0), Point2I(fieldExtent.x, rowSize));
|
||||||
|
|
||||||
|
RectI previewRect = RectI(Point2I(mProfile->mTextOffset.x, rowSize), Point2I(50, 50));
|
||||||
|
mPreviewBorderButton->resize(previewRect.point, previewRect.extent);
|
||||||
|
mPreviewImage->resize(previewRect.point, previewRect.extent);
|
||||||
|
|
||||||
|
S32 editPos = previewRect.point.x + previewRect.extent.x + 10;
|
||||||
|
mEdit->resize(Point2I(editPos, rowSize * 1.5), Point2I(fieldExtent.x - editPos - 5, rowSize));
|
||||||
|
|
||||||
|
mEditButton->resize(Point2I(fieldExtent.x - 105, previewRect.point.y + previewRect.extent.y - rowSize), Point2I(100, rowSize));
|
||||||
|
|
||||||
|
mBrowseButton->setHidden(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiInspectorTypeShapeAssetRef::updateValue()
|
||||||
|
{
|
||||||
|
Parent::updateValue();
|
||||||
|
|
||||||
|
updatePreviewImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiInspectorTypeShapeAssetRef::updatePreviewImage()
|
||||||
|
{
|
||||||
|
const char* previewImage;
|
||||||
|
if (mInspector->getInspectObject() != NULL)
|
||||||
|
previewImage = mInspector->getInspectObject()->getDataField(mCaption, NULL);
|
||||||
|
else
|
||||||
|
previewImage = Con::getVariable(mVariableName);
|
||||||
|
|
||||||
|
//if what we're working with isn't even a valid asset, don't present like we found a good one
|
||||||
|
if (!AssetDatabase.isDeclaredAsset(previewImage))
|
||||||
|
{
|
||||||
|
mPreviewImage->setBitmap(StringTable->EmptyString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String shpPreviewAssetId = String(previewImage) + "_PreviewImage";
|
||||||
|
shpPreviewAssetId.replace(":", "_");
|
||||||
|
shpPreviewAssetId = "ToolsModule:" + shpPreviewAssetId;
|
||||||
|
if (AssetDatabase.isDeclaredAsset(shpPreviewAssetId.c_str()))
|
||||||
|
{
|
||||||
|
mPreviewImage->setBitmap(StringTable->insert(shpPreviewAssetId.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPreviewImage->getBitmapAsset().isNull())
|
||||||
|
mPreviewImage->setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiInspectorTypeShapeAssetRef::setPreviewImage(StringTableEntry assetId)
|
||||||
|
{
|
||||||
|
//if what we're working with isn't even a valid asset, don't present like we found a good one
|
||||||
|
if (!AssetDatabase.isDeclaredAsset(assetId))
|
||||||
|
{
|
||||||
|
mPreviewImage->setBitmap(StringTable->EmptyString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String shpPreviewAssetId = String(assetId) + "_PreviewImage";
|
||||||
|
shpPreviewAssetId.replace(":", "_");
|
||||||
|
shpPreviewAssetId = "ToolsModule:" + shpPreviewAssetId;
|
||||||
|
if (AssetDatabase.isDeclaredAsset(shpPreviewAssetId.c_str()))
|
||||||
|
{
|
||||||
|
mPreviewImage->setBitmap(StringTable->insert(shpPreviewAssetId.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPreviewImage->getBitmapAsset().isNull())
|
||||||
|
mPreviewImage->setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,10 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
static StringTableEntry smNoShapeAssetFallback;
|
static StringTableEntry smNoShapeAssetFallback;
|
||||||
|
static AssetPtr<ShapeAsset> smNoShapeAssetFallbackAssetPtr;
|
||||||
|
|
||||||
static const String mErrCodeStrings[U32(ShapeAssetErrCode::Extended) - U32(Parent::Extended) + 1];
|
static const String mErrCodeStrings[U32(ShapeAssetErrCode::Extended) - U32(Parent::Extended) + 1];
|
||||||
static U32 getAssetErrCode(ConcreteAssetPtr checkAsset) { if (checkAsset) return checkAsset->mLoadedState; else return 0; }
|
static U32 getAssetErrCode(const ConcreteAssetPtr& checkAsset) { if (checkAsset) return checkAsset->mLoadedState; else return 0; }
|
||||||
|
|
||||||
static String getAssetErrstrn(U32 errCode)
|
static String getAssetErrstrn(U32 errCode)
|
||||||
{
|
{
|
||||||
|
|
@ -94,14 +95,6 @@ private:
|
||||||
StringTableEntry mDiffuseImposterFileName;
|
StringTableEntry mDiffuseImposterFileName;
|
||||||
StringTableEntry mNormalImposterFileName;
|
StringTableEntry mNormalImposterFileName;
|
||||||
|
|
||||||
//Material assets we're dependent on and use
|
|
||||||
Vector<StringTableEntry> mMaterialAssetIds;
|
|
||||||
Vector<AssetPtr<MaterialAsset>> mMaterialAssets;
|
|
||||||
|
|
||||||
//Animation assets we're dependent on and use
|
|
||||||
Vector<StringTableEntry> mAnimationAssetIds;
|
|
||||||
Vector<AssetPtr<ShapeAnimationAsset>> mAnimationAssets;
|
|
||||||
|
|
||||||
Resource<TSShape> mShape;
|
Resource<TSShape> mShape;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
@ -115,39 +108,17 @@ public:
|
||||||
static void initPersistFields();
|
static void initPersistFields();
|
||||||
void copyTo(SimObject* object) override;
|
void copyTo(SimObject* object) override;
|
||||||
|
|
||||||
virtual void setDataField(StringTableEntry slotName, StringTableEntry array, StringTableEntry value);
|
|
||||||
|
|
||||||
/// Declare Console Object.
|
/// Declare Console Object.
|
||||||
DECLARE_CONOBJECT(ShapeAsset);
|
DECLARE_CONOBJECT(ShapeAsset);
|
||||||
|
|
||||||
U32 load() override;
|
U32 load() override;
|
||||||
|
bool preloadMaterialList();
|
||||||
|
|
||||||
TSShape* getShape() { load(); return mShape; }
|
TSShape* getShape();
|
||||||
|
Resource<TSShape> getShapeResource();
|
||||||
Resource<TSShape> getShapeResource() { load(); return mShape; }
|
|
||||||
|
|
||||||
void SplitSequencePathAndName(String& srcPath, String& srcName);
|
|
||||||
|
|
||||||
U32 getShapeFilenameHash() { return _StringTable::hashString(mShapeFile); }
|
U32 getShapeFilenameHash() { return _StringTable::hashString(mShapeFile); }
|
||||||
|
|
||||||
Vector<AssetPtr<MaterialAsset>> getMaterialAssets() { return mMaterialAssets; }
|
|
||||||
|
|
||||||
inline AssetPtr<MaterialAsset> getMaterialAsset(U32 matId)
|
|
||||||
{
|
|
||||||
if (matId >= mMaterialAssets.size())
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
return mMaterialAssets[matId];
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearMaterialAssets() { mMaterialAssets.clear(); }
|
|
||||||
|
|
||||||
void addMaterialAssets(AssetPtr<MaterialAsset> matPtr) { mMaterialAssets.push_back(matPtr); }
|
|
||||||
|
|
||||||
S32 getMaterialCount() { return mMaterialAssets.size(); }
|
|
||||||
S32 getAnimationCount() { return mAnimationAssets.size(); }
|
|
||||||
ShapeAnimationAsset* getAnimation(S32 index);
|
|
||||||
|
|
||||||
void _onResourceChanged(const Torque::Path& path);
|
void _onResourceChanged(const Torque::Path& path);
|
||||||
|
|
||||||
void setShapeFile(const char* pScriptFile);
|
void setShapeFile(const char* pScriptFile);
|
||||||
|
|
@ -163,11 +134,18 @@ public:
|
||||||
void setNormalImposterFile(const char* pImageFile);
|
void setNormalImposterFile(const char* pImageFile);
|
||||||
inline StringTableEntry getNormalImposterFile(void) const { return mNormalImposterFileName; };
|
inline StringTableEntry getNormalImposterFile(void) const { return mNormalImposterFileName; };
|
||||||
|
|
||||||
|
|
||||||
static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAsset>* shapeAsset);
|
static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAsset>* shapeAsset);
|
||||||
|
|
||||||
static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
|
static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
|
||||||
static U32 getAssetById(StringTableEntry assetId, AssetPtr<ShapeAsset>* shapeAsset);
|
static U32 getAssetById(StringTableEntry assetId, AssetPtr<ShapeAsset>* shapeAsset);
|
||||||
|
|
||||||
|
StringTableEntry getMaterial(const S32& index);
|
||||||
|
U32 getMaterialCount();
|
||||||
|
|
||||||
|
StringTableEntry getAnimation(const S32& index);
|
||||||
|
U32 getAnimationCount();
|
||||||
|
|
||||||
#ifdef TORQUE_TOOLS
|
#ifdef TORQUE_TOOLS
|
||||||
const char* generateCachedPreviewImage(S32 resolution, String overrideMaterial = "");
|
const char* generateCachedPreviewImage(S32 resolution, String overrideMaterial = "");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -201,6 +179,9 @@ DefineConsoleType(TypeShapeAssetId, String)
|
||||||
DECLARE_STRUCT(AssetPtr<ShapeAsset>)
|
DECLARE_STRUCT(AssetPtr<ShapeAsset>)
|
||||||
DefineConsoleType(TypeShapeAssetPtr, AssetPtr<ShapeAsset>)
|
DefineConsoleType(TypeShapeAssetPtr, AssetPtr<ShapeAsset>)
|
||||||
|
|
||||||
|
DECLARE_STRUCT(AssetRef<ShapeAsset>)
|
||||||
|
DefineConsoleType(TypeShapeAssetRef, AssetRef<ShapeAsset>)
|
||||||
|
|
||||||
#ifdef TORQUE_TOOLS
|
#ifdef TORQUE_TOOLS
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// TypeAssetId GuiInspectorField Class
|
// TypeAssetId GuiInspectorField Class
|
||||||
|
|
@ -236,255 +217,29 @@ public:
|
||||||
static void consoleInit();
|
static void consoleInit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class GuiInspectorTypeShapeAssetRef : public GuiInspectorTypeFileName
|
||||||
|
{
|
||||||
|
typedef GuiInspectorTypeFileName Parent;
|
||||||
|
public:
|
||||||
|
|
||||||
|
GuiTextCtrl* mLabel;
|
||||||
|
GuiBitmapButtonCtrl* mPreviewBorderButton;
|
||||||
|
GuiBitmapCtrl* mPreviewImage;
|
||||||
|
GuiButtonCtrl* mEditButton;
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(GuiInspectorTypeShapeAssetRef);
|
||||||
|
static void consoleInit();
|
||||||
|
|
||||||
|
GuiControl* constructEditControl() override;
|
||||||
|
bool updateRects() override;
|
||||||
|
|
||||||
|
void updateValue() override;
|
||||||
|
|
||||||
|
void updatePreviewImage();
|
||||||
|
void setPreviewImage(StringTableEntry assetId);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// REFACTOR
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#pragma region Refactor Asset Macros
|
|
||||||
|
|
||||||
#define DECLARE_SHAPEASSET_REFACTOR(className, name) \
|
|
||||||
private: \
|
|
||||||
AssetPtr<ShapeAsset> m##name##Asset; \
|
|
||||||
StringTableEntry m##name##File = StringTable->EmptyString(); \
|
|
||||||
public: \
|
|
||||||
void _set##name(StringTableEntry _in) { \
|
|
||||||
if (m##name##Asset.getAssetId() == _in) \
|
|
||||||
return; \
|
|
||||||
if(get##name##File() == _in) \
|
|
||||||
return; \
|
|
||||||
if(_in == NULL || !String::compare(_in,StringTable->EmptyString())) \
|
|
||||||
{ \
|
|
||||||
m##name##Asset = NULL; \
|
|
||||||
m##name##File = ""; \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
if (!AssetDatabase.isDeclaredAsset(_in)) \
|
|
||||||
{ \
|
|
||||||
StringTableEntry 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(); } \
|
|
||||||
TSShape* get##name() { if (m##name##Asset.notNull()) return m##name##Asset->getShape(); else return NULL; } \
|
|
||||||
AssetPtr<ShapeAsset> get##name##Asset(void) { return m##name##Asset; } \
|
|
||||||
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data)); return false; } \
|
|
||||||
StringTableEntry get##name##File() { return m##name##Asset.notNull() ? m##name##Asset->getShapeFile() : ""; }
|
|
||||||
|
|
||||||
#define DECLARE_SHAPEASSET_NET_REFACTOR(className, name, mask) \
|
|
||||||
private: \
|
|
||||||
AssetPtr<ShapeAsset> m##name##Asset; \
|
|
||||||
StringTableEntry m##name##File = StringTable->EmptyString(); \
|
|
||||||
public: \
|
|
||||||
void _set##name(StringTableEntry _in) { \
|
|
||||||
if (m##name##Asset.getAssetId() == _in) \
|
|
||||||
return; \
|
|
||||||
if(get##name##File() == _in) \
|
|
||||||
return; \
|
|
||||||
if(_in == NULL || !String::compare(_in,StringTable->EmptyString())) \
|
|
||||||
{ \
|
|
||||||
m##name##Asset = NULL; \
|
|
||||||
m##name##File = ""; \
|
|
||||||
setMaskBits(mask); \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
if (!AssetDatabase.isDeclaredAsset(_in)) \
|
|
||||||
{ \
|
|
||||||
StringTableEntry 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(); } \
|
|
||||||
TSShape* get##name() { if (m##name##Asset.notNull()) return m##name##Asset->getShape(); else return NULL; } \
|
|
||||||
AssetPtr<ShapeAsset> get##name##Asset(void) { return m##name##Asset; } \
|
|
||||||
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data)); return false; } \
|
|
||||||
StringTableEntry get##name##File() { return m##name##Asset.notNull() ? m##name##Asset->getShapeFile() : ""; }
|
|
||||||
|
|
||||||
#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.), AbstractClassRep::FIELD_HideInInspectors);
|
|
||||||
|
|
||||||
|
|
||||||
#define DECLARE_SHAPEASSET_ARRAY_REFACTOR(className, name, max) \
|
|
||||||
private: \
|
|
||||||
AssetPtr<ShapeAsset> m##name##Asset[max]; \
|
|
||||||
StringTableEntry m##name##File[max] = {StringTable->EmptyString() }; \
|
|
||||||
public: \
|
|
||||||
void _set##name(StringTableEntry _in, const U32& index){ \
|
|
||||||
if (m##name##Asset[index].getAssetId() == _in) \
|
|
||||||
return; \
|
|
||||||
if(get##name##File(index) == _in) \
|
|
||||||
return; \
|
|
||||||
if(_in == NULL || !String::compare(_in,StringTable->EmptyString())) \
|
|
||||||
{ \
|
|
||||||
m##name##Asset[index] = NULL; \
|
|
||||||
m##name##File[index] = ""; \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
if (!AssetDatabase.isDeclaredAsset(_in)) \
|
|
||||||
{ \
|
|
||||||
StringTableEntry 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(); } \
|
|
||||||
TSShape* get##name(const U32& index) { if (m##name##Asset[index].notNull()) return m##name##Asset[index]->getShape(); else return NULL; } \
|
|
||||||
AssetPtr<ShapeAsset> get##name##Asset(const U32& index) { return m##name##Asset[index]; } \
|
|
||||||
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data), dAtoi(index)); return false;}\
|
|
||||||
StringTableEntry get##name##File(const U32& idx) { return m##name##Asset[idx].notNull() ? m##name##Asset[idx]->getShapeFile() : ""; }
|
|
||||||
|
|
||||||
#define DECLARE_SHAPEASSET_ARRAY_NET_REFACTOR(className, name, max, mask) \
|
|
||||||
private: \
|
|
||||||
AssetPtr<ShapeAsset> m##name##Asset[max]; \
|
|
||||||
StringTableEntry m##name##File[max] = {StringTable->EmptyString() }; \
|
|
||||||
public: \
|
|
||||||
void _set##name(StringTableEntry _in, const U32& index){ \
|
|
||||||
if (m##name##Asset[index].getAssetId() == _in) \
|
|
||||||
return; \
|
|
||||||
if(get##name##File(index) == _in) \
|
|
||||||
return; \
|
|
||||||
if (_in == NULL || !String::compare(_in,StringTable->EmptyString())) \
|
|
||||||
{ \
|
|
||||||
m##name##Asset[index] = NULL; \
|
|
||||||
m##name##File[index] = ""; \
|
|
||||||
setMaskBits(mask); \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
if (!AssetDatabase.isDeclaredAsset(_in)) \
|
|
||||||
{ \
|
|
||||||
StringTableEntry 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(); } \
|
|
||||||
TSShape* get##name(const U32& index) { if (m##name##Asset[index].notNull()) return m##name##Asset[index]->getShape(); else return NULL; } \
|
|
||||||
AssetPtr<ShapeAsset> get##name##Asset(const U32& index) { return m##name##Asset[index]; } \
|
|
||||||
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data), dAtoi(index)); return false;}\
|
|
||||||
StringTableEntry get##name##File(const U32& idx) { return m##name##Asset[idx].notNull() ? m##name##Asset[idx]->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
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// REFACTOR END
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ DebrisData::DebrisData()
|
||||||
terminalVelocity = 0.0f;
|
terminalVelocity = 0.0f;
|
||||||
ignoreWater = true;
|
ignoreWater = true;
|
||||||
|
|
||||||
mShapeAsset.registerRefreshNotify(this);
|
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#define TRACK_DEBRIS_DATA_CLONES
|
//#define TRACK_DEBRIS_DATA_CLONES
|
||||||
|
|
@ -152,7 +152,7 @@ DebrisData::DebrisData(const DebrisData& other, bool temp_clone) : GameBaseData(
|
||||||
terminalVelocity = other.terminalVelocity;
|
terminalVelocity = other.terminalVelocity;
|
||||||
ignoreWater = other.ignoreWater;
|
ignoreWater = other.ignoreWater;
|
||||||
|
|
||||||
mShapeAsset = other.mShapeAsset;
|
shapeAssetRef = other.shapeAssetRef;
|
||||||
|
|
||||||
textureName = other.textureName;
|
textureName = other.textureName;
|
||||||
explosionId = other.explosionId; // -- for pack/unpack of explosion ptr
|
explosionId = other.explosionId; // -- for pack/unpack of explosion ptr
|
||||||
|
|
@ -191,7 +191,7 @@ DebrisData* DebrisData::cloneAndPerformSubstitutions(const SimObject* owner, S32
|
||||||
|
|
||||||
void DebrisData::onPerformSubstitutions()
|
void DebrisData::onPerformSubstitutions()
|
||||||
{
|
{
|
||||||
_setShape(_getShapeAssetId());
|
shapeAssetRef = shapeAssetRef.assetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebrisData::onAdd()
|
bool DebrisData::onAdd()
|
||||||
|
|
@ -278,17 +278,21 @@ bool DebrisData::preload(bool server, String &errorStr)
|
||||||
|
|
||||||
if( server ) return true;
|
if( server ) return true;
|
||||||
|
|
||||||
if (getShape())
|
if (!shapeAssetRef.isNull())
|
||||||
{
|
{
|
||||||
TSShapeInstance* pDummy = new TSShapeInstance(getShape(), !server);
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
delete pDummy;
|
if (shape)
|
||||||
if (!server && !getShape()->preloadMaterialList(getShapeFile()) && NetConnection::filesWereDownloaded())
|
{
|
||||||
|
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||||
|
delete pDummy;
|
||||||
|
if (!server && !shapeAssetRef.assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorStr = String::ToString("DebrisData(%s)::preload: Couldn't load shape \"%s\"", getName(), shapeAssetRef.assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!mShapeAsset.isNull())
|
|
||||||
{
|
|
||||||
errorStr = String::ToString("DebrisData::load: Couldn't load shape \"%s\"", _getShapeAssetId());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -305,7 +309,8 @@ void DebrisData::initPersistFields()
|
||||||
addGroup("Shapes");
|
addGroup("Shapes");
|
||||||
addField("texture", TypeString, Offset(textureName, DebrisData),
|
addField("texture", TypeString, Offset(textureName, DebrisData),
|
||||||
"@brief Texture imagemap to use for this debris object.\n\nNot used any more.\n", AbstractClassRep::FIELD_HideInInspectors);
|
"@brief Texture imagemap to use for this debris object.\n\nNot used any more.\n", AbstractClassRep::FIELD_HideInInspectors);
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, DebrisData, "Shape to use for this debris object.");
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, DebrisData))
|
||||||
|
.doc("Shape to use for this debris object.");
|
||||||
endGroup("Shapes");
|
endGroup("Shapes");
|
||||||
|
|
||||||
addGroup("Particle Effects");
|
addGroup("Particle Effects");
|
||||||
|
|
@ -390,7 +395,7 @@ void DebrisData::packData(BitStream* stream)
|
||||||
|
|
||||||
stream->writeString( textureName );
|
stream->writeString( textureName );
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(Shape);
|
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||||
|
|
||||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||||
{
|
{
|
||||||
|
|
@ -434,7 +439,7 @@ void DebrisData::unpackData(BitStream* stream)
|
||||||
|
|
||||||
textureName = stream->readSTString();
|
textureName = stream->readSTString();
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
|
||||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||||
{
|
{
|
||||||
|
|
@ -677,18 +682,19 @@ bool Debris::onAdd()
|
||||||
mFriction = mDataBlock->friction;
|
mFriction = mDataBlock->friction;
|
||||||
|
|
||||||
// Setup our bounding box
|
// Setup our bounding box
|
||||||
if( mDataBlock->getShape())
|
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
|
||||||
|
|
||||||
|
Resource<TSShape> shape;
|
||||||
|
if( mDataBlock->shapeAssetRef.notNull())
|
||||||
{
|
{
|
||||||
mObjBox = mDataBlock->getShape()->mBounds;
|
shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
}
|
if (shape)
|
||||||
else
|
mObjBox = shape->mBounds;
|
||||||
{
|
|
||||||
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( mDataBlock->getShape())
|
if(shape)
|
||||||
{
|
{
|
||||||
mShape = new TSShapeInstance( mDataBlock->getShape(), true);
|
mShape = new TSShapeInstance(shape, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( mPart )
|
if( mPart )
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ struct DebrisData : public GameBaseData, protected AssetPtrCallback
|
||||||
F32 terminalVelocity; // max velocity magnitude
|
F32 terminalVelocity; // max velocity magnitude
|
||||||
bool ignoreWater;
|
bool ignoreWater;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(DebrisData, Shape)
|
AssetRef<ShapeAsset> shapeAssetRef;
|
||||||
|
|
||||||
StringTableEntry textureName;
|
StringTableEntry textureName;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
IMPLEMENT_CO_NETOBJECT_V1(RenderShapeExample);
|
IMPLEMENT_CO_NETOBJECT_V1(RenderShapeExample);
|
||||||
|
|
||||||
ConsoleDocClass( RenderShapeExample,
|
ConsoleDocClass( RenderShapeExample,
|
||||||
"@brief An example scene object which renders a DTS.\n\n"
|
"@brief An example scene object which renders a shape asset.\n\n"
|
||||||
"This class implements a basic SceneObject that can exist in the world at a "
|
"This class implements a basic SceneObject that can exist in the world at a "
|
||||||
"3D position and render itself. There are several valid ways to render an "
|
"3D position and render itself. There are several valid ways to render an "
|
||||||
"object in Torque. This class makes use of the 'TS' (three space) shape "
|
"object in Torque. This class makes use of the 'TS' (three space) shape "
|
||||||
|
|
@ -74,7 +74,9 @@ void RenderShapeExample::initPersistFields()
|
||||||
docsURL;
|
docsURL;
|
||||||
Parent::initPersistFields();
|
Parent::initPersistFields();
|
||||||
addGroup( "Shapes" );
|
addGroup( "Shapes" );
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, RenderShapeExample, "The path to the shape file.")
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(mShapeAssetRef, RenderShapeExample))
|
||||||
|
.doc("The shape asset to render.")
|
||||||
|
.network(UpdateMask);
|
||||||
endGroup( "Shapes" );
|
endGroup( "Shapes" );
|
||||||
|
|
||||||
// SceneObject already handles exposing the transform
|
// SceneObject already handles exposing the transform
|
||||||
|
|
@ -83,10 +85,6 @@ void RenderShapeExample::initPersistFields()
|
||||||
void RenderShapeExample::inspectPostApply()
|
void RenderShapeExample::inspectPostApply()
|
||||||
{
|
{
|
||||||
Parent::inspectPostApply();
|
Parent::inspectPostApply();
|
||||||
|
|
||||||
// Flag the network mask to send the updates
|
|
||||||
// to the client object
|
|
||||||
setMaskBits( UpdateMask );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderShapeExample::onAdd()
|
bool RenderShapeExample::onAdd()
|
||||||
|
|
@ -146,7 +144,7 @@ U32 RenderShapeExample::packUpdate( NetConnection *conn, U32 mask, BitStream *st
|
||||||
// Write out any of the updated editable properties
|
// Write out any of the updated editable properties
|
||||||
if ( stream->writeFlag( mask & UpdateMask ) )
|
if ( stream->writeFlag( mask & UpdateMask ) )
|
||||||
{
|
{
|
||||||
PACK_ASSET_REFACTOR(conn, Shape);
|
AssetDatabase.packUpdateAsset(conn, mask, stream, mShapeAssetRef.assetId);
|
||||||
|
|
||||||
// Allow the server object a chance to handle a new shape
|
// Allow the server object a chance to handle a new shape
|
||||||
createShape();
|
createShape();
|
||||||
|
|
@ -170,7 +168,7 @@ void RenderShapeExample::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
|
|
||||||
if ( stream->readFlag() ) // UpdateMask
|
if ( stream->readFlag() ) // UpdateMask
|
||||||
{
|
{
|
||||||
UNPACK_ASSET_REFACTOR(conn, Shape);
|
mShapeAssetRef = AssetDatabase.unpackUpdateAsset(conn, stream);
|
||||||
|
|
||||||
if ( isProperlyAdded() )
|
if ( isProperlyAdded() )
|
||||||
createShape();
|
createShape();
|
||||||
|
|
@ -182,28 +180,35 @@ void RenderShapeExample::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void RenderShapeExample::createShape()
|
void RenderShapeExample::createShape()
|
||||||
{
|
{
|
||||||
if ( mShapeAsset.isNull() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Clean up our previous shape
|
// Clean up our previous shape
|
||||||
if ( mShapeInstance )
|
if ( mShapeInstance )
|
||||||
SAFE_DELETE( mShapeInstance );
|
SAFE_DELETE( mShapeInstance );
|
||||||
|
|
||||||
|
if (!mShapeAssetRef.hasAssetId()) //literally nothing to do here
|
||||||
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape;
|
||||||
|
|
||||||
|
if (mShapeAssetRef.assetPtr.notNull())
|
||||||
|
shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
else
|
||||||
|
shape = ShapeAsset::smNoShapeAssetFallbackAssetPtr->getShapeResource();
|
||||||
|
|
||||||
// Attempt to preload the Materials for this shape
|
// Attempt to preload the Materials for this shape
|
||||||
if ( isClientObject() &&
|
if ( isClientObject() &&
|
||||||
!getShape()->preloadMaterialList(getShapeFile()) &&
|
!mShapeAssetRef.assetPtr->preloadMaterialList() &&
|
||||||
NetConnection::filesWereDownloaded() )
|
NetConnection::filesWereDownloaded() )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the bounding box
|
// Update the bounding box
|
||||||
mObjBox = getShape()->mBounds;
|
mObjBox = shape->mBounds;
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
setRenderTransform(mObjToWorld);
|
setRenderTransform(mObjToWorld);
|
||||||
|
|
||||||
// Create the TSShapeInstance
|
// Create the TSShapeInstance
|
||||||
mShapeInstance = new TSShapeInstance(getShape(), isClientObject() );
|
mShapeInstance = new TSShapeInstance(shape, isClientObject() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderShapeExample::prepRenderImage( SceneRenderState *state )
|
void RenderShapeExample::prepRenderImage( SceneRenderState *state )
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ class RenderShapeExample : public SceneObject
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Rendering variables
|
// Rendering variables
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
DECLARE_SHAPEASSET_REFACTOR(RenderShapeExample, Shape)
|
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||||
|
|
||||||
// The actual shape instance
|
// The actual shape instance
|
||||||
TSShapeInstance* mShapeInstance;
|
TSShapeInstance* mShapeInstance;
|
||||||
|
|
|
||||||
320
Engine/source/T3D/examples/shapeDatablockExample.cpp
Normal file
320
Engine/source/T3D/examples/shapeDatablockExample.cpp
Normal file
|
|
@ -0,0 +1,320 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2026 Jeff Raab, LLC
|
||||||
|
// Portions Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "T3D/examples/shapeDatablockExample.h"
|
||||||
|
|
||||||
|
#include "math/mathIO.h"
|
||||||
|
#include "sim/netConnection.h"
|
||||||
|
#include "scene/sceneRenderState.h"
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
#include "core/resourceManager.h"
|
||||||
|
#include "core/stream/bitStream.h"
|
||||||
|
#include "gfx/gfxTransformSaver.h"
|
||||||
|
#include "renderInstance/renderPassManager.h"
|
||||||
|
#include "lighting/lightQuery.h"
|
||||||
|
|
||||||
|
IMPLEMENT_CO_DATABLOCK_V1(ShapeDatablockExampleData);
|
||||||
|
|
||||||
|
ShapeDatablockExampleData::ShapeDatablockExampleData()
|
||||||
|
{
|
||||||
|
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeDatablockExampleData::ShapeDatablockExampleData(const ShapeDatablockExampleData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||||
|
{
|
||||||
|
shapeAssetRef = other.shapeAssetRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeDatablockExampleData::~ShapeDatablockExampleData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShapeDatablockExampleData::initPersistFields()
|
||||||
|
{
|
||||||
|
docsURL;
|
||||||
|
addGroup("Shapes");
|
||||||
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, ShapeDatablockExampleData))
|
||||||
|
.doc("The shape asset to render.");
|
||||||
|
endGroup("Shapes");
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShapeDatablockExampleData::preload(bool server, String& errorStr)
|
||||||
|
{
|
||||||
|
if (!shapeAssetRef.isNull())
|
||||||
|
{
|
||||||
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (shape)
|
||||||
|
{
|
||||||
|
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||||
|
delete pDummy;
|
||||||
|
if (!server && !shapeAssetRef.assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorStr = String::ToString("ShapeDatablockExampleData(%s)::preload: Couldn't load shape asset\"%s\"", getName(), shapeAssetRef.assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShapeDatablockExampleData::packData(BitStream* stream)
|
||||||
|
{
|
||||||
|
Parent::packData(stream);
|
||||||
|
|
||||||
|
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShapeDatablockExampleData::unpackData(BitStream* stream)
|
||||||
|
{
|
||||||
|
Parent::unpackData(stream);
|
||||||
|
|
||||||
|
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_CO_NETOBJECT_V1(ShapeDatablockExample);
|
||||||
|
|
||||||
|
ConsoleDocClass(ShapeDatablockExample,
|
||||||
|
"@brief An example scene object which renders a shape that utilizes a datablock.\n\n"
|
||||||
|
"This class implements a basic SceneObject that can exist in the world at a "
|
||||||
|
"3D position and render itself. There are several valid ways to render an "
|
||||||
|
"object in Torque. This class makes use of the 'TS' (three space) shape "
|
||||||
|
"system, while containing the shape data to be rendered in a datablock. "
|
||||||
|
"TS manages loading the various mesh formats supported by Torque as "
|
||||||
|
"well was rendering those meshes (including LOD and animation...though this "
|
||||||
|
"example doesn't include any animation over time).\n\n"
|
||||||
|
"See the C++ code for implementation details.\n\n"
|
||||||
|
"@ingroup Examples\n");
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Object setup and teardown
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
ShapeDatablockExample::ShapeDatablockExample()
|
||||||
|
{
|
||||||
|
// Flag this object so that it will always
|
||||||
|
// be sent across the network to clients
|
||||||
|
mNetFlags.set(Ghostable | ScopeAlways);
|
||||||
|
|
||||||
|
// Set it as a "static" object.
|
||||||
|
mTypeMask |= StaticObjectType | StaticShapeObjectType;
|
||||||
|
|
||||||
|
mDataBlock = NULL;
|
||||||
|
|
||||||
|
// Make sure to initialize our TSShapeInstance to NULL
|
||||||
|
mShapeInstance = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeDatablockExample::~ShapeDatablockExample()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Object Editing
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ShapeDatablockExample::initPersistFields()
|
||||||
|
{
|
||||||
|
docsURL;
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ShapeDatablockExample::onAdd()
|
||||||
|
{
|
||||||
|
if (!Parent::onAdd())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Set up a 1x1x1 bounding box
|
||||||
|
mObjBox.set(Point3F(-0.5f, -0.5f, -0.5f),
|
||||||
|
Point3F(0.5f, 0.5f, 0.5f));
|
||||||
|
|
||||||
|
resetWorldBox();
|
||||||
|
|
||||||
|
// Add this object to the scene
|
||||||
|
addToScene();
|
||||||
|
|
||||||
|
if (mDataBlock && !onNewDataBlock(mDataBlock, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShapeDatablockExample::onNewDataBlock(GameBaseData* dptr, bool reload)
|
||||||
|
{
|
||||||
|
// EDITOR FEATURE: Remove us from old datablock's reload signal and
|
||||||
|
// add us to the new one.
|
||||||
|
if (!reload)
|
||||||
|
{
|
||||||
|
if (mDataBlock)
|
||||||
|
mDataBlock->mReloadSignal.remove(this, &ShapeDatablockExample::_onDatablockModified);
|
||||||
|
if (dptr)
|
||||||
|
dptr->mReloadSignal.notify(this, &ShapeDatablockExample::_onDatablockModified);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDataBlock = dynamic_cast<ShapeDatablockExampleData*>(dptr);
|
||||||
|
if (!mDataBlock)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mShapeInstance)
|
||||||
|
SAFE_DELETE(mShapeInstance);
|
||||||
|
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
|
mShapeInstance = new TSShapeInstance(shape);
|
||||||
|
|
||||||
|
#ifdef TORQUE_AFX_ENABLED
|
||||||
|
// Don't set mask when new datablock is a temp-clone.
|
||||||
|
if (mDataBlock->isTempClone())
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setMaskBits(DataBlockMask);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShapeDatablockExample::_onDatablockModified()
|
||||||
|
{
|
||||||
|
AssertFatal(mDataBlock, "ShapeDatablockExample::onDatablockModified - mDataBlock is NULL.");
|
||||||
|
onNewDataBlock(mDataBlock, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShapeDatablockExample::onRemove()
|
||||||
|
{
|
||||||
|
// Remove this object from the scene
|
||||||
|
removeFromScene();
|
||||||
|
|
||||||
|
// Remove our TSShapeInstance
|
||||||
|
if (mShapeInstance)
|
||||||
|
SAFE_DELETE(mShapeInstance);
|
||||||
|
|
||||||
|
Parent::onRemove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShapeDatablockExample::setTransform(const MatrixF& mat)
|
||||||
|
{
|
||||||
|
// Let SceneObject handle all of the matrix manipulation
|
||||||
|
Parent::setTransform(mat);
|
||||||
|
|
||||||
|
// Dirty our network mask so that the new transform gets
|
||||||
|
// transmitted to the client object
|
||||||
|
setMaskBits(TransformMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 ShapeDatablockExample::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
|
||||||
|
{
|
||||||
|
// Allow the Parent to get a crack at writing its info
|
||||||
|
U32 retMask = Parent::packUpdate(conn, mask, stream);
|
||||||
|
|
||||||
|
// Write our transform information
|
||||||
|
if (stream->writeFlag(mask & TransformMask))
|
||||||
|
{
|
||||||
|
mathWrite(*stream, getTransform());
|
||||||
|
mathWrite(*stream, getScale());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out any of the updated editable properties
|
||||||
|
if (stream->writeFlag(mask & UpdateMask))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return retMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShapeDatablockExample::unpackUpdate(NetConnection* conn, BitStream* stream)
|
||||||
|
{
|
||||||
|
// Let the Parent read any info it sent
|
||||||
|
Parent::unpackUpdate(conn, stream);
|
||||||
|
|
||||||
|
if (stream->readFlag()) // TransformMask
|
||||||
|
{
|
||||||
|
mathRead(*stream, &mObjToWorld);
|
||||||
|
mathRead(*stream, &mObjScale);
|
||||||
|
|
||||||
|
setTransform(mObjToWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->readFlag()) // UpdateMask
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShapeDatablockExample::prepRenderImage(SceneRenderState* state)
|
||||||
|
{
|
||||||
|
// Make sure we have a TSShapeInstance
|
||||||
|
if (!mShapeInstance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Calculate the distance of this object from the camera
|
||||||
|
Point3F cameraOffset;
|
||||||
|
getRenderTransform().getColumn(3, &cameraOffset);
|
||||||
|
cameraOffset -= state->getDiffuseCameraPosition();
|
||||||
|
F32 dist = cameraOffset.len();
|
||||||
|
if (dist < 0.01f)
|
||||||
|
dist = 0.01f;
|
||||||
|
|
||||||
|
// Set up the LOD for the shape
|
||||||
|
F32 invScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
|
||||||
|
|
||||||
|
mShapeInstance->setDetailFromDistance(state, dist * invScale);
|
||||||
|
|
||||||
|
// Make sure we have a valid level of detail
|
||||||
|
if (mShapeInstance->getCurrentDetail() < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// GFXTransformSaver is a handy helper class that restores
|
||||||
|
// the current GFX matrices to their original values when
|
||||||
|
// it goes out of scope at the end of the function
|
||||||
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
// Set up our TS render state
|
||||||
|
TSRenderState rdata;
|
||||||
|
rdata.setSceneState(state);
|
||||||
|
rdata.setFadeOverride(1.0f);
|
||||||
|
|
||||||
|
// We might have some forward lit materials
|
||||||
|
// so pass down a query to gather lights.
|
||||||
|
LightQuery query;
|
||||||
|
query.init(getWorldSphere());
|
||||||
|
rdata.setLightQuery(&query);
|
||||||
|
|
||||||
|
// Set the world matrix to the objects render transform
|
||||||
|
MatrixF mat = getRenderTransform();
|
||||||
|
mat.scale(mObjScale);
|
||||||
|
GFX->setWorldMatrix(mat);
|
||||||
|
|
||||||
|
// Animate the the shape
|
||||||
|
mShapeInstance->animate();
|
||||||
|
|
||||||
|
// Allow the shape to submit the RenderInst(s) for itself
|
||||||
|
mShapeInstance->render(rdata);
|
||||||
|
}
|
||||||
|
|
||||||
103
Engine/source/T3D/examples/shapeDatablockExample.h
Normal file
103
Engine/source/T3D/examples/shapeDatablockExample.h
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef _SHAPEDATABLOCKEXAMPLE_H_
|
||||||
|
#define _SHAPEDATABLOCKEXAMPLE_H_
|
||||||
|
|
||||||
|
#ifndef _GAMEBASE_H_
|
||||||
|
#include "T3D/gameBase/gameBase.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _TSSHAPEINSTANCE_H_
|
||||||
|
#include "ts/tsShapeInstance.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "T3D/assets/ShapeAsset.h"
|
||||||
|
|
||||||
|
struct ShapeDatablockExampleData : public GameBaseData, protected AssetPtrCallback
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef GameBaseData Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AssetRef<ShapeAsset> shapeAssetRef;
|
||||||
|
|
||||||
|
// The derived class should provide the following:
|
||||||
|
DECLARE_CONOBJECT(ShapeDatablockExampleData);
|
||||||
|
DECLARE_CATEGORY("Datablock");
|
||||||
|
ShapeDatablockExampleData();
|
||||||
|
ShapeDatablockExampleData(const ShapeDatablockExampleData&, bool = false);
|
||||||
|
~ShapeDatablockExampleData();
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
bool preload(bool server, String& errorStr) override;
|
||||||
|
void packData(BitStream* stream) override;
|
||||||
|
void unpackData(BitStream* stream) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override
|
||||||
|
{
|
||||||
|
reloadOnLocalClient();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShapeDatablockExample : public GameBase
|
||||||
|
{
|
||||||
|
typedef GameBase Parent;
|
||||||
|
|
||||||
|
ShapeDatablockExampleData* mDataBlock;
|
||||||
|
|
||||||
|
// Networking masks
|
||||||
|
// We need to implement a mask specifically to handle
|
||||||
|
// updating our transform from the server object to its
|
||||||
|
// client-side "ghost". We also need to implement a
|
||||||
|
// maks for handling editor updates to our properties
|
||||||
|
// (like material).
|
||||||
|
enum MaskBits
|
||||||
|
{
|
||||||
|
TransformMask = Parent::NextFreeMask << 0,
|
||||||
|
UpdateMask = Parent::NextFreeMask << 1,
|
||||||
|
NextFreeMask = Parent::NextFreeMask << 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// The actual shape instance
|
||||||
|
TSShapeInstance* mShapeInstance;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShapeDatablockExample();
|
||||||
|
virtual ~ShapeDatablockExample();
|
||||||
|
|
||||||
|
// Declare this object as a ConsoleObject so that we can
|
||||||
|
// instantiate it into the world and network it
|
||||||
|
DECLARE_CONOBJECT(ShapeDatablockExample);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Object Editing
|
||||||
|
// Since there is always a server and a client object in Torque and we
|
||||||
|
// actually edit the server object we need to implement some basic
|
||||||
|
// networking functions
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Set up any fields that we want to be editable (like position)
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
// Handle when we are added to the scene and removed from the scene
|
||||||
|
bool onAdd() override;
|
||||||
|
void onRemove() override;
|
||||||
|
|
||||||
|
bool onNewDataBlock(GameBaseData* dptr, bool reload) override;
|
||||||
|
|
||||||
|
// Override this so that we can dirty the network flag when it is called
|
||||||
|
void setTransform(const MatrixF & mat) override;
|
||||||
|
|
||||||
|
// This function handles sending the relevant data from the server
|
||||||
|
// object to the client object
|
||||||
|
U32 packUpdate(NetConnection* conn, U32 mask, BitStream* stream) override;
|
||||||
|
// This function handles receiving relevant data from the server
|
||||||
|
// object and applying it to the client object
|
||||||
|
void unpackUpdate(NetConnection* conn, BitStream* stream) override;
|
||||||
|
|
||||||
|
// This is the function that allows this object to submit itself for rendering
|
||||||
|
void prepRenderImage(SceneRenderState* state) override;
|
||||||
|
|
||||||
|
void _onDatablockModified();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -239,7 +239,7 @@ ExplosionData::ExplosionData()
|
||||||
explosionScale.set(1.0f, 1.0f, 1.0f);
|
explosionScale.set(1.0f, 1.0f, 1.0f);
|
||||||
playSpeed = 1.0f;
|
playSpeed = 1.0f;
|
||||||
|
|
||||||
mExplosionShapeAsset.registerRefreshNotify(this);
|
explosionShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
|
|
||||||
explosionAnimation = -1;
|
explosionAnimation = -1;
|
||||||
|
|
||||||
|
|
@ -315,7 +315,7 @@ ExplosionData::ExplosionData(const ExplosionData& other, bool temp_clone) : Game
|
||||||
particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr
|
particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr
|
||||||
explosionScale = other.explosionScale;
|
explosionScale = other.explosionScale;
|
||||||
playSpeed = other.playSpeed;
|
playSpeed = other.playSpeed;
|
||||||
mExplosionShapeAsset = other.mExplosionShapeAsset;
|
explosionShapeAssetRef = other.explosionShapeAssetRef;
|
||||||
explosionAnimation = other.explosionAnimation; // -- from explosionShape sequence "ambient"
|
explosionAnimation = other.explosionAnimation; // -- from explosionShape sequence "ambient"
|
||||||
dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) );
|
dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) );
|
||||||
dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs
|
dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs
|
||||||
|
|
@ -360,8 +360,6 @@ ExplosionData::~ExplosionData()
|
||||||
if (!isTempClone())
|
if (!isTempClone())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mExplosionShapeAsset.unregisterRefreshNotify();
|
|
||||||
|
|
||||||
// particleEmitter, emitterList[*], debrisList[*], explosionList[*] will delete themselves
|
// particleEmitter, emitterList[*], debrisList[*], explosionList[*] will delete themselves
|
||||||
|
|
||||||
#ifdef TRACK_EXPLOSION_DATA_CLONES
|
#ifdef TRACK_EXPLOSION_DATA_CLONES
|
||||||
|
|
@ -395,8 +393,9 @@ void ExplosionData::initPersistFields()
|
||||||
{
|
{
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup("Shapes");
|
addGroup("Shapes");
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(ExplosionShape, ExplosionData, "@brief Optional shape asset to place at the center of the explosion.\n\n"
|
ADD_FIELD("explosionShapeAsset", TypeShapeAssetRef, Offset(explosionShapeAssetRef, ExplosionData))
|
||||||
"The <i>ambient</i> animation of this model will be played automatically at the start of the explosion.");
|
.doc("@brief Optional shape asset to place at the center of the explosion.\n\n"
|
||||||
|
"The <i>ambient</i> animation of this model will be played automatically at the start of the explosion.");
|
||||||
endGroup("Shapes");
|
endGroup("Shapes");
|
||||||
|
|
||||||
addGroup("Sounds");
|
addGroup("Sounds");
|
||||||
|
|
@ -673,7 +672,7 @@ void ExplosionData::packData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::packData(stream);
|
Parent::packData(stream);
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(ExplosionShape);
|
AssetDatabase.packDataAsset(stream, explosionShapeAssetRef.assetId);
|
||||||
|
|
||||||
//PACKDATA_SOUNDASSET(Sound);
|
//PACKDATA_SOUNDASSET(Sound);
|
||||||
PACKDATA_ASSET(Sound);
|
PACKDATA_ASSET(Sound);
|
||||||
|
|
@ -778,7 +777,7 @@ void ExplosionData::unpackData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::unpackData(stream);
|
Parent::unpackData(stream);
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(ExplosionShape);
|
explosionShapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
|
||||||
UNPACKDATA_ASSET(Sound);
|
UNPACKDATA_ASSET(Sound);
|
||||||
|
|
||||||
|
|
@ -913,23 +912,21 @@ bool ExplosionData::preload(bool server, String &errorStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getExplosionShape()) {
|
if (!explosionShapeAssetRef.isNull())
|
||||||
|
|
||||||
// Resolve animations
|
|
||||||
explosionAnimation = getExplosionShape()->findSequence("ambient");
|
|
||||||
|
|
||||||
// Preload textures with a dummy instance...
|
|
||||||
TSShapeInstance* pDummy = new TSShapeInstance(getExplosionShape(), !server);
|
|
||||||
delete pDummy;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (mExplosionShapeAsset.notNull())
|
|
||||||
{
|
{
|
||||||
errorStr = String::ToString("ExplosionData::preload: Couldn't load shape \"%s\"", _getExplosionShapeAssetId());
|
Resource<TSShape> shape = explosionShapeAssetRef.assetPtr->getShapeResource();
|
||||||
return false;
|
if (shape)
|
||||||
}
|
{
|
||||||
else {
|
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||||
explosionAnimation = -1;
|
delete pDummy;
|
||||||
|
if (!server && !explosionShapeAssetRef.assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorStr = String::ToString("ExplosionData(%s)::preload: Couldn't load shape \"%s\"", getName(), explosionShapeAssetRef.assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1417,8 +1414,12 @@ bool Explosion::explode()
|
||||||
launchDebris( mInitialNormal );
|
launchDebris( mInitialNormal );
|
||||||
spawnSubExplosions();
|
spawnSubExplosions();
|
||||||
|
|
||||||
if (bool(mDataBlock->getExplosionShape()) && mDataBlock->explosionAnimation != -1) {
|
Resource<TSShape> eShape;
|
||||||
mExplosionInstance = new TSShapeInstance(mDataBlock->getExplosionShape(), true);
|
if (mDataBlock->explosionShapeAssetRef.notNull())
|
||||||
|
eShape = mDataBlock->explosionShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
|
if (bool(eShape) && mDataBlock->explosionAnimation != -1) {
|
||||||
|
mExplosionInstance = new TSShapeInstance(eShape, true);
|
||||||
|
|
||||||
mExplosionThread = mExplosionInstance->addThread();
|
mExplosionThread = mExplosionInstance->addThread();
|
||||||
mExplosionInstance->setSequence(mExplosionThread, mDataBlock->explosionAnimation, 0);
|
mExplosionInstance->setSequence(mExplosionThread, mDataBlock->explosionAnimation, 0);
|
||||||
|
|
@ -1428,7 +1429,7 @@ bool Explosion::explode()
|
||||||
mEndingMS = U32(mExplosionInstance->getScaledDuration(mExplosionThread) * 1000.0f);
|
mEndingMS = U32(mExplosionInstance->getScaledDuration(mExplosionThread) * 1000.0f);
|
||||||
|
|
||||||
mObjScale.convolve(mDataBlock->explosionScale);
|
mObjScale.convolve(mDataBlock->explosionScale);
|
||||||
mObjBox = mDataBlock->getExplosionShape()->mBounds;
|
mObjBox = eShape->mBounds;
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ class ExplosionData : public GameBaseData, protected AssetPtrCallback {
|
||||||
Point3F explosionScale;
|
Point3F explosionScale;
|
||||||
F32 playSpeed;
|
F32 playSpeed;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(ExplosionData, ExplosionShape)
|
AssetRef<ShapeAsset> explosionShapeAssetRef;
|
||||||
|
|
||||||
S32 explosionAnimation;
|
S32 explosionAnimation;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -513,9 +513,6 @@ GroundCover::GroundCover()
|
||||||
mLayerAsset[i] = NULL;
|
mLayerAsset[i] = NULL;
|
||||||
mLayerFile[i] = StringTable->EmptyString();
|
mLayerFile[i] = StringTable->EmptyString();
|
||||||
|
|
||||||
mShapeAsset[i] = NULL;
|
|
||||||
mShapeFile[i] = StringTable->EmptyString();
|
|
||||||
|
|
||||||
mInvertLayer[i] = NULL;
|
mInvertLayer[i] = NULL;
|
||||||
|
|
||||||
mMinClumpCount[i] = 1;
|
mMinClumpCount[i] = 1;
|
||||||
|
|
@ -526,7 +523,7 @@ GroundCover::GroundCover()
|
||||||
mBillboardRects[i].point.set( 0.0f, 0.0f );
|
mBillboardRects[i].point.set( 0.0f, 0.0f );
|
||||||
mBillboardRects[i].extent.set( 1.0f, 1.0f );
|
mBillboardRects[i].extent.set( 1.0f, 1.0f );
|
||||||
|
|
||||||
mShapeAsset[i].registerRefreshNotify(this);
|
mShapeAssetRef[i].assetPtr.registerRefreshNotify(this);
|
||||||
|
|
||||||
mShapeInstances[i] = NULL;
|
mShapeInstances[i] = NULL;
|
||||||
|
|
||||||
|
|
@ -568,7 +565,10 @@ void GroundCover::initPersistFields()
|
||||||
|
|
||||||
addField( "billboardUVs", TypeRectUV, Offset( mBillboardRects, GroundCover ), MAX_COVERTYPES, "Subset material UV coordinates for this cover billboard." );
|
addField( "billboardUVs", TypeRectUV, Offset( mBillboardRects, GroundCover ), MAX_COVERTYPES, "Subset material UV coordinates for this cover billboard." );
|
||||||
|
|
||||||
INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(Shape, MAX_COVERTYPES, GroundCover, "The cover shape. [Optional]");
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(mShapeAssetRef, GroundCover))
|
||||||
|
.elements(MAX_COVERTYPES)
|
||||||
|
.doc("The cover shape. [Optional]")
|
||||||
|
.network(-1);
|
||||||
|
|
||||||
INITPERSISTFIELD_TERRAINMATERIALASSET_ARRAY(Layer, MAX_COVERTYPES, GroundCover, "Terrain material assetId to limit coverage to, or blank to not limit.");
|
INITPERSISTFIELD_TERRAINMATERIALASSET_ARRAY(Layer, MAX_COVERTYPES, GroundCover, "Terrain material assetId to limit coverage to, or blank to not limit.");
|
||||||
|
|
||||||
|
|
@ -773,10 +773,11 @@ U32 GroundCover::packUpdate( NetConnection *connection, U32 mask, BitStream *str
|
||||||
stream->write( mBillboardRects[i].point.y );
|
stream->write( mBillboardRects[i].point.y );
|
||||||
stream->write( mBillboardRects[i].extent.x );
|
stream->write( mBillboardRects[i].extent.x );
|
||||||
stream->write( mBillboardRects[i].extent.y );
|
stream->write( mBillboardRects[i].extent.y );
|
||||||
|
|
||||||
|
AssetDatabase.packUpdateAsset(connection, mask, stream, mShapeAssetRef[i].assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
PACK_ASSET_ARRAY_REFACTOR(connection, Layer, MAX_COVERTYPES)
|
PACK_ASSET_ARRAY_REFACTOR(connection, Layer, MAX_COVERTYPES)
|
||||||
PACK_ASSET_ARRAY_REFACTOR(connection, Shape, MAX_COVERTYPES)
|
|
||||||
|
|
||||||
stream->writeFlag( mDebugRenderCells );
|
stream->writeFlag( mDebugRenderCells );
|
||||||
stream->writeFlag( mDebugNoBillboards );
|
stream->writeFlag( mDebugNoBillboards );
|
||||||
|
|
@ -844,12 +845,12 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream )
|
||||||
stream->read( &mBillboardRects[i].point.y );
|
stream->read( &mBillboardRects[i].point.y );
|
||||||
stream->read( &mBillboardRects[i].extent.x );
|
stream->read( &mBillboardRects[i].extent.x );
|
||||||
stream->read( &mBillboardRects[i].extent.y );
|
stream->read( &mBillboardRects[i].extent.y );
|
||||||
|
|
||||||
|
mShapeAssetRef[i] = AssetDatabase.unpackUpdateAsset(connection, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNPACK_ASSET_ARRAY_REFACTOR(connection, Layer, MAX_COVERTYPES)
|
UNPACK_ASSET_ARRAY_REFACTOR(connection, Layer, MAX_COVERTYPES)
|
||||||
|
|
||||||
UNPACK_ASSET_ARRAY_REFACTOR(connection, Shape, MAX_COVERTYPES)
|
|
||||||
|
|
||||||
mDebugRenderCells = stream->readFlag();
|
mDebugRenderCells = stream->readFlag();
|
||||||
mDebugNoBillboards = stream->readFlag();
|
mDebugNoBillboards = stream->readFlag();
|
||||||
mDebugNoShapes = stream->readFlag();
|
mDebugNoShapes = stream->readFlag();
|
||||||
|
|
@ -895,17 +896,21 @@ void GroundCover::_initShapes()
|
||||||
|
|
||||||
for ( S32 i=0; i < MAX_COVERTYPES; i++ )
|
for ( S32 i=0; i < MAX_COVERTYPES; i++ )
|
||||||
{
|
{
|
||||||
if ( mShapeAsset[i].isNull() || getShape(i) == NULL)
|
if ( mShapeAssetRef[i].isNull())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( isClientObject() && !getShape(i)->preloadMaterialList(getShapeFile(i)) && NetConnection::filesWereDownloaded() )
|
Resource<TSShape> shape = mShapeAssetRef[i].assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( isClientObject() && !mShapeAssetRef[i].assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded() )
|
||||||
{
|
{
|
||||||
Con::warnf( "GroundCover::_initShapes() material preload failed for shape: %s", _getShapeAssetId(i));
|
Con::warnf( "GroundCover::_initShapes() material preload failed for shape: %s", mShapeAssetRef[i].assetId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the shape instance.
|
// Create the shape instance.
|
||||||
mShapeInstances[i] = new TSShapeInstance(getShape(i), isClientObject() );
|
mShapeInstances[i] = new TSShapeInstance(shape, isClientObject() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -345,7 +345,7 @@ protected:
|
||||||
RectF mBillboardRects[MAX_COVERTYPES];
|
RectF mBillboardRects[MAX_COVERTYPES];
|
||||||
|
|
||||||
/// The cover shape filenames.
|
/// The cover shape filenames.
|
||||||
DECLARE_SHAPEASSET_ARRAY_NET_REFACTOR(GroundCover, Shape, MAX_COVERTYPES, -1)
|
AssetRef<ShapeAsset> mShapeAssetRef[MAX_COVERTYPES];
|
||||||
|
|
||||||
/// The cover shape instances.
|
/// The cover shape instances.
|
||||||
TSShapeInstance* mShapeInstances[MAX_COVERTYPES];
|
TSShapeInstance* mShapeInstances[MAX_COVERTYPES];
|
||||||
|
|
|
||||||
|
|
@ -850,9 +850,6 @@ ConsoleSetType(TypeParticleList)
|
||||||
const char* values = argv[0];
|
const char* values = argv[0];
|
||||||
numUnits = StringUnit::getUnitCount(values, " ");
|
numUnits = StringUnit::getUnitCount(values, " ");
|
||||||
|
|
||||||
if (numUnits > 1)
|
|
||||||
bool dafgdf = true;
|
|
||||||
|
|
||||||
for (U32 i = 0; i < numUnits; i++)
|
for (U32 i = 0; i < numUnits; i++)
|
||||||
{
|
{
|
||||||
const char* value = StringUnit::getUnit(values, i, " ");
|
const char* value = StringUnit::getUnit(values, i, " ");
|
||||||
|
|
@ -877,7 +874,6 @@ ConsoleSetType(TypeParticleList)
|
||||||
Con::printf("TypeParticleList vec results: %s", testVec[x]);
|
Con::printf("TypeParticleList vec results: %s", testVec[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool test = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TORQUE_TOOLS
|
#ifdef TORQUE_TOOLS
|
||||||
|
|
|
||||||
|
|
@ -259,23 +259,30 @@ void GuiMaterialPreview::onMiddleMouseDragged(const GuiEvent &event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used to set the model we want to view in the control object.
|
// This is used to set the model we want to view in the control object.
|
||||||
void GuiMaterialPreview::setObjectModel(StringTableEntry modelName)
|
void GuiMaterialPreview::setObjectShape(StringTableEntry assetId)
|
||||||
{
|
{
|
||||||
deleteModel();
|
deleteShape();
|
||||||
|
|
||||||
_setModel(modelName);
|
mShapeAssetRef = assetId;
|
||||||
|
|
||||||
if (!getModel())
|
if (mShapeAssetRef.isNull())
|
||||||
{
|
{
|
||||||
Con::warnf("GuiMaterialPreview::setObjectModel - Failed to load model '%s'", modelName);
|
Con::warnf("GuiMaterialPreview::setObjectShape - Invalid assetId specified.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mModelInstance = new TSShapeInstance(getModel(), true);
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
{
|
||||||
|
Con::warnf("GuiMaterialPreview::setObjectModel - Failed to load shape '%s'", assetId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mModelInstance = new TSShapeInstance(shape, true);
|
||||||
mModelInstance->resetMaterialList();
|
mModelInstance->resetMaterialList();
|
||||||
mModelInstance->cloneMaterialList();
|
mModelInstance->cloneMaterialList();
|
||||||
|
|
||||||
AssertFatal(mModelInstance, avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", modelName));
|
AssertFatal(mModelInstance, avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", assetId));
|
||||||
|
|
||||||
// Initialize camera values:
|
// Initialize camera values:
|
||||||
mOrbitPos = mModelInstance->getShape()->center;
|
mOrbitPos = mModelInstance->getShape()->center;
|
||||||
|
|
@ -284,7 +291,7 @@ void GuiMaterialPreview::setObjectModel(StringTableEntry modelName)
|
||||||
lastRenderTime = Platform::getVirtualMilliseconds();
|
lastRenderTime = Platform::getVirtualMilliseconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiMaterialPreview::deleteModel()
|
void GuiMaterialPreview::deleteShape()
|
||||||
{
|
{
|
||||||
SAFE_DELETE(mModelInstance);
|
SAFE_DELETE(mModelInstance);
|
||||||
runThread = 0;
|
runThread = 0;
|
||||||
|
|
@ -499,17 +506,32 @@ ConsoleDocClass( GuiMaterialPreview,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Set the model.
|
// Set the model.
|
||||||
DefineEngineMethod(GuiMaterialPreview, setModel, void, ( const char* shapeName ),,
|
DefineEngineMethod(GuiMaterialPreview, setModel, void, ( const char* assetId ),,
|
||||||
"Sets the model to be displayed in this control\n\n"
|
"Sets the shape to be displayed in this control\n\n"
|
||||||
"@param shapeName Name of the model to display.\n")
|
"@param assetId Id of the shapeAsset to display.\n"
|
||||||
|
"@Deprecated\n\n")
|
||||||
{
|
{
|
||||||
object->setObjectModel(StringTable->insert(shapeName));
|
object->setObjectShape(StringTable->insert(assetId));
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(GuiMaterialPreview, setShape, void, (const char* assetId), ,
|
||||||
|
"Sets the shape to be displayed in this control\n\n"
|
||||||
|
"@param assetId Id of the shapeAsset to display.\n")
|
||||||
|
{
|
||||||
|
object->setObjectShape(StringTable->insert(assetId));
|
||||||
}
|
}
|
||||||
|
|
||||||
DefineEngineMethod(GuiMaterialPreview, deleteModel, void, (),,
|
DefineEngineMethod(GuiMaterialPreview, deleteModel, void, (),,
|
||||||
|
"Deletes the preview model.\n"
|
||||||
|
"@Deprecated\n\n")
|
||||||
|
{
|
||||||
|
object->deleteShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(GuiMaterialPreview, deleteShape, void, (), ,
|
||||||
"Deletes the preview model.\n")
|
"Deletes the preview model.\n")
|
||||||
{
|
{
|
||||||
object->deleteModel();
|
object->deleteShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set orbit distance around the model.
|
// Set orbit distance around the model.
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ protected:
|
||||||
|
|
||||||
MouseState mMouseState;
|
MouseState mMouseState;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(GuiMaterialPreview, Model)
|
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||||
DECLARE_SHAPEASSET_REFACTOR(GuiMaterialPreview, MountedModel)
|
AssetRef<ShapeAsset> mMountedShapeAssetRef;
|
||||||
|
|
||||||
TSShapeInstance* mModelInstance;
|
TSShapeInstance* mModelInstance;
|
||||||
TSShapeInstance* mMountedModelInstance;
|
TSShapeInstance* mMountedModelInstance;
|
||||||
|
|
@ -110,8 +110,8 @@ public:
|
||||||
// For changing the ambient light color.
|
// For changing the ambient light color.
|
||||||
void setAmbientLightColor( F32 r, F32 g, F32 b );
|
void setAmbientLightColor( F32 r, F32 g, F32 b );
|
||||||
|
|
||||||
void setObjectModel(const char * modelName);
|
void setObjectShape(const char * assetId);
|
||||||
void deleteModel();
|
void deleteShape();
|
||||||
void resetViewport();
|
void resetViewport();
|
||||||
void setOrbitDistance(F32 distance);
|
void setOrbitDistance(F32 distance);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,11 +134,16 @@ GuiObjectView::~GuiObjectView()
|
||||||
void GuiObjectView::initPersistFields()
|
void GuiObjectView::initPersistFields()
|
||||||
{
|
{
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup( "Model" );
|
addGroup( "Shape" );
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Model, GuiObjectView, "The source shape asset.");
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(mShapeAssetRef, GuiObjectView))
|
||||||
|
.doc("The source shape asset.");
|
||||||
|
ADD_FIELD("modelAsset", TypeShapeAssetRef, Offset(mShapeAssetRef, GuiObjectView))
|
||||||
|
.doc("The source shape asset.")
|
||||||
|
.withFlags(AbstractClassRep::FieldFlags::FIELD_HideInInspectors | AbstractClassRep::FieldFlags::FIELD_DontWriteToFile);
|
||||||
|
|
||||||
addField( "skin", TypeRealString, Offset( mSkinName, GuiObjectView ),
|
addField( "skin", TypeRealString, Offset( mSkinName, GuiObjectView ),
|
||||||
"The skin to use on the object model." );
|
"The skin to use on the object model." );
|
||||||
endGroup( "Model" );
|
endGroup( "Shape" );
|
||||||
|
|
||||||
addGroup( "Animation" );
|
addGroup( "Animation" );
|
||||||
|
|
||||||
|
|
@ -148,7 +153,11 @@ void GuiObjectView::initPersistFields()
|
||||||
endGroup( "Animation" );
|
endGroup( "Animation" );
|
||||||
|
|
||||||
addGroup( "Mounting" );
|
addGroup( "Mounting" );
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(MountedModel, GuiObjectView, "The mounted shape asset.");
|
ADD_FIELD("mountedShapeAsset", TypeShapeAssetRef, Offset(mMountedShapeAssetRef, GuiObjectView))
|
||||||
|
.doc("The mounted shape asset.");
|
||||||
|
ADD_FIELD("mountedModelAsset", TypeShapeAssetRef, Offset(mMountedShapeAssetRef, GuiObjectView))
|
||||||
|
.doc("The source shape asset.")
|
||||||
|
.withFlags(AbstractClassRep::FieldFlags::FIELD_HideInInspectors | AbstractClassRep::FieldFlags::FIELD_DontWriteToFile);
|
||||||
addField( "mountedSkin", TypeRealString, Offset( mMountSkinName, GuiObjectView ),
|
addField( "mountedSkin", TypeRealString, Offset( mMountSkinName, GuiObjectView ),
|
||||||
"Skin name used on mounted shape file." );
|
"Skin name used on mounted shape file." );
|
||||||
addField( "mountedNode", TypeRealString, Offset( mMountNodeName, GuiObjectView ),
|
addField( "mountedNode", TypeRealString, Offset( mMountNodeName, GuiObjectView ),
|
||||||
|
|
@ -329,27 +338,34 @@ void GuiObjectView::setObjectAnimation( const String& sequenceName )
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
bool GuiObjectView::setObjectModel( const String& modelName )
|
bool GuiObjectView::setObjectShape( const String& assetId )
|
||||||
{
|
{
|
||||||
mRunThread = 0;
|
mRunThread = 0;
|
||||||
|
|
||||||
// Load the shape if its not the one already set.
|
// Load the shape if its not the one already set.
|
||||||
if (modelName.c_str() != _getModelAssetId())
|
if (assetId.c_str() != mShapeAssetRef.assetId)
|
||||||
_setModel(modelName.c_str());
|
mShapeAssetRef = assetId.c_str();
|
||||||
else
|
else
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( !getModel())
|
if (mShapeAssetRef.isNull())
|
||||||
{
|
{
|
||||||
Con::warnf( "GuiObjectView::setObjectModel - Failed to load model '%s'", modelName.c_str() );
|
Con::warnf( "GuiObjectView::setObjectShape(%s) - Failed to load shape assetId '%s'", getName(), assetId.c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getModel()->preloadMaterialList(getModelFile())) return false;
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if( !shape)
|
||||||
|
{
|
||||||
|
Con::warnf( "GuiObjectView::setObjectShape(%s) - Failed to load shape '%s'", getName(), assetId.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mShapeAssetRef.assetPtr->preloadMaterialList()) return false;
|
||||||
|
|
||||||
// Instantiate it.
|
// Instantiate it.
|
||||||
|
|
||||||
mModelInstance = new TSShapeInstance(getModel(), true );
|
mModelInstance = new TSShapeInstance(shape, true );
|
||||||
mModelInstance->resetMaterialList();
|
mModelInstance->resetMaterialList();
|
||||||
mModelInstance->cloneMaterialList();
|
mModelInstance->cloneMaterialList();
|
||||||
|
|
||||||
|
|
@ -357,12 +373,12 @@ bool GuiObjectView::setObjectModel( const String& modelName )
|
||||||
mModelInstance->reSkin( mSkinName );
|
mModelInstance->reSkin( mSkinName );
|
||||||
|
|
||||||
TSMaterialList* pMatList = mModelInstance->getMaterialList();
|
TSMaterialList* pMatList = mModelInstance->getMaterialList();
|
||||||
pMatList->setTextureLookupPath(mModelAsset->getShapeFile());
|
pMatList->setTextureLookupPath(mShapeAssetRef.assetPtr->getShapeFile());
|
||||||
mModelInstance->initMaterialList();
|
mModelInstance->initMaterialList();
|
||||||
// Initialize camera values.
|
// Initialize camera values.
|
||||||
|
|
||||||
mOrbitPos = getModel()->center;
|
mOrbitPos = shape->center;
|
||||||
mMinOrbitDist = getModel()->mRadius;
|
mMinOrbitDist = shape->mRadius;
|
||||||
|
|
||||||
// Initialize animation.
|
// Initialize animation.
|
||||||
|
|
||||||
|
|
@ -384,23 +400,30 @@ void GuiObjectView::setSkin( const String& name )
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
bool GuiObjectView::setMountedObject( const String& modelName )
|
bool GuiObjectView::setMountedShape( const String& assetId )
|
||||||
{
|
{
|
||||||
// Load the model if it is not already the asset then set it..
|
// Load the model if it is not already the asset then set it..
|
||||||
if (modelName.c_str() != _getMountedModelAssetId())
|
if (assetId.c_str() != mMountedShapeAssetRef.assetId)
|
||||||
_setMountedModel(modelName.c_str());
|
mMountedShapeAssetRef = assetId.c_str();
|
||||||
else
|
else
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!getMountedModel())
|
if (mMountedShapeAssetRef.isNull())
|
||||||
{
|
{
|
||||||
Con::warnf("GuiObjectView::setMountedObject - Failed to load model '%s'", modelName.c_str());
|
Con::warnf("GuiObjectView::setMountedShape(%s) - Failed to load shape assetId '%s'", getName(), assetId.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getMountedModel()->preloadMaterialList(getMountedModelFile())) return false;
|
Resource<TSShape> shape = mMountedShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
{
|
||||||
|
Con::warnf("GuiObjectView::setMountedShape(%s) - Failed to load model '%s'", getName(), assetId.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
mMountedModelInstance = new TSShapeInstance(getMountedModel(), true);
|
if (!mMountedShapeAssetRef.assetPtr->preloadMaterialList()) return false;
|
||||||
|
|
||||||
|
mMountedModelInstance = new TSShapeInstance(shape, true);
|
||||||
mMountedModelInstance->resetMaterialList();
|
mMountedModelInstance->resetMaterialList();
|
||||||
mMountedModelInstance->cloneMaterialList();
|
mMountedModelInstance->cloneMaterialList();
|
||||||
|
|
||||||
|
|
@ -628,22 +651,27 @@ void GuiObjectView::setLightDirection( const Point3F& direction )
|
||||||
|
|
||||||
void GuiObjectView::_initAnimation()
|
void GuiObjectView::_initAnimation()
|
||||||
{
|
{
|
||||||
AssertFatal(getModel(), "GuiObjectView::_initAnimation - No model loaded!" );
|
AssertFatal(mModelInstance, "GuiObjectView::_initAnimation - No model loaded!" );
|
||||||
|
|
||||||
|
if (!mModelInstance)
|
||||||
|
return;
|
||||||
|
|
||||||
if( mAnimationSeqName.isEmpty() && mAnimationSeq == -1 )
|
if( mAnimationSeqName.isEmpty() && mAnimationSeq == -1 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
// Look up sequence by name.
|
// Look up sequence by name.
|
||||||
|
|
||||||
if( !mAnimationSeqName.isEmpty() )
|
if( !mAnimationSeqName.isEmpty() )
|
||||||
{
|
{
|
||||||
mAnimationSeq = getModel()->findSequence( mAnimationSeqName );
|
mAnimationSeq = shape->findSequence( mAnimationSeqName );
|
||||||
|
|
||||||
if( mAnimationSeq == -1 )
|
if( mAnimationSeq == -1 )
|
||||||
{
|
{
|
||||||
Con::errorf( "GuiObjectView::_initAnimation - Cannot find animation sequence '%s' on '%s'",
|
Con::errorf( "GuiObjectView::_initAnimation - Cannot find animation sequence '%s' on '%s'",
|
||||||
mAnimationSeqName.c_str(),
|
mAnimationSeqName.c_str(),
|
||||||
_getModelAssetId()
|
mShapeAssetRef.assetId
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -654,11 +682,11 @@ void GuiObjectView::_initAnimation()
|
||||||
|
|
||||||
if( mAnimationSeq != -1 )
|
if( mAnimationSeq != -1 )
|
||||||
{
|
{
|
||||||
if( mAnimationSeq >= getModel()->sequences.size() )
|
if( mAnimationSeq >= shape->sequences.size() )
|
||||||
{
|
{
|
||||||
Con::errorf( "GuiObjectView::_initAnimation - Sequence '%i' out of range for model '%s'",
|
Con::errorf( "GuiObjectView::_initAnimation - Sequence '%i' out of range for model '%s'",
|
||||||
mAnimationSeq,
|
mAnimationSeq,
|
||||||
_getModelAssetId()
|
mShapeAssetRef.assetId
|
||||||
);
|
);
|
||||||
|
|
||||||
mAnimationSeq = -1;
|
mAnimationSeq = -1;
|
||||||
|
|
@ -683,18 +711,20 @@ void GuiObjectView::_initMount()
|
||||||
if( !mModelInstance)
|
if( !mModelInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
mMountTransform.identity();
|
mMountTransform.identity();
|
||||||
|
|
||||||
// Look up the node to which to mount to.
|
// Look up the node to which to mount to.
|
||||||
|
|
||||||
if( !mMountNodeName.isEmpty() )
|
if( !mMountNodeName.isEmpty() )
|
||||||
{
|
{
|
||||||
mMountNode = getModel()->findNode( mMountNodeName );
|
mMountNode = shape->findNode( mMountNodeName );
|
||||||
if( mMountNode == -1 )
|
if( mMountNode == -1 )
|
||||||
{
|
{
|
||||||
Con::errorf( "GuiObjectView::_initMount - No node '%s' on '%s'",
|
Con::errorf( "GuiObjectView::_initMount - No node '%s' on '%s'",
|
||||||
mMountNodeName.c_str(),
|
mMountNodeName.c_str(),
|
||||||
_getModelAssetId()
|
mShapeAssetRef.assetId
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -703,24 +733,28 @@ void GuiObjectView::_initMount()
|
||||||
|
|
||||||
// Make sure mount node is valid.
|
// Make sure mount node is valid.
|
||||||
|
|
||||||
if( mMountNode != -1 && mMountNode >= getModel()->nodes.size() )
|
if( mMountNode != -1 && mMountNode >= shape->nodes.size() )
|
||||||
{
|
{
|
||||||
Con::errorf( "GuiObjectView::_initMount - Mount node index '%i' out of range for '%s'",
|
Con::errorf( "GuiObjectView::_initMount - Mount node index '%i' out of range for '%s'",
|
||||||
mMountNode,
|
mMountNode,
|
||||||
_getModelAssetId()
|
mShapeAssetRef.assetId
|
||||||
);
|
);
|
||||||
|
|
||||||
mMountNode = -1;
|
mMountNode = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resource<TSShape> mountShape;
|
||||||
|
if (mMountedShapeAssetRef.notNull())
|
||||||
|
mountShape = mMountedShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
// Look up node on the mounted model from
|
// Look up node on the mounted model from
|
||||||
// which to mount to the primary model's node.
|
// which to mount to the primary model's node.
|
||||||
if (!getMountedModel()) return;
|
if (!mountShape) return;
|
||||||
S32 mountPoint = getMountedModel()->findNode( "mountPoint" );
|
S32 mountPoint = mountShape->findNode( "mountPoint" );
|
||||||
if( mountPoint != -1 )
|
if( mountPoint != -1 )
|
||||||
{
|
{
|
||||||
getMountedModel()->getNodeWorldTransform(mountPoint, &mMountTransform),
|
mountShape->getNodeWorldTransform(mountPoint, &mMountTransform),
|
||||||
mMountTransform.inverse();
|
mMountTransform.inverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -738,26 +772,28 @@ DefineEngineMethod( GuiObjectView, getModel, const char*, (),,
|
||||||
"// Request the displayed model name from the GuiObjectView object.\n"
|
"// Request the displayed model name from the GuiObjectView object.\n"
|
||||||
"%modelName = %thisGuiObjectView.getModel();\n"
|
"%modelName = %thisGuiObjectView.getModel();\n"
|
||||||
"@endtsexample\n\n"
|
"@endtsexample\n\n"
|
||||||
"@return Name of the displayed model.\n\n"
|
"@return Id of the displayed shape.\n\n"
|
||||||
"@see GuiControl")
|
"@see GuiControl\n"
|
||||||
|
"@Deprecated\n\n")
|
||||||
{
|
{
|
||||||
return Con::getReturnBuffer( object->_getModelAssetId() );
|
return Con::getReturnBuffer( object->getObjectShapeId() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
DefineEngineMethod( GuiObjectView, setModel, bool, (const char* shapeName),,
|
DefineEngineMethod( GuiObjectView, setModel, bool, (const char* assetId),,
|
||||||
"@brief Sets the model to be displayed in this control.\n\n"
|
"@brief Sets the model to be displayed in this control.\n\n"
|
||||||
"@param shapeName Name of the model to display.\n"
|
"@param shapassetIdeName Name of the shapeAsset to display.\n"
|
||||||
"@tsexample\n"
|
"@tsexample\n"
|
||||||
"// Define the model we want to display\n"
|
"// Define the shapeAsset we want to display\n"
|
||||||
"%shapeName = \"gideon.dts\";\n\n"
|
"%assetId = \"MyModule:MyShapeAsset\";\n\n"
|
||||||
"// Tell the GuiObjectView object to display the defined model\n"
|
"// Tell the GuiObjectView object to display the defined model\n"
|
||||||
"%thisGuiObjectView.setModel(%shapeName);\n"
|
"%thisGuiObjectView.setModel(%assetId);\n"
|
||||||
"@endtsexample\n\n"
|
"@endtsexample\n\n"
|
||||||
"@see GuiControl")
|
"@see GuiControl\n"
|
||||||
|
"@Deprecated\n\n")
|
||||||
{
|
{
|
||||||
return object->setObjectModel( shapeName );
|
return object->setObjectShape(assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -769,25 +805,86 @@ DefineEngineMethod( GuiObjectView, getMountedModel, const char*, (),,
|
||||||
"%mountedModelName = %thisGuiObjectView.getMountedModel();\n"
|
"%mountedModelName = %thisGuiObjectView.getMountedModel();\n"
|
||||||
"@endtsexample\n\n"
|
"@endtsexample\n\n"
|
||||||
"@return Name of the mounted model.\n\n"
|
"@return Name of the mounted model.\n\n"
|
||||||
"@see GuiControl")
|
"@see GuiControl\n"
|
||||||
|
"@Deprecated\n\n")
|
||||||
{
|
{
|
||||||
return Con::getReturnBuffer( object->_getMountedModelAssetId() );
|
return Con::getReturnBuffer( object->getMountedShapeId() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
DefineEngineMethod( GuiObjectView, setMountedModel, void, (const char* shapeName),,
|
DefineEngineMethod( GuiObjectView, setMountedModel, void, (const char* assetId),,
|
||||||
"@brief Sets the model to be mounted on the primary model.\n\n"
|
"@brief Sets the model to be mounted on the primary model.\n\n"
|
||||||
"@param shapeName Name of the model to mount.\n"
|
"@param assetId Name of the shapeAsset to mount.\n"
|
||||||
"@tsexample\n"
|
"@tsexample\n"
|
||||||
"// Define the model name to mount\n"
|
"// Define the model name to mount\n"
|
||||||
"%modelToMount = \"GideonGlasses.dts\";\n\n"
|
"%shapeToMount = \"MyModule:MyMountedShapeAsset\";\n\n"
|
||||||
"// Inform the GuiObjectView object to mount the defined model to the existing model in the control\n"
|
"// Inform the GuiObjectView object to mount the defined model to the existing model in the control\n"
|
||||||
"%thisGuiObjectView.setMountedModel(%modelToMount);\n"
|
"%thisGuiObjectView.setMountedModel(%shapeToMount);\n"
|
||||||
|
"@endtsexample\n\n"
|
||||||
|
"@see GuiControl\n"
|
||||||
|
"@Deprecated\n\n")
|
||||||
|
{
|
||||||
|
object->setMountedShape(assetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
DefineEngineMethod(GuiObjectView, getShape, const char*, (), ,
|
||||||
|
"@brief Return the model displayed in this view.\n\n"
|
||||||
|
"@tsexample\n"
|
||||||
|
"// Request the displayed model name from the GuiObjectView object.\n"
|
||||||
|
"%modelName = %thisGuiObjectView.getModel();\n"
|
||||||
|
"@endtsexample\n\n"
|
||||||
|
"@return Id of the displayed shape.\n\n"
|
||||||
|
"@see GuiControl")
|
||||||
|
{
|
||||||
|
return Con::getReturnBuffer(object->getObjectShapeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
DefineEngineMethod(GuiObjectView, setShape, bool, (const char* assetId), ,
|
||||||
|
"@brief Sets the shape to be displayed in this control.\n\n"
|
||||||
|
"@param shapassetIdeName Name of the shapeAsset to display.\n"
|
||||||
|
"@tsexample\n"
|
||||||
|
"// Define the shapeAsset we want to display\n"
|
||||||
|
"%assetId = \"MyModule:MyShapeAsset\";\n\n"
|
||||||
|
"// Tell the GuiObjectView object to display the defined model\n"
|
||||||
|
"%thisGuiObjectView.setshape(%assetId);\n"
|
||||||
"@endtsexample\n\n"
|
"@endtsexample\n\n"
|
||||||
"@see GuiControl")
|
"@see GuiControl")
|
||||||
{
|
{
|
||||||
object->setObjectModel(shapeName);
|
return object->setObjectShape(assetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
DefineEngineMethod(GuiObjectView, getMountedShape, const char*, (), ,
|
||||||
|
"@brief Return the id of the mounted shape.\n\n"
|
||||||
|
"@tsexample\n"
|
||||||
|
"// Request the id of the mounted shape from the GuiObjectView object\n"
|
||||||
|
"%mountedShapeId = %thisGuiObjectView.getMounteShape();\n"
|
||||||
|
"@endtsexample\n\n"
|
||||||
|
"@return Name of the mounted shape.\n\n"
|
||||||
|
"@see GuiControl")
|
||||||
|
{
|
||||||
|
return Con::getReturnBuffer(object->getMountedShapeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
DefineEngineMethod(GuiObjectView, setMountedShape, void, (const char* assetId), ,
|
||||||
|
"@brief Sets the shape to be mounted on the primary shape.\n\n"
|
||||||
|
"@param assetId Name of the shapeAsset to mount.\n"
|
||||||
|
"@tsexample\n"
|
||||||
|
"// Define the shapeAsset name to mount\n"
|
||||||
|
"%shapeToMount = \"MyModule:MyMountedShapeAsset\";\n\n"
|
||||||
|
"// Inform the GuiObjectView object to mount the defined shapeAsset to the existing shape in the control\n"
|
||||||
|
"%thisGuiObjectView.setMountedShape(%shapeToMount);\n"
|
||||||
|
"@endtsexample\n\n"
|
||||||
|
"@see GuiControl")
|
||||||
|
{
|
||||||
|
object->setMountedShape(assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -873,20 +970,20 @@ DefineEngineMethod( GuiObjectView, setSeq, void, (const char* indexOrName),,
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
DefineEngineMethod( GuiObjectView, setMount, void, ( const char* shapeName, const char* mountNodeIndexOrName),,
|
DefineEngineMethod( GuiObjectView, setMount, void, ( const char* assetId, const char* mountNodeIndexOrName),,
|
||||||
"@brief Mounts the given model to the specified mount point of the primary model displayed in this control.\n\n"
|
"@brief Mounts the given model to the specified mount point of the primary model displayed in this control.\n\n"
|
||||||
"Detailed description\n\n"
|
"Detailed description\n\n"
|
||||||
"@param shapeName Name of the model to mount.\n"
|
"@param assetId Name of the shapeAsset to mount.\n"
|
||||||
"@param mountNodeIndexOrName Index or name of the mount point to be mounted to. If index, corresponds to \"mountN\" in your shape where N is the number passed here.\n"
|
"@param mountNodeIndexOrName Index or name of the mount point to be mounted to. If index, corresponds to \"mountN\" in your shape where N is the number passed here.\n"
|
||||||
"@tsexample\n"
|
"@tsexample\n"
|
||||||
"// Set the shapeName to mount\n"
|
"// Set the shapeName to mount\n"
|
||||||
"%shapeName = \"GideonGlasses.dts\"\n\n"
|
"%assetId = \"MyModule:MyMountedShapeAsset\"\n\n"
|
||||||
"// Set the mount node of the primary model in the control to mount the new shape at\n"
|
"// Set the mount node of the primary model in the control to mount the new shape at\n"
|
||||||
"%mountNodeIndexOrName = \"3\";\n"
|
"%mountNodeIndexOrName = \"3\";\n"
|
||||||
"//OR:\n"
|
"//OR:\n"
|
||||||
"%mountNodeIndexOrName = \"Face\";\n\n"
|
"%mountNodeIndexOrName = \"Face\";\n\n"
|
||||||
"// Inform the GuiObjectView object to mount the shape at the specified node.\n"
|
"// Inform the GuiObjectView object to mount the shape at the specified node.\n"
|
||||||
"%thisGuiObjectView.setMount(%shapeName,%mountNodeIndexOrName);\n"
|
"%thisGuiObjectView.setMount(%assetId,%mountNodeIndexOrName);\n"
|
||||||
"@endtsexample\n\n"
|
"@endtsexample\n\n"
|
||||||
"@see GuiControl")
|
"@see GuiControl")
|
||||||
{
|
{
|
||||||
|
|
@ -895,7 +992,7 @@ DefineEngineMethod( GuiObjectView, setMount, void, ( const char* shapeName, cons
|
||||||
else
|
else
|
||||||
object->setMountNode( mountNodeIndexOrName );
|
object->setMountNode( mountNodeIndexOrName );
|
||||||
|
|
||||||
object->setMountedObject( shapeName );
|
object->setMountedShape(assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,12 @@ class GuiObjectView : public GuiTSCtrl, protected AssetPtrCallback
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/// @name Model
|
/// @name Shape
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///Model loaded for display.
|
///Shape loaded for display.
|
||||||
DECLARE_SHAPEASSET_REFACTOR(GuiObjectView, Model)
|
///
|
||||||
|
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||||
|
|
||||||
TSShapeInstance* mModelInstance;
|
TSShapeInstance* mModelInstance;
|
||||||
/// Name of skin to use on model.
|
/// Name of skin to use on model.
|
||||||
|
|
@ -102,7 +103,7 @@ class GuiObjectView : public GuiTSCtrl, protected AssetPtrCallback
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///Model to mount to the primary model.
|
///Model to mount to the primary model.
|
||||||
DECLARE_SHAPEASSET_REFACTOR(GuiObjectView, MountedModel)
|
AssetRef<ShapeAsset> mMountedShapeAssetRef;
|
||||||
TSShapeInstance* mMountedModelInstance;
|
TSShapeInstance* mMountedModelInstance;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
@ -176,8 +177,11 @@ class GuiObjectView : public GuiTSCtrl, protected AssetPtrCallback
|
||||||
/// Set the skin to use on the primary model.
|
/// Set the skin to use on the primary model.
|
||||||
void setSkin( const String& name );
|
void setSkin( const String& name );
|
||||||
|
|
||||||
/// Set the model to show in this view.
|
/// Set the shape to show in this view.
|
||||||
bool setObjectModel( const String& modelName );
|
bool setObjectShape( const String& assetId );
|
||||||
|
|
||||||
|
/// Get the shape currently shown in this view.
|
||||||
|
StringTableEntry getObjectShapeId() const { return mShapeAssetRef.assetId; }
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
@ -210,7 +214,8 @@ class GuiObjectView : public GuiTSCtrl, protected AssetPtrCallback
|
||||||
void setMountNode( const String& nodeName );
|
void setMountNode( const String& nodeName );
|
||||||
|
|
||||||
///
|
///
|
||||||
bool setMountedObject( const String& modelName );
|
bool setMountedShape( const String& assetId );
|
||||||
|
StringTableEntry getMountedShapeId() const { return mMountedShapeAssetRef.assetId; }
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
@ -274,11 +279,11 @@ class GuiObjectView : public GuiTSCtrl, protected AssetPtrCallback
|
||||||
protected:
|
protected:
|
||||||
void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override
|
void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override
|
||||||
{
|
{
|
||||||
if (getModel())
|
if (mShapeAssetRef.notNull())
|
||||||
setObjectModel(_getModelAssetId());
|
setObjectShape(mShapeAssetRef.assetId);
|
||||||
|
|
||||||
if (getMountedModel())
|
if (mMountedShapeAssetRef.notNull())
|
||||||
setMountedObject(_getMountedModelAssetId());
|
setMountedShape(mMountedShapeAssetRef.assetId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -657,11 +657,18 @@ void Item::setTransform(const MatrixF& mat)
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Item::updateWorkingCollisionSet(const U32 mask, const F32 dt)
|
void Item::updateWorkingCollisionSet(const U32 mask, const F32 dt)
|
||||||
{
|
{
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return;
|
||||||
|
|
||||||
// It is assumed that we will never accelerate more than 10 m/s for gravity...
|
// It is assumed that we will never accelerate more than 10 m/s for gravity...
|
||||||
//
|
//
|
||||||
Point3F scaledVelocity = mVelocity * dt * TickSec;
|
Point3F scaledVelocity = mVelocity * dt * TickSec;
|
||||||
F32 len = scaledVelocity.len();
|
F32 len = scaledVelocity.len();
|
||||||
F32 newLen = len + (mDataBlock->getShape()->mRadius * dt * TickSec);
|
F32 newLen = len + (shape->mRadius * dt * TickSec);
|
||||||
|
|
||||||
// Check to see if it is actually necessary to construct the new working list,
|
// Check to see if it is actually necessary to construct the new working list,
|
||||||
// or if we can use the cached version from the last query. We use the x
|
// or if we can use the cached version from the last query. We use the x
|
||||||
|
|
|
||||||
|
|
@ -473,14 +473,23 @@ void SpawnSphere::unpackUpdate(NetConnection * con, BitStream * stream)
|
||||||
{
|
{
|
||||||
delete mShapeInstance;
|
delete mShapeInstance;
|
||||||
ShapeBaseData *spawnedDatablock = dynamic_cast<ShapeBaseData *>(Sim::findObject(mSpawnDataBlock.c_str()));
|
ShapeBaseData *spawnedDatablock = dynamic_cast<ShapeBaseData *>(Sim::findObject(mSpawnDataBlock.c_str()));
|
||||||
if (spawnedDatablock && spawnedDatablock->getShape())
|
if (spawnedDatablock)
|
||||||
{
|
{
|
||||||
mShapeInstance = new TSShapeInstance(spawnedDatablock->getShape());
|
if (spawnedDatablock->shapeAssetRef.notNull())
|
||||||
|
{
|
||||||
|
Resource<TSShape> shape = spawnedDatablock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (shape)
|
||||||
|
mShapeInstance = new TSShapeInstance(shape);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mDataBlock)
|
else if (mDataBlock)
|
||||||
{
|
{
|
||||||
if (mDataBlock->getShape())
|
if (mDataBlock->shapeAssetRef.notNull())
|
||||||
mShapeInstance = new TSShapeInstance(mDataBlock->getShape());
|
{
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (shape)
|
||||||
|
mShapeInstance = new TSShapeInstance(shape);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stream->read(&mSpawnName);
|
stream->read(&mSpawnName);
|
||||||
|
|
|
||||||
|
|
@ -74,12 +74,11 @@ PhysicsDebrisData::PhysicsDebrisData()
|
||||||
lifetime = 5.0f;
|
lifetime = 5.0f;
|
||||||
lifetimeVariance = 0.0f;
|
lifetimeVariance = 0.0f;
|
||||||
|
|
||||||
mShapeAsset.registerRefreshNotify(this);
|
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsDebrisData::~PhysicsDebrisData()
|
PhysicsDebrisData::~PhysicsDebrisData()
|
||||||
{
|
{
|
||||||
mShapeAsset.unregisterRefreshNotify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsDebrisData::onAdd()
|
bool PhysicsDebrisData::onAdd()
|
||||||
|
|
@ -97,17 +96,21 @@ bool PhysicsDebrisData::preload( bool server, String &errorStr )
|
||||||
|
|
||||||
if ( server ) return true;
|
if ( server ) return true;
|
||||||
|
|
||||||
if ( getShape() )
|
if (!shapeAssetRef.isNull())
|
||||||
{
|
{
|
||||||
// Create a dummy shape to force the generation of shaders and materials
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
// during the level load and not during gameplay.
|
if (shape)
|
||||||
TSShapeInstance *pDummy = new TSShapeInstance( getShape(), !server);
|
{
|
||||||
delete pDummy;
|
// Create a dummy shape to force the generation of shaders and materials
|
||||||
}
|
// during the level load and not during gameplay.
|
||||||
else
|
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||||
{
|
delete pDummy;
|
||||||
errorStr = String::ToString("PhysicsDebrisData::load: Couldn't load shape asset \"%s\"", _getShapeAssetId());
|
}
|
||||||
return false;
|
else
|
||||||
|
{
|
||||||
|
errorStr = String::ToString("PhysicsDebrisData(%s)::preload: Couldn't load shape asset\"%s\"", getName(), shapeAssetRef.assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -118,8 +121,9 @@ void PhysicsDebrisData::initPersistFields()
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup( "Shapes" );
|
addGroup( "Shapes" );
|
||||||
|
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, PhysicsDebrisData, "@brief Shape to use with this debris.\n\n"
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, PhysicsDebrisData))
|
||||||
"Compatable with Live-Asset Reloading.");
|
.doc("@brief Shape to use with this debris.\n\n"
|
||||||
|
"Compatable with Live-Asset Reloading.");
|
||||||
|
|
||||||
endGroup( "Shapes" );
|
endGroup( "Shapes" );
|
||||||
|
|
||||||
|
|
@ -218,7 +222,7 @@ void PhysicsDebrisData::packData(BitStream* stream)
|
||||||
stream->write( waterDampingScale );
|
stream->write( waterDampingScale );
|
||||||
stream->write( buoyancyDensity );
|
stream->write( buoyancyDensity );
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(Shape);
|
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsDebrisData::unpackData(BitStream* stream)
|
void PhysicsDebrisData::unpackData(BitStream* stream)
|
||||||
|
|
@ -239,7 +243,7 @@ void PhysicsDebrisData::unpackData(BitStream* stream)
|
||||||
stream->read( &waterDampingScale );
|
stream->read( &waterDampingScale );
|
||||||
stream->read( &buoyancyDensity );
|
stream->read( &buoyancyDensity );
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
DefineEngineMethod( PhysicsDebrisData, preload, void, (), ,
|
DefineEngineMethod( PhysicsDebrisData, preload, void, (), ,
|
||||||
|
|
@ -250,7 +254,7 @@ DefineEngineMethod( PhysicsDebrisData, preload, void, (), ,
|
||||||
{
|
{
|
||||||
String errorStr;
|
String errorStr;
|
||||||
|
|
||||||
object->_setShape(object->_getShapeAssetId());
|
object->shapeAssetRef = object->shapeAssetRef.assetId;
|
||||||
|
|
||||||
if( !object->preload( false, errorStr ) )
|
if( !object->preload( false, errorStr ) )
|
||||||
Con::errorf( "PhsysicsDebrisData::preload - error: %s", errorStr.c_str() );
|
Con::errorf( "PhsysicsDebrisData::preload - error: %s", errorStr.c_str() );
|
||||||
|
|
@ -356,6 +360,19 @@ bool PhysicsDebris::onAdd()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !mDataBlock->shapeAssetRef.notNull() )
|
||||||
|
{
|
||||||
|
Con::errorf("PhysicsDebris::onAdd - Fail - No shape asset \"%s\"", mDataBlock->shapeAssetRef.assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
{
|
||||||
|
Con::errorf("PhysicsDebris::onAdd - Fail - Unable to load shape asset \"%s\"", mDataBlock->shapeAssetRef.assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If it has a fixed lifetime then calculate it.
|
// If it has a fixed lifetime then calculate it.
|
||||||
if ( mDataBlock->lifetime > 0.0f )
|
if ( mDataBlock->lifetime > 0.0f )
|
||||||
{
|
{
|
||||||
|
|
@ -364,7 +381,7 @@ bool PhysicsDebris::onAdd()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup our bounding box
|
// Setup our bounding box
|
||||||
mObjBox = mDataBlock->getShape()->mBounds;
|
mObjBox = shape->mBounds;
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
|
|
||||||
// Add it to the client scene.
|
// Add it to the client scene.
|
||||||
|
|
@ -627,7 +644,7 @@ void PhysicsDebris::_createFragments()
|
||||||
if ( !mWorld )
|
if ( !mWorld )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TSShape *shape = mDataBlock->getShape();
|
TSShape *shape = mDataBlock->shapeAssetRef.assetPtr->getShape();
|
||||||
|
|
||||||
mShapeInstance = new TSShapeInstance( shape, true );
|
mShapeInstance = new TSShapeInstance( shape, true );
|
||||||
mShapeInstance->animate();
|
mShapeInstance->animate();
|
||||||
|
|
@ -701,7 +718,7 @@ void PhysicsDebris::_findNodes( U32 colNode, Vector<U32> &nodeIds )
|
||||||
// 1. Visible mesh nodes are siblings of the collision node under a common parent dummy node
|
// 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
|
// 2. Collision node is a child of its visible mesh node
|
||||||
|
|
||||||
TSShape *shape = mDataBlock->getShape();
|
TSShape *shape = mDataBlock->shapeAssetRef.assetPtr->getShape();
|
||||||
S32 itr = shape->nodes[colNode].parentIndex;
|
S32 itr = shape->nodes[colNode].parentIndex;
|
||||||
itr = shape->nodes[itr].firstChild;
|
itr = shape->nodes[itr].firstChild;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ public:
|
||||||
/// Is rendererd during shadow passes.
|
/// Is rendererd during shadow passes.
|
||||||
bool castShadows;
|
bool castShadows;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(PhysicsDebrisData, Shape)
|
AssetRef<ShapeAsset> shapeAssetRef;
|
||||||
|
|
||||||
PhysicsDebrisData();
|
PhysicsDebrisData();
|
||||||
virtual ~PhysicsDebrisData();
|
virtual ~PhysicsDebrisData();
|
||||||
|
|
|
||||||
|
|
@ -78,12 +78,11 @@ PhysicsShapeData::PhysicsShapeData()
|
||||||
buoyancyDensity( 0.0f ),
|
buoyancyDensity( 0.0f ),
|
||||||
simType( SimType_ClientServer )
|
simType( SimType_ClientServer )
|
||||||
{
|
{
|
||||||
mShapeAsset.registerRefreshNotify(this);
|
shapeAsset.assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsShapeData::~PhysicsShapeData()
|
PhysicsShapeData::~PhysicsShapeData()
|
||||||
{
|
{
|
||||||
mShapeAsset.unregisterRefreshNotify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsShapeData::initPersistFields()
|
void PhysicsShapeData::initPersistFields()
|
||||||
|
|
@ -91,8 +90,9 @@ void PhysicsShapeData::initPersistFields()
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup("Shapes");
|
addGroup("Shapes");
|
||||||
|
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, PhysicsShapeData, "@brief Shape asset to be used with this physics object.\n\n"
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAsset, PhysicsShapeData))
|
||||||
"Compatable with Live-Asset Reloading. ")
|
. doc("@brief Shape asset to be used with this physics object.\n\n"
|
||||||
|
"Compatable with Live-Asset Reloading. ");
|
||||||
|
|
||||||
addField( "debris", TYPEID< SimObjectRef<PhysicsDebrisData> >(), Offset( debris, PhysicsShapeData ),
|
addField( "debris", TYPEID< SimObjectRef<PhysicsDebrisData> >(), Offset( debris, PhysicsShapeData ),
|
||||||
"@brief Name of a PhysicsDebrisData to spawn when this shape is destroyed (optional)." );
|
"@brief Name of a PhysicsDebrisData to spawn when this shape is destroyed (optional)." );
|
||||||
|
|
@ -181,7 +181,7 @@ void PhysicsShapeData::packData( BitStream *stream )
|
||||||
{
|
{
|
||||||
Parent::packData( stream );
|
Parent::packData( stream );
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(Shape);
|
AssetDatabase.packDataAsset(stream, shapeAsset.assetId);
|
||||||
|
|
||||||
stream->write( mass );
|
stream->write( mass );
|
||||||
stream->write( dynamicFriction );
|
stream->write( dynamicFriction );
|
||||||
|
|
@ -205,7 +205,7 @@ void PhysicsShapeData::unpackData( BitStream *stream )
|
||||||
{
|
{
|
||||||
Parent::unpackData(stream);
|
Parent::unpackData(stream);
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
shapeAsset = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
|
||||||
stream->read( &mass );
|
stream->read( &mass );
|
||||||
stream->read( &dynamicFriction );
|
stream->read( &dynamicFriction );
|
||||||
|
|
@ -242,27 +242,28 @@ void PhysicsShapeData::onRemove()
|
||||||
|
|
||||||
void PhysicsShapeData::_onResourceChanged( const Torque::Path &path )
|
void PhysicsShapeData::_onResourceChanged( const Torque::Path &path )
|
||||||
{
|
{
|
||||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
|
U32 assetStatus = ShapeAsset::getAssetErrCode(shapeAsset.assetPtr);
|
||||||
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( path != Path(mShapeAsset->getShapeFile()) )
|
|
||||||
|
if ( path != Path(shapeAsset.assetPtr->getShapeFile()) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_setShape(_getShapeAssetId());
|
shapeAsset = shapeAsset.assetId;
|
||||||
|
|
||||||
// Reload the changed shape.
|
// Reload the changed shape.
|
||||||
PhysicsCollisionRef reloadcolShape;
|
PhysicsCollisionRef reloadcolShape;
|
||||||
|
Resource<TSShape> shape = shapeAsset.assetPtr->getShapeResource();
|
||||||
if ( !getShape())
|
if ( !shape)
|
||||||
{
|
{
|
||||||
Con::warnf( ConsoleLogEntry::General, "PhysicsShapeData::_onResourceChanged: Could not reload %s.", path.getFileName().c_str() );
|
Con::warnf( ConsoleLogEntry::General, "PhysicsShapeData::_onResourceChanged: Could not reload %s.", path.getFileName().c_str() );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload the collision shape.
|
// Reload the collision shape.
|
||||||
reloadcolShape = getShape()->buildColShape( false, Point3F::One );
|
reloadcolShape = shape->buildColShape( false, Point3F::One );
|
||||||
|
|
||||||
if ( bool(reloadcolShape))
|
if ( bool(reloadcolShape))
|
||||||
colShape = reloadcolShape;
|
colShape = reloadcolShape;
|
||||||
|
|
@ -283,34 +284,41 @@ bool PhysicsShapeData::preload( bool server, String &errorBuffer )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shapeError = false;
|
if (shapeAsset.isNull())
|
||||||
|
|
||||||
if (getShape())
|
|
||||||
{
|
{
|
||||||
if (!server && !getShape()->preloadMaterialList(getShapeFile()) && NetConnection::filesWereDownloaded())
|
errorBuffer = String::ToString("PhysicsShapeData::preload(%s) - No shape asset!", getName());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shapeError = false;
|
||||||
|
Resource<TSShape> shape = shapeAsset.assetPtr->getShapeResource();
|
||||||
|
|
||||||
|
if (shape)
|
||||||
|
{
|
||||||
|
if (!server && !shapeAsset.assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||||
shapeError = true;
|
shapeError = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errorBuffer = String::ToString("PhysicsShapeData: Couldn't load shape \"%s\"", _getShapeAssetId());
|
errorBuffer = String::ToString("PhysicsShapeData: Couldn't load shape! AssetId \"%s\"", shapeAsset.assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the shared physics collision shape.
|
// Prepare the shared physics collision shape.
|
||||||
if ( !colShape && getShape())
|
if ( !colShape && shape)
|
||||||
{
|
{
|
||||||
colShape = getShape()->buildColShape( false, Point3F::One );
|
colShape = shape->buildColShape( false, Point3F::One );
|
||||||
|
|
||||||
// If we got here and didn't get a collision shape then
|
// If we got here and didn't get a collision shape then
|
||||||
// we need to fail... can't have a shape without collision.
|
// we need to fail... can't have a shape without collision.
|
||||||
if ( !colShape )
|
if ( !colShape )
|
||||||
{
|
{
|
||||||
//no collision so we create a simple box collision shape from the shapes bounds and alert the user
|
//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", _getShapeAssetId());
|
Con::warnf( "PhysicsShapeData::preload - No collision found for shape '%s', auto-creating one", shapeAsset.assetId);
|
||||||
Point3F halfWidth = getShape()->mBounds.getExtents() * 0.5f;
|
Point3F halfWidth = shape->mBounds.getExtents() * 0.5f;
|
||||||
colShape = PHYSICSMGR->createCollision();
|
colShape = PHYSICSMGR->createCollision();
|
||||||
MatrixF centerXfm(true);
|
MatrixF centerXfm(true);
|
||||||
centerXfm.setPosition(getShape()->mBounds.getCenter());
|
centerXfm.setPosition(shape->mBounds.getCenter());
|
||||||
colShape->addBox(halfWidth, centerXfm);
|
colShape->addBox(halfWidth, centerXfm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -703,11 +711,12 @@ bool PhysicsShape::_createShape()
|
||||||
mAmbientSeq = -1;
|
mAmbientSeq = -1;
|
||||||
|
|
||||||
PhysicsShapeData *db = getDataBlock();
|
PhysicsShapeData *db = getDataBlock();
|
||||||
if ( !db || !db->getShape())
|
Resource<TSShape> shape;
|
||||||
|
if ( !db || !(shape = db->shapeAsset.assetPtr->getShapeResource()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Set the world box.
|
// Set the world box.
|
||||||
mObjBox = db->getShape()->mBounds;
|
mObjBox = shape->mBounds;
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
|
|
||||||
// If this is the server and its a client only simulation
|
// If this is the server and its a client only simulation
|
||||||
|
|
@ -721,11 +730,11 @@ bool PhysicsShape::_createShape()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the shape instance.
|
// Create the shape instance.
|
||||||
mShapeInst = new TSShapeInstance( db->getShape(), isClientObject() );
|
mShapeInst = new TSShapeInstance(shape, isClientObject() );
|
||||||
|
|
||||||
if ( isClientObject() )
|
if ( isClientObject() )
|
||||||
{
|
{
|
||||||
mAmbientSeq = db->getShape()->findSequence( "ambient" );
|
mAmbientSeq = shape->findSequence( "ambient" );
|
||||||
_initAmbient();
|
_initAmbient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(PhysicsShapeData, Shape)
|
AssetRef<ShapeAsset> shapeAsset;
|
||||||
|
|
||||||
/// The shared unscaled collision shape.
|
/// The shared unscaled collision shape.
|
||||||
PhysicsCollisionRef colShape;
|
PhysicsCollisionRef colShape;
|
||||||
|
|
|
||||||
|
|
@ -299,7 +299,7 @@ PlayerData::PlayerData()
|
||||||
imageAnimPrefixFP = StringTable->EmptyString();
|
imageAnimPrefixFP = StringTable->EmptyString();
|
||||||
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
||||||
{
|
{
|
||||||
mShapeFPAsset[i].registerRefreshNotify(this);
|
shapeFPAssetRef[i].assetPtr.registerRefreshNotify(this);
|
||||||
mCRCFP[i] = 0;
|
mCRCFP[i] = 0;
|
||||||
mValidShapeFP[i] = false;
|
mValidShapeFP[i] = false;
|
||||||
}
|
}
|
||||||
|
|
@ -506,12 +506,16 @@ bool PlayerData::preload(bool server, String &errorStr)
|
||||||
Con::printf("PlayerData:: Jump delay exceeds range (0-%d)",jumpDelay);
|
Con::printf("PlayerData:: Jump delay exceeds range (0-%d)",jumpDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resource<TSShape> shape;
|
||||||
|
if (shapeAssetRef.notNull())
|
||||||
|
shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
// If we don't have a shape don't crash out trying to
|
// If we don't have a shape don't crash out trying to
|
||||||
// setup animations and sequences.
|
// setup animations and sequences.
|
||||||
if (getShape())
|
if (shape)
|
||||||
{
|
{
|
||||||
// Go ahead a pre-load the player shape
|
// Go ahead a pre-load the player shape
|
||||||
TSShapeInstance* si = new TSShapeInstance(getShape(), false);
|
TSShapeInstance* si = new TSShapeInstance(shape, false);
|
||||||
TSThread* thread = si->addThread();
|
TSThread* thread = si->addThread();
|
||||||
|
|
||||||
// Extract ground transform velocity from animations
|
// Extract ground transform velocity from animations
|
||||||
|
|
@ -522,7 +526,7 @@ bool PlayerData::preload(bool server, String &errorStr)
|
||||||
ActionAnimationDef *sp = &ActionAnimationList[i];
|
ActionAnimationDef *sp = &ActionAnimationList[i];
|
||||||
dp->name = sp->name;
|
dp->name = sp->name;
|
||||||
dp->dir.set(sp->dir.x,sp->dir.y,sp->dir.z);
|
dp->dir.set(sp->dir.x,sp->dir.y,sp->dir.z);
|
||||||
dp->sequence = getShape()->findSequence(sp->name);
|
dp->sequence = shape->findSequence(sp->name);
|
||||||
|
|
||||||
// If this is a sprint action and is missing a sequence, attempt to use
|
// If this is a sprint action and is missing a sequence, attempt to use
|
||||||
// the standard run ones.
|
// the standard run ones.
|
||||||
|
|
@ -530,7 +534,7 @@ bool PlayerData::preload(bool server, String &errorStr)
|
||||||
{
|
{
|
||||||
S32 offset = i-SprintRootAnim;
|
S32 offset = i-SprintRootAnim;
|
||||||
ActionAnimationDef *standDef = &ActionAnimationList[RootAnim+offset];
|
ActionAnimationDef *standDef = &ActionAnimationList[RootAnim+offset];
|
||||||
dp->sequence = getShape()->findSequence(standDef->name);
|
dp->sequence = shape->findSequence(standDef->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
dp->velocityScale = true;
|
dp->velocityScale = true;
|
||||||
|
|
@ -538,12 +542,12 @@ bool PlayerData::preload(bool server, String &errorStr)
|
||||||
if (dp->sequence != -1)
|
if (dp->sequence != -1)
|
||||||
getGroundInfo(si,thread,dp);
|
getGroundInfo(si,thread,dp);
|
||||||
}
|
}
|
||||||
for (S32 b = 0; b < getShape()->sequences.size(); b++)
|
for (S32 b = 0; b < shape->sequences.size(); b++)
|
||||||
{
|
{
|
||||||
if (!isTableSequence(b))
|
if (!isTableSequence(b))
|
||||||
{
|
{
|
||||||
dp->sequence = b;
|
dp->sequence = b;
|
||||||
dp->name = getShape()->getName(getShape()->sequences[b].nameIndex);
|
dp->name = shape->getName(shape->sequences[b].nameIndex);
|
||||||
dp->velocityScale = false;
|
dp->velocityScale = false;
|
||||||
getGroundInfo(si,thread,dp++);
|
getGroundInfo(si,thread,dp++);
|
||||||
}
|
}
|
||||||
|
|
@ -560,17 +564,17 @@ bool PlayerData::preload(bool server, String &errorStr)
|
||||||
lookAction = c;
|
lookAction = c;
|
||||||
|
|
||||||
// Resolve spine
|
// Resolve spine
|
||||||
spineNode[0] = getShape()->findNode("Bip01 Pelvis");
|
spineNode[0] = shape->findNode("Bip01 Pelvis");
|
||||||
spineNode[1] = getShape()->findNode("Bip01 Spine");
|
spineNode[1] = shape->findNode("Bip01 Spine");
|
||||||
spineNode[2] = getShape()->findNode("Bip01 Spine1");
|
spineNode[2] = shape->findNode("Bip01 Spine1");
|
||||||
spineNode[3] = getShape()->findNode("Bip01 Spine2");
|
spineNode[3] = shape->findNode("Bip01 Spine2");
|
||||||
spineNode[4] = getShape()->findNode("Bip01 Neck");
|
spineNode[4] = shape->findNode("Bip01 Neck");
|
||||||
spineNode[5] = getShape()->findNode("Bip01 Head");
|
spineNode[5] = shape->findNode("Bip01 Head");
|
||||||
|
|
||||||
// Recoil animations
|
// Recoil animations
|
||||||
recoilSequence[0] = getShape()->findSequence("light_recoil");
|
recoilSequence[0] = shape->findSequence("light_recoil");
|
||||||
recoilSequence[1] = getShape()->findSequence("medium_recoil");
|
recoilSequence[1] = shape->findSequence("medium_recoil");
|
||||||
recoilSequence[2] = getShape()->findSequence("heavy_recoil");
|
recoilSequence[2] = shape->findSequence("heavy_recoil");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert pickupRadius to a delta of boundingBox
|
// Convert pickupRadius to a delta of boundingBox
|
||||||
|
|
@ -613,40 +617,44 @@ bool PlayerData::preload(bool server, String &errorStr)
|
||||||
{
|
{
|
||||||
bool shapeError = false;
|
bool shapeError = false;
|
||||||
|
|
||||||
if (mShapeFPAsset[i].notNull())
|
if (shapeFPAssetRef[i].isNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Resource<TSShape> shapeFP = shapeFPAssetRef[i].assetPtr->getShapeResource();
|
||||||
|
|
||||||
|
if (!shapeFP)
|
||||||
{
|
{
|
||||||
if (!getShapeFP(i))
|
errorStr = String::ToString("PlayerData: Couldn't load mounted image %d shape \"%s\"", i, shapeFPAssetRef[i].assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!server && !shapeFPAssetRef[i].assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||||
|
shapeError = true;
|
||||||
|
|
||||||
|
if (computeCRC)
|
||||||
|
{
|
||||||
|
Con::printf("Validation required for mounted image %d shape: %s", i, shapeFPAssetRef[i].assetId);
|
||||||
|
|
||||||
|
Torque::Path shapeFPFilePath = shapeFPAssetRef[i].assetPtr->getShapeFile();
|
||||||
|
|
||||||
|
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(shapeFPFilePath);
|
||||||
|
|
||||||
|
if (!fileRef)
|
||||||
{
|
{
|
||||||
errorStr = String::ToString("PlayerData: Couldn't load mounted image %d shape \"%s\"", i, _getShapeFPAssetId(i));
|
errorStr = String::ToString("PlayerData: Mounted image %d loading failed, shape \"%s\" is not found.", i, shapeFPFilePath.getFullPath().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!server && !getShapeFP(i)->preloadMaterialList(getShapeFPFile(i)) && NetConnection::filesWereDownloaded())
|
if (server)
|
||||||
shapeError = true;
|
mCRCFP[i] = fileRef->getChecksum();
|
||||||
|
else if (mCRCFP[i] != fileRef->getChecksum())
|
||||||
if (computeCRC)
|
|
||||||
{
|
{
|
||||||
Con::printf("Validation required for mounted image %d shape: %s", i, _getShapeFPAssetId(i));
|
errorStr = String::ToString("PlayerData: Mounted image %d shape \"%s\" does not match version on server.", i, shapeFPAssetRef[i].assetId);
|
||||||
|
return false;
|
||||||
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(getShapeFPFile(i));
|
|
||||||
|
|
||||||
if (!fileRef)
|
|
||||||
{
|
|
||||||
errorStr = String::ToString("PlayerData: Mounted image %d loading failed, shape \"%s\" is not found.", i, getShapeFPFile(i));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server)
|
|
||||||
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, _getShapeFPAssetId(i));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mValidShapeFP[i] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mValidShapeFP[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1150,7 +1158,9 @@ void PlayerData::initPersistFields()
|
||||||
// Mounted images arrays
|
// Mounted images arrays
|
||||||
addArray( "Mounted Images", ShapeBase::MaxMountedImages );
|
addArray( "Mounted Images", ShapeBase::MaxMountedImages );
|
||||||
|
|
||||||
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"
|
ADD_FIELD("shapeFPAsset", TypeShapeAssetRef, Offset(shapeFPAssetRef, PlayerData))
|
||||||
|
.elements(ShapeBase::MaxMountedImages)
|
||||||
|
.doc("@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 "
|
"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 "
|
"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");
|
"animated along with the mounted image's state animation sequences.\n");
|
||||||
|
|
@ -1357,9 +1367,9 @@ void PlayerData::packData(BitStream* stream)
|
||||||
{
|
{
|
||||||
stream->write(mCRCFP[i]);
|
stream->write(mCRCFP[i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PACKDATA_ASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages)
|
AssetDatabase.packDataAsset(stream, shapeFPAssetRef[i].assetId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerData::unpackData(BitStream* stream)
|
void PlayerData::unpackData(BitStream* stream)
|
||||||
|
|
@ -1539,9 +1549,10 @@ void PlayerData::unpackData(BitStream* stream)
|
||||||
{
|
{
|
||||||
stream->read(&(mCRCFP[i]));
|
stream->read(&(mCRCFP[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shapeFPAssetRef[i] = AssetDatabase.unpackDataAsset(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNPACKDATA_ASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1878,9 +1889,13 @@ bool Player::onNewDataBlock( GameBaseData *dptr, bool reload )
|
||||||
{
|
{
|
||||||
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
||||||
{
|
{
|
||||||
if (bool(mDataBlock->getShapeFP(i)))
|
if (mDataBlock->shapeFPAssetRef[i].isNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Resource<TSShape> shapeFP = mDataBlock->shapeFPAssetRef[i].assetPtr->getShapeResource();
|
||||||
|
if (bool(shapeFP))
|
||||||
{
|
{
|
||||||
mShapeFPInstance[i] = new TSShapeInstance(mDataBlock->getShapeFP(i), isClientObject());
|
mShapeFPInstance[i] = new TSShapeInstance(shapeFP, isClientObject());
|
||||||
|
|
||||||
mShapeFPInstance[i]->cloneMaterialList();
|
mShapeFPInstance[i]->cloneMaterialList();
|
||||||
|
|
||||||
|
|
@ -6166,6 +6181,13 @@ void Player::buildConvex(const Box3F& box, Convex* convex)
|
||||||
|
|
||||||
void Player::updateWorkingCollisionSet()
|
void Player::updateWorkingCollisionSet()
|
||||||
{
|
{
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeFPAssetRef->assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return;
|
||||||
|
|
||||||
// First, we need to adjust our velocity for possible acceleration. It is assumed
|
// First, we need to adjust our velocity for possible acceleration. It is assumed
|
||||||
// that we will never accelerate more than 20 m/s for gravity, plus 10 m/s for
|
// that we will never accelerate more than 20 m/s for gravity, plus 10 m/s for
|
||||||
// jetting, and an equivalent 10 m/s for jumping. We also assume that the
|
// jetting, and an equivalent 10 m/s for jumping. We also assume that the
|
||||||
|
|
@ -6173,7 +6195,7 @@ void Player::updateWorkingCollisionSet()
|
||||||
// box by the possible movement in that tick.
|
// box by the possible movement in that tick.
|
||||||
Point3F scaledVelocity = mVelocity * TickSec;
|
Point3F scaledVelocity = mVelocity * TickSec;
|
||||||
F32 len = scaledVelocity.len();
|
F32 len = scaledVelocity.len();
|
||||||
F32 newLen = len + (mDataBlock->getShape()->mRadius * TickSec);
|
F32 newLen = len + (shape->mRadius * TickSec);
|
||||||
|
|
||||||
// Check to see if it is actually necessary to construct the new working list,
|
// Check to see if it is actually necessary to construct the new working list,
|
||||||
// or if we can use the cached version from the last query. We use the x
|
// or if we can use the cached version from the last query. We use the x
|
||||||
|
|
@ -7571,9 +7593,17 @@ F32 Player::getAnimationDurationByID(U32 anim_id)
|
||||||
{
|
{
|
||||||
if (anim_id == BAD_ANIM_ID)
|
if (anim_id == BAD_ANIM_ID)
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
S32 seq_id = mDataBlock->actionList[anim_id].sequence;
|
S32 seq_id = mDataBlock->actionList[anim_id].sequence;
|
||||||
if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size())
|
if (seq_id >= 0 && seq_id < shape->sequences.size())
|
||||||
return mDataBlock->getShape()->sequences[seq_id].duration;
|
return shape->sequences[seq_id].duration;
|
||||||
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
@ -7584,10 +7614,16 @@ bool Player::isBlendAnimation(const char* name)
|
||||||
if (anim_id == BAD_ANIM_ID)
|
if (anim_id == BAD_ANIM_ID)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
S32 seq_id = mDataBlock->actionList[anim_id].sequence;
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size())
|
return false;
|
||||||
return mDataBlock->getShape()->sequences[seq_id].isBlend();
|
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
S32 seq_id = mDataBlock->actionList[anim_id].sequence;
|
||||||
|
if (seq_id >= 0 && seq_id < shape->sequences.size())
|
||||||
|
return shape->sequences[seq_id].isBlend();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ struct PlayerData: public ShapeBaseData /*protected AssetPtrCallback < already i
|
||||||
/// that we don't create a TSThread on the player if we don't
|
/// that we don't create a TSThread on the player if we don't
|
||||||
/// need to.
|
/// need to.
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_ARRAY_REFACTOR(PlayerData, ShapeFP, ShapeBase::MaxMountedImages)
|
AssetRef<ShapeAsset> shapeFPAssetRef[ShapeBase::MaxMountedImages];
|
||||||
|
|
||||||
StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify
|
StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify
|
||||||
/// animation sequences played in first person. [optional]
|
/// animation sequences played in first person. [optional]
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ U32 Projectile::smProjectileWarpTicks = 5;
|
||||||
//
|
//
|
||||||
ProjectileData::ProjectileData()
|
ProjectileData::ProjectileData()
|
||||||
{
|
{
|
||||||
mProjectileShapeAsset.registerRefreshNotify(this);
|
projectileShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
|
|
||||||
INIT_ASSET(ProjectileSound);
|
INIT_ASSET(ProjectileSound);
|
||||||
|
|
||||||
|
|
@ -223,7 +223,7 @@ ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : G
|
||||||
CLONE_ASSET(ProjectileSound);
|
CLONE_ASSET(ProjectileSound);
|
||||||
lightDesc = other.lightDesc;
|
lightDesc = other.lightDesc;
|
||||||
lightDescId = other.lightDescId; // -- for pack/unpack of lightDesc ptr
|
lightDescId = other.lightDescId; // -- for pack/unpack of lightDesc ptr
|
||||||
mProjectileShapeAsset = other.mProjectileShapeAsset;// -- TSShape loads using mProjectileShapeName
|
projectileShapeAssetRef = other.projectileShapeAssetRef;// -- TSShape loads using projectileShapeAssetRef
|
||||||
activateSeq = other.activateSeq; // -- from projectileShape sequence "activate"
|
activateSeq = other.activateSeq; // -- from projectileShape sequence "activate"
|
||||||
maintainSeq = other.maintainSeq; // -- from projectileShape sequence "maintain"
|
maintainSeq = other.maintainSeq; // -- from projectileShape sequence "maintain"
|
||||||
particleEmitter = other.particleEmitter;
|
particleEmitter = other.particleEmitter;
|
||||||
|
|
@ -237,7 +237,8 @@ void ProjectileData::initPersistFields()
|
||||||
{
|
{
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup("Shapes");
|
addGroup("Shapes");
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(ProjectileShape, ProjectileData, "@brief The model of the projectile.\n\n");
|
ADD_FIELD("projectileShapeAsset", TypeShapeAssetRef, Offset(projectileShapeAssetRef, ProjectileData))
|
||||||
|
.doc("@brief The model of the projectile.\n\n");
|
||||||
addField("scale", TypePoint3F, Offset(scale, ProjectileData),
|
addField("scale", TypePoint3F, Offset(scale, ProjectileData),
|
||||||
"@brief Scale to apply to the projectile's size.\n\n"
|
"@brief Scale to apply to the projectile's size.\n\n"
|
||||||
"@note This is applied after SceneObject::scale\n");
|
"@note This is applied after SceneObject::scale\n");
|
||||||
|
|
@ -422,18 +423,21 @@ bool ProjectileData::preload(bool server, String &errorStr)
|
||||||
Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockid(lightDesc): %d", lightDescId);
|
Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockid(lightDesc): %d", lightDescId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getProjectileShape())
|
if (!projectileShapeAssetRef.isNull())
|
||||||
{
|
{
|
||||||
activateSeq = getProjectileShape()->findSequence("activate");
|
Resource<TSShape> shape = projectileShapeAssetRef.assetPtr->getShapeResource();
|
||||||
maintainSeq = getProjectileShape()->findSequence("maintain");
|
if (shape)
|
||||||
|
{
|
||||||
TSShapeInstance* pDummy = new TSShapeInstance(getProjectileShape(), !server);
|
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||||
delete pDummy;
|
delete pDummy;
|
||||||
}
|
if (!server && !projectileShapeAssetRef.assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||||
else if (mProjectileShapeAsset.notNull())
|
return false;
|
||||||
{
|
}
|
||||||
errorStr = String::ToString("ProjectileData::preload: Couldn't load shape \"%s\"", _getProjectileShapeAssetId());
|
else
|
||||||
return false;
|
{
|
||||||
|
errorStr = String::ToString("ProjectileData(%s)::preload: Couldn't load shape \"%s\"", getName(), projectileShapeAssetRef.assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -444,7 +448,7 @@ void ProjectileData::packData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::packData(stream);
|
Parent::packData(stream);
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(ProjectileShape);
|
AssetDatabase.packDataAsset(stream, projectileShapeAssetRef.assetId);;
|
||||||
|
|
||||||
stream->writeFlag(faceViewer);
|
stream->writeFlag(faceViewer);
|
||||||
if(stream->writeFlag(scale.x != 1 || scale.y != 1 || scale.z != 1))
|
if(stream->writeFlag(scale.x != 1 || scale.y != 1 || scale.z != 1))
|
||||||
|
|
@ -509,7 +513,7 @@ void ProjectileData::unpackData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::unpackData(stream);
|
Parent::unpackData(stream);
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(ProjectileShape);
|
projectileShapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
|
||||||
faceViewer = stream->readFlag();
|
faceViewer = stream->readFlag();
|
||||||
if(stream->readFlag())
|
if(stream->readFlag())
|
||||||
|
|
@ -808,6 +812,8 @@ bool Projectile::onAdd()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resource<TSShape> pShape;
|
||||||
|
|
||||||
if (isServerObject())
|
if (isServerObject())
|
||||||
{
|
{
|
||||||
ShapeBase* ptr;
|
ShapeBase* ptr;
|
||||||
|
|
@ -835,15 +841,19 @@ bool Projectile::onAdd()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (bool(mDataBlock->getProjectileShape()))
|
if (mDataBlock->projectileShapeAssetRef.notNull())
|
||||||
{
|
{
|
||||||
mProjectileShape = new TSShapeInstance(mDataBlock->getProjectileShape(), isClientObject());
|
pShape = mDataBlock->projectileShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (pShape)
|
||||||
if (mDataBlock->activateSeq != -1)
|
|
||||||
{
|
{
|
||||||
mActivateThread = mProjectileShape->addThread();
|
mProjectileShape = new TSShapeInstance(pShape, isClientObject());
|
||||||
mProjectileShape->setTimeScale(mActivateThread, 1);
|
|
||||||
mProjectileShape->setSequence(mActivateThread, mDataBlock->activateSeq, 0);
|
if (mDataBlock->activateSeq != -1)
|
||||||
|
{
|
||||||
|
mActivateThread = mProjectileShape->addThread();
|
||||||
|
mProjectileShape->setTimeScale(mActivateThread, 1);
|
||||||
|
mProjectileShape->setSequence(mActivateThread, mDataBlock->activateSeq, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mDataBlock->particleEmitter != NULL)
|
if (mDataBlock->particleEmitter != NULL)
|
||||||
|
|
@ -876,8 +886,8 @@ bool Projectile::onAdd()
|
||||||
processAfter(mSourceObject);
|
processAfter(mSourceObject);
|
||||||
|
|
||||||
// Setup our bounding box
|
// Setup our bounding box
|
||||||
if (bool(mDataBlock->getProjectileShape()) == true)
|
if (bool(pShape) == true)
|
||||||
mObjBox = mDataBlock->getProjectileShape()->mBounds;
|
mObjBox = pShape->mBounds;
|
||||||
else
|
else
|
||||||
mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0));
|
mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ protected:
|
||||||
bool onAdd() override;
|
bool onAdd() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DECLARE_SHAPEASSET_REFACTOR(ProjectileData, ProjectileShape)
|
AssetRef<ShapeAsset> projectileShapeAssetRef;
|
||||||
|
|
||||||
/// Set to true if it is a billboard and want it to always face the viewer, false otherwise
|
/// Set to true if it is a billboard and want it to always face the viewer, false otherwise
|
||||||
bool faceViewer;
|
bool faceViewer;
|
||||||
|
|
|
||||||
|
|
@ -144,11 +144,15 @@ bool ProximityMineData::preload( bool server, String& errorStr )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( getShape() )
|
if (shapeAssetRef.notNull())
|
||||||
{
|
{
|
||||||
// Lookup animation sequences
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
armingSequence = getShape()->findSequence( "armed" );
|
if (shape)
|
||||||
triggerSequence = getShape()->findSequence( "triggered" );
|
{
|
||||||
|
// Lookup animation sequences
|
||||||
|
armingSequence = shape->findSequence("armed");
|
||||||
|
triggerSequence = shape->findSequence("triggered");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,8 @@ RigidShapeData::RigidShapeData()
|
||||||
|
|
||||||
dustTrailEmitter = NULL;
|
dustTrailEmitter = NULL;
|
||||||
dustTrailID = 0;
|
dustTrailID = 0;
|
||||||
_setShape(ShapeAsset::smNoShapeAssetFallback);
|
|
||||||
|
shapeAssetRef = ShapeAsset::smNoShapeAssetFallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidShapeData::~RigidShapeData()
|
RigidShapeData::~RigidShapeData()
|
||||||
|
|
@ -340,7 +341,7 @@ bool RigidShapeData::preload(bool server, String &errorStr)
|
||||||
if (!collisionDetails.size() || collisionDetails[0] == -1)
|
if (!collisionDetails.size() || collisionDetails[0] == -1)
|
||||||
{
|
{
|
||||||
Con::errorf("RigidShapeData::preload failed: Rigid shapes must define a collision-1 detail");
|
Con::errorf("RigidShapeData::preload failed: Rigid shapes must define a collision-1 detail");
|
||||||
errorStr = String::ToString("RigidShapeData: Couldn't load shape asset \"%s\"", getShapeAsset().getAssetId());
|
errorStr = String::ToString("RigidShapeData: Couldn't load shape asset \"%s\"", shapeAssetRef.assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1443,13 +1444,20 @@ void RigidShape::updateWorkingCollisionSet(const U32 mask)
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE( Vehicle_UpdateWorkingCollisionSet );
|
PROFILE_SCOPE( Vehicle_UpdateWorkingCollisionSet );
|
||||||
|
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return;
|
||||||
|
|
||||||
// First, we need to adjust our velocity for possible acceleration. It is assumed
|
// First, we need to adjust our velocity for possible acceleration. It is assumed
|
||||||
// that we will never accelerate more than 20 m/s for gravity, plus 30 m/s for
|
// that we will never accelerate more than 20 m/s for gravity, plus 30 m/s for
|
||||||
// jetting, and an equivalent 10 m/s for vehicle accel. We also assume that our
|
// jetting, and an equivalent 10 m/s for vehicle accel. We also assume that our
|
||||||
// working list is updated on a Tick basis, which means we only expand our box by
|
// working list is updated on a Tick basis, which means we only expand our box by
|
||||||
// the possible movement in that tick, plus some extra for caching purposes
|
// the possible movement in that tick, plus some extra for caching purposes
|
||||||
Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
|
Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
|
||||||
F32 len = (mRigid.linVelocity.len() + mDataBlock->getShape()->mRadius) * TickSec;
|
F32 len = (mRigid.linVelocity.len() + shape->mRadius) * TickSec;
|
||||||
F32 l = (len * 1.1) + 0.1; // fudge factor
|
F32 l = (len * 1.1) + 0.1; // fudge factor
|
||||||
convexBox.minExtents -= Point3F(l, l, l);
|
convexBox.minExtents -= Point3F(l, l, l);
|
||||||
convexBox.maxExtents += Point3F(l, l, l);
|
convexBox.maxExtents += Point3F(l, l, l);
|
||||||
|
|
|
||||||
|
|
@ -205,8 +205,8 @@ ShapeBaseData::ShapeBaseData()
|
||||||
remap_txr_tags = NULL;
|
remap_txr_tags = NULL;
|
||||||
remap_buffer = NULL;
|
remap_buffer = NULL;
|
||||||
silent_bbox_check = false;
|
silent_bbox_check = false;
|
||||||
mShapeAsset.registerRefreshNotify(this);
|
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
mDebrisShapeAsset.registerRefreshNotify(this);
|
debrisShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||||
|
|
@ -216,13 +216,13 @@ ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : Game
|
||||||
shadowProjectionDistance = other.shadowProjectionDistance;
|
shadowProjectionDistance = other.shadowProjectionDistance;
|
||||||
shadowSphereAdjust = other.shadowSphereAdjust;
|
shadowSphereAdjust = other.shadowSphereAdjust;
|
||||||
cloakTexName = other.cloakTexName;
|
cloakTexName = other.cloakTexName;
|
||||||
mShapeAsset = other.mShapeAsset;
|
shapeAssetRef = other.shapeAssetRef;
|
||||||
cubeDescName = other.cubeDescName;
|
cubeDescName = other.cubeDescName;
|
||||||
cubeDescId = other.cubeDescId;
|
cubeDescId = other.cubeDescId;
|
||||||
reflectorDesc = other.reflectorDesc;
|
reflectorDesc = other.reflectorDesc;
|
||||||
debris = other.debris;
|
debris = other.debris;
|
||||||
debrisID = other.debrisID; // -- for pack/unpack of debris ptr
|
debrisID = other.debrisID; // -- for pack/unpack of debris ptr
|
||||||
mDebrisShapeAsset = other.mDebrisShapeAsset;
|
debrisShapeAssetRef = other.debrisShapeAssetRef;
|
||||||
explosion = other.explosion;
|
explosion = other.explosion;
|
||||||
explosionID = other.explosionID; // -- for pack/unpack of explosion ptr
|
explosionID = other.explosionID; // -- for pack/unpack of explosion ptr
|
||||||
underwaterExplosion = other.underwaterExplosion;
|
underwaterExplosion = other.underwaterExplosion;
|
||||||
|
|
@ -299,12 +299,8 @@ static ShapeBaseDataProto gShapeBaseDataProto;
|
||||||
|
|
||||||
ShapeBaseData::~ShapeBaseData()
|
ShapeBaseData::~ShapeBaseData()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (remap_buffer && !isTempClone())
|
if (remap_buffer && !isTempClone())
|
||||||
dFree(remap_buffer);
|
dFree(remap_buffer);
|
||||||
|
|
||||||
mShapeAsset.unregisterRefreshNotify();
|
|
||||||
mDebrisShapeAsset.unregisterRefreshNotify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShapeBaseData::preload(bool server, String &errorStr)
|
bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||||
|
|
@ -350,32 +346,38 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||||
"ShapeBaseData::preload: invalid debris data");
|
"ShapeBaseData::preload: invalid debris data");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getDebrisShape())
|
if (debrisShapeAssetRef.notNull())
|
||||||
{
|
{
|
||||||
TSShapeInstance* pDummy = new TSShapeInstance(getDebrisShape(), !server);
|
Resource<TSShape> dShape = debrisShapeAssetRef.assetPtr->getShapeResource();
|
||||||
delete pDummy;
|
if (dShape)
|
||||||
|
{
|
||||||
|
TSShapeInstance* pDummy = new TSShapeInstance(dShape, !server);
|
||||||
|
delete pDummy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resource<TSShape> shape;
|
||||||
|
|
||||||
S32 i;
|
S32 i;
|
||||||
if (getShape())
|
if (shapeAssetRef.notNull() && (shape = shapeAssetRef.assetPtr->getShapeResource()))
|
||||||
{
|
{
|
||||||
//mShapeAsset->load();
|
//mShapeAsset->load();
|
||||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
|
U32 assetStatus = ShapeAsset::getAssetErrCode(shapeAssetRef.assetPtr);
|
||||||
if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback)
|
if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback)
|
||||||
{
|
{
|
||||||
if (!server && !getShape()->preloadMaterialList(getShapeFile()) && NetConnection::filesWereDownloaded())
|
if (!server && !shapeAssetRef.assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||||
shapeError = true;
|
shapeError = true;
|
||||||
|
|
||||||
if (computeCRC)
|
if (computeCRC)
|
||||||
{
|
{
|
||||||
Con::printf("Validation required for shape asset: %s", mShapeAsset.getAssetId());
|
Con::printf("Validation required for shape asset: %s", shapeAssetRef.assetId);
|
||||||
|
|
||||||
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShapeAsset->getShapeFile());
|
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(shapeAssetRef.assetPtr->getShapeFile());
|
||||||
|
|
||||||
if (!fileRef)
|
if (!fileRef)
|
||||||
{
|
{
|
||||||
errorStr = String::ToString("ShapeBaseData: Couldn't load shape asset \"%s\"", mShapeAsset.getAssetId());
|
errorStr = String::ToString("ShapeBaseData(%s): Couldn't load shape asset \"%s\"", getName(), shapeAssetRef.assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,36 +385,36 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||||
mCRC = fileRef->getChecksum();
|
mCRC = fileRef->getChecksum();
|
||||||
else if (mCRC != fileRef->getChecksum())
|
else if (mCRC != fileRef->getChecksum())
|
||||||
{
|
{
|
||||||
errorStr = String::ToString("Shape asset \"%s\" does not match version on server.", mShapeAsset.getAssetId());
|
errorStr = String::ToString("Shape asset \"%s\" does not match version on server.", shapeAssetRef.assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Resolve details and camera node indexes.
|
// Resolve details and camera node indexes.
|
||||||
static const String sCollisionStr("collision-");
|
static const String sCollisionStr("collision-");
|
||||||
|
|
||||||
for (i = 0; i < getShape()->details.size(); i++)
|
for (i = 0; i < shape->details.size(); i++)
|
||||||
{
|
{
|
||||||
const String& name = getShape()->names[getShape()->details[i].nameIndex];
|
const String& name = shape->names[shape->details[i].nameIndex];
|
||||||
|
|
||||||
if (name.compare(sCollisionStr, sCollisionStr.length(), String::NoCase) == 0)
|
if (name.compare(sCollisionStr, sCollisionStr.length(), String::NoCase) == 0)
|
||||||
{
|
{
|
||||||
collisionDetails.push_back(i);
|
collisionDetails.push_back(i);
|
||||||
collisionBounds.increment();
|
collisionBounds.increment();
|
||||||
|
|
||||||
getShape()->computeBounds(collisionDetails.last(), collisionBounds.last());
|
shape->computeBounds(collisionDetails.last(), collisionBounds.last());
|
||||||
getShape()->getAccelerator(collisionDetails.last());
|
shape->getAccelerator(collisionDetails.last());
|
||||||
|
|
||||||
if (!getShape()->mBounds.isContained(collisionBounds.last()))
|
if (!shape->mBounds.isContained(collisionBounds.last()))
|
||||||
{
|
{
|
||||||
if (!silent_bbox_check)
|
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());
|
Con::warnf("Warning: shape asset %s collision detail %d (Collision-%d) bounds exceed that of shape.", shapeAssetRef.assetId, collisionDetails.size() - 1, collisionDetails.last());
|
||||||
collisionBounds.last() = getShape()->mBounds;
|
collisionBounds.last() = shape->mBounds;
|
||||||
}
|
}
|
||||||
else if (collisionBounds.last().isValidBox() == false)
|
else if (collisionBounds.last().isValidBox() == false)
|
||||||
{
|
{
|
||||||
if (!silent_bbox_check)
|
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());
|
Con::errorf("Error: shape asset %s-collision detail %d (Collision-%d) bounds box invalid!", shapeAssetRef.assetId, collisionDetails.size() - 1, collisionDetails.last());
|
||||||
collisionBounds.last() = getShape()->mBounds;
|
collisionBounds.last() = shape->mBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The way LOS works is that it will check to see if there is a LOS detail that matches
|
// The way LOS works is that it will check to see if there is a LOS detail that matches
|
||||||
|
|
@ -422,7 +424,7 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||||
LOSDetails.increment();
|
LOSDetails.increment();
|
||||||
|
|
||||||
String buff = String::ToString("LOS-%d", i + 1 + MaxCollisionShapes);
|
String buff = String::ToString("LOS-%d", i + 1 + MaxCollisionShapes);
|
||||||
U32 los = getShape()->findDetail(buff);
|
U32 los = shape->findDetail(buff);
|
||||||
if (los == -1)
|
if (los == -1)
|
||||||
LOSDetails.last() = i;
|
LOSDetails.last() = i;
|
||||||
else
|
else
|
||||||
|
|
@ -433,9 +435,9 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||||
// Snag any "unmatched" LOS details
|
// Snag any "unmatched" LOS details
|
||||||
static const String sLOSStr("LOS-");
|
static const String sLOSStr("LOS-");
|
||||||
|
|
||||||
for (i = 0; i < getShape()->details.size(); i++)
|
for (i = 0; i < shape->details.size(); i++)
|
||||||
{
|
{
|
||||||
const String& name = getShape()->names[getShape()->details[i].nameIndex];
|
const String& name = shape->names[shape->details[i].nameIndex];
|
||||||
|
|
||||||
if (name.compare(sLOSStr, sLOSStr.length(), String::NoCase) == 0)
|
if (name.compare(sLOSStr, sLOSStr.length(), String::NoCase) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -455,12 +457,12 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debrisDetail = getShape()->findDetail("Debris-17");
|
debrisDetail = shape->findDetail("Debris-17");
|
||||||
eyeNode = getShape()->findNode("eye");
|
eyeNode = shape->findNode("eye");
|
||||||
earNode = getShape()->findNode("ear");
|
earNode = shape->findNode("ear");
|
||||||
if (earNode == -1)
|
if (earNode == -1)
|
||||||
earNode = eyeNode;
|
earNode = eyeNode;
|
||||||
cameraNode = getShape()->findNode("cam");
|
cameraNode = shape->findNode("cam");
|
||||||
if (cameraNode == -1)
|
if (cameraNode == -1)
|
||||||
cameraNode = eyeNode;
|
cameraNode = eyeNode;
|
||||||
|
|
||||||
|
|
@ -468,18 +470,18 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||||
for (i = 0; i < SceneObject::NumMountPoints; i++) {
|
for (i = 0; i < SceneObject::NumMountPoints; i++) {
|
||||||
char fullName[256];
|
char fullName[256];
|
||||||
dSprintf(fullName, sizeof(fullName), "mount%d", i);
|
dSprintf(fullName, sizeof(fullName), "mount%d", i);
|
||||||
mountPointNode[i] = getShape()->findNode(fullName);
|
mountPointNode[i] = shape->findNode(fullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the AIRepairNode - hardcoded to be the last node in the array...
|
// find the AIRepairNode - hardcoded to be the last node in the array...
|
||||||
mountPointNode[AIRepairNode] = getShape()->findNode("AIRepairNode");
|
mountPointNode[AIRepairNode] = shape->findNode("AIRepairNode");
|
||||||
|
|
||||||
//
|
//
|
||||||
hulkSequence = getShape()->findSequence("Visibility");
|
hulkSequence = shape->findSequence("Visibility");
|
||||||
damageSequence = getShape()->findSequence("Damage");
|
damageSequence = shape->findSequence("Damage");
|
||||||
|
|
||||||
//
|
//
|
||||||
F32 w = getShape()->mBounds.len_y() / 2;
|
F32 w = shape->mBounds.len_y() / 2;
|
||||||
if (cameraMaxDist < w)
|
if (cameraMaxDist < w)
|
||||||
cameraMaxDist = w;
|
cameraMaxDist = w;
|
||||||
// just parse up the string and collect the remappings in txr_tag_remappings.
|
// just parse up the string and collect the remappings in txr_tag_remappings.
|
||||||
|
|
@ -507,7 +509,7 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Con::errorf("ShapeBaseData::preload -%s failed: %s", mShapeAsset.getAssetId(), ShapeAsset::getAssetErrstrn(assetStatus).c_str());
|
Con::errorf("ShapeBaseData::preload(%s) -%s failed: %s", getName(), shapeAssetRef.assetId, ShapeAsset::getAssetErrstrn(assetStatus).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!server)
|
if(!server)
|
||||||
|
|
@ -557,12 +559,14 @@ void ShapeBaseData::initPersistFields()
|
||||||
{
|
{
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup( "Shapes" );
|
addGroup( "Shapes" );
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, ShapeBaseData, "The source shape asset.");
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, ShapeBaseData))
|
||||||
|
.doc("The source shape asset.");
|
||||||
addField("computeCRC", TypeBool, Offset(computeCRC, ShapeBaseData),
|
addField("computeCRC", TypeBool, Offset(computeCRC, ShapeBaseData),
|
||||||
"If true, verify that the CRC of the client's shape model matches the "
|
"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.");
|
"server's CRC for the shape model when loaded by the client.");
|
||||||
addField("silentBBoxValidation", TypeBool, Offset(silent_bbox_check, ShapeBaseData));
|
addField("silentBBoxValidation", TypeBool, Offset(silent_bbox_check, ShapeBaseData));
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(DebrisShape, ShapeBaseData, "The shape asset to use for auto-generated breakups via blowup(). @note may not be functional.");
|
ADD_FIELD("debrisShapeAsset", TypeShapeAssetRef, Offset(debrisShapeAssetRef, ShapeBaseData))
|
||||||
|
.doc("The shape asset to use for auto-generated breakups via blowup(). @note may not be functional.");
|
||||||
endGroup( "Shapes" );
|
endGroup( "Shapes" );
|
||||||
addGroup("Movement");
|
addGroup("Movement");
|
||||||
addField("aiControllerData", TYPEID< AIControllerData >(), Offset(mAIControllData, ShapeBaseData),
|
addField("aiControllerData", TYPEID< AIControllerData >(), Offset(mAIControllData, ShapeBaseData),
|
||||||
|
|
@ -691,12 +695,16 @@ DefineEngineMethod( ShapeBaseData, checkDeployPos, bool, ( TransformF txfm ),,
|
||||||
|
|
||||||
"@note This is a server side only check, and is not actually limited to spawning.\n")
|
"@note This is a server side only check, and is not actually limited to spawning.\n")
|
||||||
{
|
{
|
||||||
if (bool(object->getShape()) == false)
|
if (object->shapeAssetRef.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = object->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (bool(shape) == false)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MatrixF mat = txfm.getMatrix();
|
MatrixF mat = txfm.getMatrix();
|
||||||
|
|
||||||
Box3F objBox = object->getShape()->mBounds;
|
Box3F objBox = shape->mBounds;
|
||||||
Point3F boxCenter = (objBox.minExtents + objBox.maxExtents) * 0.5f;
|
Point3F boxCenter = (objBox.minExtents + objBox.maxExtents) * 0.5f;
|
||||||
objBox.minExtents = boxCenter + (objBox.minExtents - boxCenter) * 0.9f;
|
objBox.minExtents = boxCenter + (objBox.minExtents - boxCenter) * 0.9f;
|
||||||
objBox.maxExtents = boxCenter + (objBox.maxExtents - boxCenter) * 0.9f;
|
objBox.maxExtents = boxCenter + (objBox.maxExtents - boxCenter) * 0.9f;
|
||||||
|
|
@ -766,8 +774,8 @@ void ShapeBaseData::packData(BitStream* stream)
|
||||||
stream->write(shadowProjectionDistance);
|
stream->write(shadowProjectionDistance);
|
||||||
stream->write(shadowSphereAdjust);
|
stream->write(shadowSphereAdjust);
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(Shape);
|
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||||
PACKDATA_ASSET_REFACTOR(DebrisShape);
|
AssetDatabase.packDataAsset(stream, debrisShapeAssetRef.assetId);
|
||||||
|
|
||||||
stream->writeString(cloakTexName);
|
stream->writeString(cloakTexName);
|
||||||
if(stream->writeFlag(mass != gShapeBaseDataProto.mass))
|
if(stream->writeFlag(mass != gShapeBaseDataProto.mass))
|
||||||
|
|
@ -843,8 +851,8 @@ void ShapeBaseData::unpackData(BitStream* stream)
|
||||||
stream->read(&shadowProjectionDistance);
|
stream->read(&shadowProjectionDistance);
|
||||||
stream->read(&shadowSphereAdjust);
|
stream->read(&shadowSphereAdjust);
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
UNPACKDATA_ASSET_REFACTOR(DebrisShape);
|
debrisShapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
|
||||||
cloakTexName = stream->readSTString();
|
cloakTexName = stream->readSTString();
|
||||||
if(stream->readFlag())
|
if(stream->readFlag())
|
||||||
|
|
@ -1224,12 +1232,14 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload )
|
||||||
|
|
||||||
// Even if loadShape succeeds, there may not actually be
|
// Even if loadShape succeeds, there may not actually be
|
||||||
// a shape assigned to this object.
|
// a shape assigned to this object.
|
||||||
if (bool(mDataBlock->getShape())) {
|
Resource<TSShape> shape;
|
||||||
|
if (bool(mDataBlock->shapeAssetRef.notNull() && (shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource())))
|
||||||
|
{
|
||||||
delete mShapeInstance;
|
delete mShapeInstance;
|
||||||
if (isClientObject() && mDataBlock->txr_tag_remappings.size() > 0)
|
if (isClientObject() && mDataBlock->txr_tag_remappings.size() > 0)
|
||||||
{
|
{
|
||||||
// temporarily substitute material tags with alternates
|
// temporarily substitute material tags with alternates
|
||||||
TSMaterialList* mat_list = mDataBlock->getShape()->materialList;
|
TSMaterialList* mat_list = shape->materialList;
|
||||||
if (mat_list)
|
if (mat_list)
|
||||||
{
|
{
|
||||||
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
||||||
|
|
@ -1249,7 +1259,7 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mShapeInstance = new TSShapeInstance(mDataBlock->getShape(), isClientObject());
|
mShapeInstance = new TSShapeInstance(shape, isClientObject());
|
||||||
if (isClientObject())
|
if (isClientObject())
|
||||||
{
|
{
|
||||||
mShapeInstance->cloneMaterialList();
|
mShapeInstance->cloneMaterialList();
|
||||||
|
|
@ -1257,7 +1267,7 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload )
|
||||||
// restore the material tags to original form
|
// restore the material tags to original form
|
||||||
if (mDataBlock->txr_tag_remappings.size() > 0)
|
if (mDataBlock->txr_tag_remappings.size() > 0)
|
||||||
{
|
{
|
||||||
TSMaterialList* mat_list = mDataBlock->getShape()->materialList;
|
TSMaterialList* mat_list = shape->materialList;
|
||||||
if (mat_list)
|
if (mat_list)
|
||||||
{
|
{
|
||||||
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
||||||
|
|
@ -1283,11 +1293,11 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mObjBox = mDataBlock->getShape()->mBounds;
|
mObjBox = shape->mBounds;
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
|
|
||||||
// Set the initial mesh hidden state.
|
// Set the initial mesh hidden state.
|
||||||
mMeshHidden.setSize(mDataBlock->getShape()->objects.size());
|
mMeshHidden.setSize(shape->objects.size());
|
||||||
mMeshHidden.clear();
|
mMeshHidden.clear();
|
||||||
|
|
||||||
// Initialize the threads
|
// Initialize the threads
|
||||||
|
|
@ -1311,11 +1321,11 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload )
|
||||||
|
|
||||||
AssertFatal(prevDB != NULL, "ShapeBase::onNewDataBlock - how did you have a sequence playing without a prior datablock?");
|
AssertFatal(prevDB != NULL, "ShapeBase::onNewDataBlock - how did you have a sequence playing without a prior datablock?");
|
||||||
|
|
||||||
const TSShape* prevShape = prevDB->getShape();
|
const TSShape* prevShape = prevDB->shapeAssetRef.assetPtr->getShape();
|
||||||
const TSShape::Sequence& prevSeq = prevShape->sequences[st.sequence];
|
const TSShape::Sequence& prevSeq = prevShape->sequences[st.sequence];
|
||||||
const String& prevSeqName = prevShape->names[prevSeq.nameIndex];
|
const String& prevSeqName = prevShape->names[prevSeq.nameIndex];
|
||||||
|
|
||||||
st.sequence = mDataBlock->getShape()->findSequence(prevSeqName);
|
st.sequence = shape->findSequence(prevSeqName);
|
||||||
|
|
||||||
if (st.sequence != -1)
|
if (st.sequence != -1)
|
||||||
{
|
{
|
||||||
|
|
@ -1991,13 +2001,14 @@ void ShapeBase::blowUp()
|
||||||
|
|
||||||
TSShapeInstance *debShape = NULL;
|
TSShapeInstance *debShape = NULL;
|
||||||
|
|
||||||
if( mDataBlock->getDebrisShape() == NULL)
|
Resource<TSShape> debrisShape;
|
||||||
|
if( mDataBlock->debrisShapeAssetRef.isNull() || !(debrisShape = mDataBlock->debrisShapeAssetRef.assetPtr->getShapeResource()) )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debShape = new TSShapeInstance( mDataBlock->getDebrisShape(), true);
|
debShape = new TSShapeInstance(debrisShape, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2069,7 +2080,11 @@ Point3F ShapeBase::getAIRepairPoint()
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void ShapeBase::getNodeTransform(const char* nodeName, MatrixF* outMat)
|
void ShapeBase::getNodeTransform(const char* nodeName, MatrixF* outMat)
|
||||||
{
|
{
|
||||||
S32 nodeIDx = mDataBlock->getShape()->findNode(nodeName);
|
Resource<TSShape> shape;
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull() || !(shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
S32 nodeIDx = shape->findNode(nodeName);
|
||||||
const MatrixF& xfm = isMounted() ? mMount.xfm : MatrixF::Identity;
|
const MatrixF& xfm = isMounted() ? mMount.xfm : MatrixF::Identity;
|
||||||
|
|
||||||
MatrixF nodeTransform(xfm);
|
MatrixF nodeTransform(xfm);
|
||||||
|
|
@ -2236,7 +2251,9 @@ void ShapeBase::getNodeTransform(const char* nodeName, const MatrixF& xfm, Matri
|
||||||
if (!mShapeInstance)
|
if (!mShapeInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
S32 nodeIDx = mDataBlock->getShape()->findNode(nodeName);
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
|
S32 nodeIDx = shape->findNode(nodeName);
|
||||||
|
|
||||||
MatrixF nodeTransform(xfm);
|
MatrixF nodeTransform(xfm);
|
||||||
const Point3F& scale = getScale();
|
const Point3F& scale = getScale();
|
||||||
|
|
@ -5045,7 +5062,14 @@ void ShapeBase::_updateHiddenMeshes()
|
||||||
|
|
||||||
void ShapeBase::setMeshHidden( const char *meshName, bool forceHidden )
|
void ShapeBase::setMeshHidden( const char *meshName, bool forceHidden )
|
||||||
{
|
{
|
||||||
setMeshHidden( mDataBlock->getShape()->findObject(meshName), forceHidden);
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setMeshHidden(shape->findObject(meshName), forceHidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeBase::setMeshHidden( S32 meshIndex, bool forceHidden )
|
void ShapeBase::setMeshHidden( S32 meshIndex, bool forceHidden )
|
||||||
|
|
@ -5114,7 +5138,8 @@ void ShapeBase::dumpMeshVisibility()
|
||||||
{
|
{
|
||||||
const TSShapeInstance::MeshObjectInstance &mesh = meshes[i];
|
const TSShapeInstance::MeshObjectInstance &mesh = meshes[i];
|
||||||
|
|
||||||
const String &meshName = mDataBlock->getShape()->getMeshName( i );
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
const String &meshName = shape->getMeshName( i );
|
||||||
|
|
||||||
Con::printf( "%d - %s - forceHidden = %s, visibility = %f",
|
Con::printf( "%d - %s - forceHidden = %s, visibility = %f",
|
||||||
i,
|
i,
|
||||||
|
|
@ -5395,9 +5420,16 @@ F32 ShapeBase::getAnimationDurationByID(U32 anim_id)
|
||||||
if (anim_id == BAD_ANIM_ID)
|
if (anim_id == BAD_ANIM_ID)
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
S32 seq_id = (S32) anim_id;
|
S32 seq_id = (S32) anim_id;
|
||||||
if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size())
|
if (seq_id >= 0 && seq_id < shape->sequences.size())
|
||||||
return mDataBlock->getShape()->sequences[seq_id].duration;
|
return shape->sequences[seq_id].duration;
|
||||||
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
@ -5408,9 +5440,16 @@ bool ShapeBase::isBlendAnimation(const char* name)
|
||||||
if (anim_id == BAD_ANIM_ID)
|
if (anim_id == BAD_ANIM_ID)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
S32 seq_id = (S32) anim_id;
|
S32 seq_id = (S32) anim_id;
|
||||||
if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size())
|
if (seq_id >= 0 && seq_id < shape->sequences.size())
|
||||||
return mDataBlock->getShape()->sequences[seq_id].isBlend();
|
return shape->sequences[seq_id].isBlend();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -5420,13 +5459,20 @@ const char* ShapeBase::getLastClipName(U32 clip_tag)
|
||||||
if (clip_tag != last_anim_tag)
|
if (clip_tag != last_anim_tag)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return "";
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return "";
|
||||||
|
|
||||||
S32 seq_id = (S32) last_anim_id;
|
S32 seq_id = (S32) last_anim_id;
|
||||||
|
|
||||||
S32 idx = mDataBlock->getShape()->sequences[seq_id].nameIndex;
|
S32 idx = shape->sequences[seq_id].nameIndex;
|
||||||
if (idx < 0 || idx >= mDataBlock->getShape()->names.size())
|
if (idx < 0 || idx >= shape->names.size())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return mDataBlock->getShape()->names[idx];
|
return shape->names[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,7 @@ struct ShapeBaseImageData: public GameBaseData, protected AssetPtrCallback
|
||||||
F32 scriptAnimTransitionTime; ///< The amount of time to transition between the previous sequence and new sequence
|
F32 scriptAnimTransitionTime; ///< The amount of time to transition between the previous sequence and new sequence
|
||||||
///< when the script prefix has changed.
|
///< when the script prefix has changed.
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_ARRAY_REFACTOR(ShapeBaseImageData, Shape, MaxShapes) ///< Name of shape to render.
|
AssetRef<ShapeAsset> shapeAssetRef[MaxShapes];
|
||||||
|
|
||||||
StringTableEntry imageAnimPrefix; ///< Passed along to the mounting shape to modify
|
StringTableEntry imageAnimPrefix; ///< Passed along to the mounting shape to modify
|
||||||
/// animation sequences played in 3rd person. [optional]
|
/// animation sequences played in 3rd person. [optional]
|
||||||
|
|
@ -556,7 +556,7 @@ public:
|
||||||
F32 shadowProjectionDistance;
|
F32 shadowProjectionDistance;
|
||||||
F32 shadowSphereAdjust;
|
F32 shadowSphereAdjust;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(ShapeBaseData, Shape)
|
AssetRef<ShapeAsset> shapeAssetRef;
|
||||||
|
|
||||||
StringTableEntry cloakTexName;
|
StringTableEntry cloakTexName;
|
||||||
|
|
||||||
|
|
@ -572,7 +572,7 @@ public:
|
||||||
DebrisData * debris;
|
DebrisData * debris;
|
||||||
S32 debrisID;
|
S32 debrisID;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(ShapeBaseData, DebrisShape)
|
AssetRef<ShapeAsset> debrisShapeAssetRef;
|
||||||
|
|
||||||
ExplosionData* explosion;
|
ExplosionData* explosion;
|
||||||
S32 explosionID;
|
S32 explosionID;
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ ShapeBaseImageData::ShapeBaseImageData()
|
||||||
isAnimated[i] = false;
|
isAnimated[i] = false;
|
||||||
hasFlash[i] = false;
|
hasFlash[i] = false;
|
||||||
shapeIsValid[i] = false;
|
shapeIsValid[i] = false;
|
||||||
mShapeAsset[i].registerRefreshNotify(this);
|
shapeAssetRef[i].assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
shakeCamera = false;
|
shakeCamera = false;
|
||||||
|
|
@ -439,7 +439,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
||||||
|
|
||||||
if (i == FirstPersonImageShape)
|
if (i == FirstPersonImageShape)
|
||||||
{
|
{
|
||||||
if ((useEyeOffset || useEyeNode) && !mShapeAsset[i].isNull())
|
if ((useEyeOffset || useEyeNode) && !shapeAssetRef[i].isNull())
|
||||||
{
|
{
|
||||||
// Make use of the first person shape
|
// Make use of the first person shape
|
||||||
useFirstPersonShape = true;
|
useFirstPersonShape = true;
|
||||||
|
|
@ -451,21 +451,22 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mShapeAsset[i].isNull())
|
if (shapeAssetRef[i].notNull())
|
||||||
{
|
{
|
||||||
if (!bool(getShape(i))) {
|
Resource<TSShape> shape = shapeAssetRef[i].assetPtr->getShapeResource();
|
||||||
errorStr = String::ToString("Unable to load shape asset: %s", mShapeAsset[i]->getAssetId());
|
if (!shape) {
|
||||||
|
errorStr = String::ToString("ShapeBaseImageData(%s)::preload: Couldn't to load shape asset: %s", getName(), shapeAssetRef[i].assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(computeCRC)
|
if(computeCRC)
|
||||||
{
|
{
|
||||||
Con::printf("Validation required for shape asset: %s", mShapeAsset[i]->getAssetId());
|
Con::printf("ShapeBaseImageData(%s)::preload: Validation required for shape asset: %s", getName(), shapeAssetRef[i].assetId);
|
||||||
|
|
||||||
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(getShapeFile(i));
|
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(shapeAssetRef[i].assetPtr->getShapeFile());
|
||||||
|
|
||||||
if (!fileRef)
|
if (!fileRef)
|
||||||
{
|
{
|
||||||
errorStr = String::ToString("ShapeBaseImageData: Couldn't load shape asset\"%s\"", mShapeAsset[i]->getAssetId());
|
errorStr = String::ToString("ShapeBaseImageData(%s)::preload: Couldn't find shape asset \"%s\"'s file", getName(), shapeAssetRef[i].assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -475,29 +476,29 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
||||||
}
|
}
|
||||||
else if(mCRC[i] != fileRef->getChecksum())
|
else if(mCRC[i] != fileRef->getChecksum())
|
||||||
{
|
{
|
||||||
errorStr = String::ToString("Shape asset\"%s\" does not match version on server.", mShapeAsset[i]->getAssetId());
|
errorStr = String::ToString("ShapeBaseImageData(%s)::preload: Shape asset\"%s\" does not match version on server.", getName(), shapeAssetRef[i].assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve nodes & build mount transform
|
// Resolve nodes & build mount transform
|
||||||
eyeMountNode[i] = getShape(i)->findNode("eyeMount");
|
eyeMountNode[i] = shape->findNode("eyeMount");
|
||||||
eyeNode[i] = getShape(i)->findNode("eye");
|
eyeNode[i] = shape->findNode("eye");
|
||||||
if (eyeNode[i] == -1)
|
if (eyeNode[i] == -1)
|
||||||
eyeNode[i] = eyeMountNode[i];
|
eyeNode[i] = eyeMountNode[i];
|
||||||
ejectNode[i] = getShape(i)->findNode("ejectPoint");
|
ejectNode[i] = shape->findNode("ejectPoint");
|
||||||
muzzleNode[i] = getShape(i)->findNode("muzzlePoint");
|
muzzleNode[i] = shape->findNode("muzzlePoint");
|
||||||
retractNode[i] = getShape(i)->findNode("retractionPoint");
|
retractNode[i] = shape->findNode("retractionPoint");
|
||||||
mountTransform[i] = mountOffset;
|
mountTransform[i] = mountOffset;
|
||||||
S32 node = getShape(i)->findNode("mountPoint");
|
S32 node = shape->findNode("mountPoint");
|
||||||
if (node != -1) {
|
if (node != -1) {
|
||||||
MatrixF total(1);
|
MatrixF total(1);
|
||||||
do {
|
do {
|
||||||
MatrixF nmat;
|
MatrixF nmat;
|
||||||
QuatF q;
|
QuatF q;
|
||||||
TSTransform::setMatrix(getShape(i)->defaultRotations[node].getQuatF(&q), getShape(i)->defaultTranslations[node],&nmat);
|
TSTransform::setMatrix(shape->defaultRotations[node].getQuatF(&q), shape->defaultTranslations[node],&nmat);
|
||||||
total.mul(nmat);
|
total.mul(nmat);
|
||||||
node = getShape(i)->nodes[node].parentIndex;
|
node = shape->nodes[node].parentIndex;
|
||||||
}
|
}
|
||||||
while(node != -1);
|
while(node != -1);
|
||||||
total.inverse();
|
total.inverse();
|
||||||
|
|
@ -510,7 +511,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
||||||
for (U32 j = 0; j < MaxStates; j++) {
|
for (U32 j = 0; j < MaxStates; j++) {
|
||||||
StateData& s = state[j];
|
StateData& s = state[j];
|
||||||
if (stateSequence[j] && stateSequence[j][0])
|
if (stateSequence[j] && stateSequence[j][0])
|
||||||
s.sequence[i] = getShape(i)->findSequence(stateSequence[j]);
|
s.sequence[i] = shape->findSequence(stateSequence[j]);
|
||||||
if (s.sequence[i] != -1)
|
if (s.sequence[i] != -1)
|
||||||
{
|
{
|
||||||
// This state has an animation sequence
|
// This state has an animation sequence
|
||||||
|
|
@ -521,7 +522,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
||||||
char bufferVis[128];
|
char bufferVis[128];
|
||||||
dStrncpy(bufferVis, stateSequence[j], 100);
|
dStrncpy(bufferVis, stateSequence[j], 100);
|
||||||
dStrcat(bufferVis, "_vis", 128);
|
dStrcat(bufferVis, "_vis", 128);
|
||||||
s.sequenceVis[i] = getShape(i)->findSequence(bufferVis);
|
s.sequenceVis[i] = shape->findSequence(bufferVis);
|
||||||
}
|
}
|
||||||
if (s.sequenceVis[i] != -1)
|
if (s.sequenceVis[i] != -1)
|
||||||
{
|
{
|
||||||
|
|
@ -533,13 +534,13 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
||||||
s.ignoreLoadedForReady = stateIgnoreLoadedForReady[j];
|
s.ignoreLoadedForReady = stateIgnoreLoadedForReady[j];
|
||||||
|
|
||||||
if (stateEmitterNode[j] && stateEmitterNode[j][0])
|
if (stateEmitterNode[j] && stateEmitterNode[j][0])
|
||||||
s.emitterNode[i] = getShape(i)->findNode(stateEmitterNode[j]);
|
s.emitterNode[i] = shape->findNode(stateEmitterNode[j]);
|
||||||
if (s.emitterNode[i] == -1)
|
if (s.emitterNode[i] == -1)
|
||||||
s.emitterNode[i] = muzzleNode[i];
|
s.emitterNode[i] = muzzleNode[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ambientSequence[i] = getShape(i)->findSequence("ambient");
|
ambientSequence[i] = shape->findSequence("ambient");
|
||||||
spinSequence[i] = getShape(i)->findSequence("spin");
|
spinSequence[i] = shape->findSequence("spin");
|
||||||
|
|
||||||
shapeIsValid[i] = true;
|
shapeIsValid[i] = true;
|
||||||
}
|
}
|
||||||
|
|
@ -564,7 +565,9 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
||||||
{
|
{
|
||||||
if( shapeIsValid[i] )
|
if( shapeIsValid[i] )
|
||||||
{
|
{
|
||||||
TSShapeInstance* pDummy = new TSShapeInstance(getShape(i), !server);
|
Resource<TSShape> shape = shapeAssetRef[i].assetPtr->getShapeResource();
|
||||||
|
|
||||||
|
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||||
delete pDummy;
|
delete pDummy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -625,7 +628,9 @@ void ShapeBaseImageData::initPersistFields()
|
||||||
{
|
{
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup("Shapes");
|
addGroup("Shapes");
|
||||||
INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(Shape, MaxShapes, ShapeBaseImageData, "The shape assets for this shape image")
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, ShapeBaseImageData))
|
||||||
|
.doc("The shape assets for this shape image")
|
||||||
|
.elements(MaxShapes);
|
||||||
|
|
||||||
addField("casing", TYPEID< DebrisData >(), Offset(casing, ShapeBaseImageData),
|
addField("casing", TYPEID< DebrisData >(), Offset(casing, ShapeBaseImageData),
|
||||||
"@brief DebrisData datablock to use for ejected casings.\n\n"
|
"@brief DebrisData datablock to use for ejected casings.\n\n"
|
||||||
|
|
@ -999,7 +1004,10 @@ void ShapeBaseImageData::packData(BitStream* stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PACKDATA_ASSET_ARRAY_REFACTOR(Shape, MaxShapes); // shape 0 for normal use, shape 1 for first person use (optional)
|
for (U32 j = 0; j < MaxShapes; ++j)
|
||||||
|
{
|
||||||
|
AssetDatabase.packDataAsset(stream, shapeAssetRef[j].assetId); // shape 0 for normal use, shape 1 for first person use (optional)
|
||||||
|
}
|
||||||
|
|
||||||
stream->writeString(imageAnimPrefix);
|
stream->writeString(imageAnimPrefix);
|
||||||
stream->writeString(imageAnimPrefixFP);
|
stream->writeString(imageAnimPrefixFP);
|
||||||
|
|
@ -1180,7 +1188,10 @@ void ShapeBaseImageData::unpackData(BitStream* stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UNPACKDATA_ASSET_ARRAY_REFACTOR(Shape, MaxShapes); // shape 0 for normal use, shape 1 for first person use (optional)
|
for (U32 j = 0; j < MaxShapes; ++j)
|
||||||
|
{
|
||||||
|
shapeAssetRef[j] = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
}
|
||||||
|
|
||||||
imageAnimPrefix = stream->readSTString();
|
imageAnimPrefix = stream->readSTString();
|
||||||
imageAnimPrefixFP = stream->readSTString();
|
imageAnimPrefixFP = stream->readSTString();
|
||||||
|
|
@ -2139,9 +2150,17 @@ S32 ShapeBase::getNodeIndex(U32 imageSlot,StringTableEntry nodeName)
|
||||||
{
|
{
|
||||||
MountedImage& image = mMountedImageList[imageSlot];
|
MountedImage& image = mMountedImageList[imageSlot];
|
||||||
if (image.dataBlock)
|
if (image.dataBlock)
|
||||||
return image.dataBlock->getShape(getImageShapeIndex(image))->findNode(nodeName);
|
{
|
||||||
else
|
U32 imageShapeidx = getImageShapeIndex(image);
|
||||||
return -1;
|
if (image.dataBlock->shapeAssetRef[imageShapeidx].notNull())
|
||||||
|
{
|
||||||
|
Resource<TSShape> shape = image.dataBlock->shapeAssetRef[imageShapeidx].assetPtr->getShapeResource();
|
||||||
|
if (shape)
|
||||||
|
return shape->findNode(nodeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify muzzle if needed to aim at whatever is straight in front of the camera. Let the
|
// Modify muzzle if needed to aim at whatever is straight in front of the camera. Let the
|
||||||
|
|
@ -2329,7 +2348,10 @@ void ShapeBase::setImage( U32 imageSlot,
|
||||||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
||||||
{
|
{
|
||||||
if (image.dataBlock->shapeIsValid[i])
|
if (image.dataBlock->shapeIsValid[i])
|
||||||
image.shapeInstance[i] = new TSShapeInstance(image.dataBlock->getShape(i), isClientObject());
|
{
|
||||||
|
Resource<TSShape> shape = image.dataBlock->shapeAssetRef[i].assetPtr->getShapeResource();
|
||||||
|
image.shapeInstance[i] = new TSShapeInstance(shape, isClientObject());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isClientObject())
|
if (isClientObject())
|
||||||
|
|
|
||||||
|
|
@ -152,14 +152,14 @@ TSStatic::TSStatic()
|
||||||
mAnimOffset = 0.0f;
|
mAnimOffset = 0.0f;
|
||||||
mAnimSpeed = 1.0f;
|
mAnimSpeed = 1.0f;
|
||||||
|
|
||||||
mShapeAsset.registerRefreshNotify(this);
|
mShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSStatic::~TSStatic()
|
TSStatic::~TSStatic()
|
||||||
{
|
{
|
||||||
delete mConvexList;
|
delete mConvexList;
|
||||||
mConvexList = NULL;
|
mConvexList = NULL;
|
||||||
mShapeAsset.unregisterRefreshNotify();
|
|
||||||
if (mCubeReflector)
|
if (mCubeReflector)
|
||||||
{
|
{
|
||||||
mCubeReflector->unregisterReflector();
|
mCubeReflector->unregisterReflector();
|
||||||
|
|
@ -187,7 +187,9 @@ void TSStatic::initPersistFields()
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup("Shape");
|
addGroup("Shape");
|
||||||
|
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, TSStatic, "Model to use for this TSStatic");
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(mShapeAssetRef, TSStatic))
|
||||||
|
.doc("Model to use for this TSStatic")
|
||||||
|
.network(AdvancedStaticOptionsMask);
|
||||||
|
|
||||||
endGroup("Shape");
|
endGroup("Shape");
|
||||||
|
|
||||||
|
|
@ -403,17 +405,26 @@ bool TSStatic::_createShape()
|
||||||
mAmbientThread = NULL;
|
mAmbientThread = NULL;
|
||||||
//mShape = NULL;
|
//mShape = NULL;
|
||||||
|
|
||||||
if (getShape())
|
if (mShapeAssetRef.assetId == StringTable->EmptyString())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Resource<TSShape> shape;
|
||||||
|
if (!mShapeAssetRef.assetPtr.isValid())
|
||||||
|
shape = ShapeAsset::smNoShapeAssetFallbackAssetPtr->getShapeResource();
|
||||||
|
else
|
||||||
|
shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
|
if (shape)
|
||||||
{
|
{
|
||||||
if (isClientObject() &&
|
if (isClientObject() &&
|
||||||
!getShape()->preloadMaterialList(getShapeFile()) &&
|
!mShapeAssetRef.assetPtr->preloadMaterialList() &&
|
||||||
NetConnection::filesWereDownloaded())
|
NetConnection::filesWereDownloaded())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mObjBox = getShape()->mBounds;
|
mObjBox = shape->mBounds;
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
|
|
||||||
mShapeInstance = new TSShapeInstance(getShape(), true);
|
mShapeInstance = new TSShapeInstance(shape, true);
|
||||||
mShapeInstance->resetMaterialList();
|
mShapeInstance->resetMaterialList();
|
||||||
mShapeInstance->cloneMaterialList();
|
mShapeInstance->cloneMaterialList();
|
||||||
|
|
||||||
|
|
@ -429,7 +440,7 @@ bool TSStatic::_createShape()
|
||||||
prepCollision();
|
prepCollision();
|
||||||
|
|
||||||
// Find the "ambient" animation if it exists
|
// Find the "ambient" animation if it exists
|
||||||
S32 ambientSeq = getShape()->findSequence("ambient");
|
S32 ambientSeq = shape->findSequence("ambient");
|
||||||
|
|
||||||
if (ambientSeq > -1 && !mAmbientThread)
|
if (ambientSeq > -1 && !mAmbientThread)
|
||||||
mAmbientThread = mShapeInstance->addThread();
|
mAmbientThread = mShapeInstance->addThread();
|
||||||
|
|
@ -449,77 +460,13 @@ bool TSStatic::_createShape()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Con::errorf("TSStatic::_createShape() - Shape Asset %s had no valid shape!", mShapeAsset.getAssetId());
|
Con::errorf("TSStatic::_createShape() - Shape Asset %s had no valid shape!", mShapeAssetRef.assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set up the material slot vars for easy manipulation
|
|
||||||
/*S32 materialCount = mShape->materialList->getMaterialNameList().size(); //mMeshAsset->getMaterialCount();
|
|
||||||
|
|
||||||
//Temporarily disabled until fixup of materialName->assetId lookup logic is sorted for easy persistance
|
|
||||||
if (isServerObject())
|
|
||||||
{
|
|
||||||
char matFieldName[128];
|
|
||||||
|
|
||||||
for (U32 i = 0; i < materialCount; i++)
|
|
||||||
{
|
|
||||||
StringTableEntry materialname = StringTable->insert(mShape->materialList->getMaterialName(i).c_str());
|
|
||||||
|
|
||||||
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
|
|
||||||
StringTableEntry matFld = StringTable->insert(matFieldName);
|
|
||||||
|
|
||||||
setDataField(matFld, NULL, materialname);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSStatic::onDynamicModified(const char* slotName, const char* newValue)
|
|
||||||
{
|
|
||||||
if (FindMatch::isMatch("materialslot*", slotName, false))
|
|
||||||
{
|
|
||||||
if (!getShape())
|
|
||||||
return;
|
|
||||||
|
|
||||||
S32 slot = -1;
|
|
||||||
String outStr(String::GetTrailingNumber(slotName, slot));
|
|
||||||
|
|
||||||
if (slot == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//Safe to assume the inbound value for the material will be a MaterialAsset, so lets do a lookup on the name
|
|
||||||
MaterialAsset* matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newValue);
|
|
||||||
if (!matAsset)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
for (U32 i = 0; i < mChangingMaterials.size(); i++)
|
|
||||||
{
|
|
||||||
if (mChangingMaterials[i].slot == slot)
|
|
||||||
{
|
|
||||||
mChangingMaterials[i].matAsset = matAsset;
|
|
||||||
mChangingMaterials[i].assetId = newValue;
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
matMap newMatMap;
|
|
||||||
newMatMap.slot = slot;
|
|
||||||
newMatMap.matAsset = matAsset;
|
|
||||||
newMatMap.assetId = newValue;
|
|
||||||
|
|
||||||
mChangingMaterials.push_back(newMatMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
setMaskBits(MaterialMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
Parent::onDynamicModified(slotName, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TSStatic::prepCollision()
|
void TSStatic::prepCollision()
|
||||||
{
|
{
|
||||||
// Let the client know that the collision was updated
|
// Let the client know that the collision was updated
|
||||||
|
|
@ -536,22 +483,24 @@ void TSStatic::prepCollision()
|
||||||
mLOSDetails.clear();
|
mLOSDetails.clear();
|
||||||
mConvexList->nukeList();
|
mConvexList->nukeList();
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
if (mCollisionType == CollisionMesh || mCollisionType == VisibleMesh)
|
if (mCollisionType == CollisionMesh || mCollisionType == VisibleMesh)
|
||||||
{
|
{
|
||||||
getShape()->findColDetails(mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails, mCollisionLOD);
|
shape->findColDetails(mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails, mCollisionLOD);
|
||||||
if (mDecalType == mCollisionType)
|
if (mDecalType == mCollisionType)
|
||||||
{
|
{
|
||||||
mDecalDetailsPtr = &mCollisionDetails;
|
mDecalDetailsPtr = &mCollisionDetails;
|
||||||
}
|
}
|
||||||
else if (mDecalType == CollisionMesh || mDecalType == VisibleMesh)
|
else if (mDecalType == CollisionMesh || mDecalType == VisibleMesh)
|
||||||
{
|
{
|
||||||
getShape()->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD);
|
shape->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD);
|
||||||
mDecalDetailsPtr = &mDecalDetails;
|
mDecalDetailsPtr = &mDecalDetails;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mDecalType == CollisionMesh || mDecalType == VisibleMesh)
|
else if (mDecalType == CollisionMesh || mDecalType == VisibleMesh)
|
||||||
{
|
{
|
||||||
getShape()->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD);
|
shape->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD);
|
||||||
mDecalDetailsPtr = &mDecalDetails;
|
mDecalDetailsPtr = &mDecalDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -565,16 +514,18 @@ void TSStatic::_updatePhysics()
|
||||||
if (!PHYSICSMGR || mCollisionType == None)
|
if (!PHYSICSMGR || mCollisionType == None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
PhysicsCollision* colShape = NULL;
|
PhysicsCollision* colShape = NULL;
|
||||||
if (mCollisionType == Bounds)
|
if (mCollisionType == Bounds)
|
||||||
{
|
{
|
||||||
MatrixF offset(true);
|
MatrixF offset(true);
|
||||||
offset.setPosition(getShape()->center);
|
offset.setPosition(shape->center);
|
||||||
colShape = PHYSICSMGR->createCollision();
|
colShape = PHYSICSMGR->createCollision();
|
||||||
colShape->addBox(getObjBox().getExtents() * 0.5f * mObjScale, offset);
|
colShape->addBox(getObjBox().getExtents() * 0.5f * mObjScale, offset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
colShape = getShape()->buildColShape(mCollisionType == VisibleMesh, getScale());
|
colShape = shape->buildColShape(mCollisionType == VisibleMesh, getScale());
|
||||||
|
|
||||||
if (colShape)
|
if (colShape)
|
||||||
{
|
{
|
||||||
|
|
@ -727,7 +678,7 @@ void TSStatic::_updateShouldTick()
|
||||||
|
|
||||||
void TSStatic::prepRenderImage(SceneRenderState* state)
|
void TSStatic::prepRenderImage(SceneRenderState* state)
|
||||||
{
|
{
|
||||||
if (!mShapeAsset.isValid() || !mShapeInstance)
|
if (!mShapeAssetRef.isValid() || !mShapeInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Point3F cameraOffset;
|
Point3F cameraOffset;
|
||||||
|
|
@ -967,7 +918,7 @@ U32 TSStatic::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
||||||
|
|
||||||
if (stream->writeFlag(mask & AdvancedStaticOptionsMask))
|
if (stream->writeFlag(mask & AdvancedStaticOptionsMask))
|
||||||
{
|
{
|
||||||
PACK_ASSET_REFACTOR(con, Shape);
|
AssetDatabase.packUpdateAsset(con, mask, stream, mShapeAssetRef.assetId);
|
||||||
|
|
||||||
stream->writeInt(mDecalType,4);
|
stream->writeInt(mDecalType,4);
|
||||||
|
|
||||||
|
|
@ -1086,7 +1037,7 @@ void TSStatic::unpackUpdate(NetConnection* con, BitStream* stream)
|
||||||
|
|
||||||
if (stream->readFlag()) // AdvancedStaticOptionsMask
|
if (stream->readFlag()) // AdvancedStaticOptionsMask
|
||||||
{
|
{
|
||||||
UNPACK_ASSET_REFACTOR(con, Shape);
|
mShapeAssetRef = AssetDatabase.unpackUpdateAsset(con, stream);
|
||||||
|
|
||||||
mDecalType = (MeshType)stream->readInt(4);
|
mDecalType = (MeshType)stream->readInt(4);
|
||||||
|
|
||||||
|
|
@ -1611,10 +1562,10 @@ void TSStatic::updateMaterials()
|
||||||
TSMaterialList* pMatList = mShapeInstance->getMaterialList();
|
TSMaterialList* pMatList = mShapeInstance->getMaterialList();
|
||||||
|
|
||||||
String path;
|
String path;
|
||||||
if (mShapeAsset->isAssetValid())
|
if (mShapeAssetRef.assetPtr->isAssetValid())
|
||||||
path = mShapeAsset->getShapeFile();
|
path = mShapeAssetRef.assetPtr->getShapeFile();
|
||||||
else
|
else
|
||||||
path = mShapeFile;
|
return;
|
||||||
|
|
||||||
pMatList->setTextureLookupPath(path);
|
pMatList->setTextureLookupPath(path);
|
||||||
|
|
||||||
|
|
@ -1643,10 +1594,10 @@ void TSStatic::updateMaterials()
|
||||||
|
|
||||||
void TSStatic::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
|
void TSStatic::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
|
||||||
{
|
{
|
||||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
|
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAssetRef.assetPtr);
|
||||||
if (assetStatus == AssetBase::Ok)
|
if (assetStatus == AssetBase::Ok)
|
||||||
{
|
{
|
||||||
usedAssetsList->push_back_unique(mShapeAsset->getAssetId());
|
usedAssetsList->push_back_unique(mShapeAssetRef.assetId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1796,7 +1747,16 @@ DefineEngineMethod(TSStatic, changeMaterial, void, (const char* mapTo, Material*
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TSMaterialList* shapeMaterialList = object->getShape()->materialList;
|
const AssetPtr<ShapeAsset> shapeAsset = object->getShapeAsset();
|
||||||
|
|
||||||
|
if (shapeAsset.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = shapeAsset->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TSMaterialList* shapeMaterialList = shape->materialList;
|
||||||
|
|
||||||
// Check the mapTo name exists for this shape
|
// Check the mapTo name exists for this shape
|
||||||
S32 matIndex = shapeMaterialList->getMaterialNameList().find_next(String(mapTo));
|
S32 matIndex = shapeMaterialList->getMaterialNameList().find_next(String(mapTo));
|
||||||
|
|
@ -1836,7 +1796,11 @@ DefineEngineMethod(TSStatic, getModelFile, const char*, (), ,
|
||||||
"@endtsexample\n"
|
"@endtsexample\n"
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return object->getShapeFile();
|
const AssetPtr<ShapeAsset> shapeAsset = object->getShapeAsset();
|
||||||
|
if (shapeAsset.isNull())
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return shapeAsset->getShapeFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSStatic::set_special_typing()
|
void TSStatic::set_special_typing()
|
||||||
|
|
@ -1880,15 +1844,27 @@ void TSStatic::setSelectionFlags(U8 flags)
|
||||||
|
|
||||||
bool TSStatic::hasNode(const char* nodeName)
|
bool TSStatic::hasNode(const char* nodeName)
|
||||||
{
|
{
|
||||||
|
if (mShapeAssetRef.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
S32 nodeIDx = getShape()->findNode(nodeName);
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
S32 nodeIDx = shape->findNode(nodeName);
|
||||||
return nodeIDx >= 0;
|
return nodeIDx >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSStatic::getNodeTransform(const char *nodeName, const MatrixF &xfm, MatrixF *outMat)
|
void TSStatic::getNodeTransform(const char *nodeName, const MatrixF &xfm, MatrixF *outMat)
|
||||||
{
|
{
|
||||||
|
if (mShapeAssetRef.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
S32 nodeIDx = getShape()->findNode(nodeName);
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return;
|
||||||
|
|
||||||
|
S32 nodeIDx = shape->findNode(nodeName);
|
||||||
|
|
||||||
MatrixF nodeTransform(xfm);
|
MatrixF nodeTransform(xfm);
|
||||||
const Point3F& scale = getScale();
|
const Point3F& scale = getScale();
|
||||||
|
|
|
||||||
|
|
@ -176,8 +176,6 @@ protected:
|
||||||
void interpolateTick(F32 delta) override;
|
void interpolateTick(F32 delta) override;
|
||||||
void advanceTime(F32 dt) override;
|
void advanceTime(F32 dt) override;
|
||||||
|
|
||||||
void onDynamicModified(const char* slotName, const char* newValue) override;
|
|
||||||
|
|
||||||
/// Start or stop processing ticks depending on our state.
|
/// Start or stop processing ticks depending on our state.
|
||||||
void _updateShouldTick();
|
void _updateShouldTick();
|
||||||
|
|
||||||
|
|
@ -196,7 +194,7 @@ protected:
|
||||||
|
|
||||||
Convex* mConvexList;
|
Convex* mConvexList;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_NET_REFACTOR(TSStatic, Shape, AdvancedStaticOptionsMask)
|
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||||
|
|
||||||
U32 mShapeHash;
|
U32 mShapeHash;
|
||||||
Vector<S32> mCollisionDetails;
|
Vector<S32> mCollisionDetails;
|
||||||
|
|
@ -244,7 +242,7 @@ public:
|
||||||
DECLARE_CATEGORY("Object \t Simple");
|
DECLARE_CATEGORY("Object \t Simple");
|
||||||
static void initPersistFields();
|
static void initPersistFields();
|
||||||
/// returns the shape asset used for this object
|
/// returns the shape asset used for this object
|
||||||
StringTableEntry getTypeHint() const override { return (mShapeAsset.notNull()) ? mShapeAsset->getAssetName(): StringTable->EmptyString(); }
|
StringTableEntry getTypeHint() const override { return (mShapeAssetRef.notNull()) ? mShapeAssetRef.assetPtr->getAssetName(): StringTable->EmptyString(); }
|
||||||
static void consoleInit();
|
static void consoleInit();
|
||||||
static bool _setFieldSkin(void* object, const char* index, const char* data);
|
static bool _setFieldSkin(void* object, const char* index, const char* data);
|
||||||
static const char* _getFieldSkin(void* object, const char* data);
|
static const char* _getFieldSkin(void* object, const char* data);
|
||||||
|
|
@ -289,6 +287,8 @@ public:
|
||||||
|
|
||||||
void getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList) override;
|
void getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList) override;
|
||||||
|
|
||||||
|
const AssetPtr<ShapeAsset>& getShapeAsset() const { return mShapeAssetRef.assetPtr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onStaticModified(const char* slotName, const char* newValue = NULL) override;
|
void onStaticModified(const char* slotName, const char* newValue = NULL) override;
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -245,9 +245,11 @@ bool AITurretShapeData::preload(bool server, String &errorStr)
|
||||||
if (!Parent::preload(server, errorStr))
|
if (!Parent::preload(server, errorStr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
// We have mShape at this point. Resolve nodes.
|
// We have mShape at this point. Resolve nodes.
|
||||||
scanNode = getShape()->findNode("scanPoint");
|
scanNode = shape->findNode("scanPoint");
|
||||||
aimNode = getShape()->findNode("aimPoint");
|
aimNode = shape->findNode("aimPoint");
|
||||||
|
|
||||||
if (scanNode == -1) scanNode = pitchNode;
|
if (scanNode == -1) scanNode = pitchNode;
|
||||||
if (scanNode == -1) scanNode = headingNode;
|
if (scanNode == -1) scanNode = headingNode;
|
||||||
|
|
@ -259,7 +261,7 @@ bool AITurretShapeData::preload(bool server, String &errorStr)
|
||||||
for (U32 j = 0; j < MaxStates; j++) {
|
for (U32 j = 0; j < MaxStates; j++) {
|
||||||
StateData& s = state[j];
|
StateData& s = state[j];
|
||||||
if (stateSequence[j] && stateSequence[j][0])
|
if (stateSequence[j] && stateSequence[j][0])
|
||||||
s.sequence = getShape()->findSequence(stateSequence[j]);
|
s.sequence = shape->findSequence(stateSequence[j]);
|
||||||
if (s.sequence != -1)
|
if (s.sequence != -1)
|
||||||
{
|
{
|
||||||
// This state has an animation sequence
|
// This state has an animation sequence
|
||||||
|
|
|
||||||
|
|
@ -216,36 +216,43 @@ bool TurretShapeData::preload(bool server, String &errorStr)
|
||||||
if (!Parent::preload(server, errorStr))
|
if (!Parent::preload(server, errorStr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (shapeAssetRef.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
return false;
|
||||||
|
|
||||||
// We have mShape at this point. Resolve nodes.
|
// We have mShape at this point. Resolve nodes.
|
||||||
headingNode = getShape()->findNode("heading");
|
headingNode = shape->findNode("heading");
|
||||||
pitchNode = getShape()->findNode("pitch");
|
pitchNode = shape->findNode("pitch");
|
||||||
|
|
||||||
// Find any mirror pitch nodes
|
// Find any mirror pitch nodes
|
||||||
for (U32 i = 0; i < NumMirrorDirectionNodes; ++i)
|
for (U32 i = 0; i < NumMirrorDirectionNodes; ++i)
|
||||||
{
|
{
|
||||||
char name[32];
|
char name[32];
|
||||||
dSprintf(name, 31, "pitch%d", i+1);
|
dSprintf(name, 31, "pitch%d", i+1);
|
||||||
pitchNodes[i] = getShape()->findNode(name);
|
pitchNodes[i] = shape->findNode(name);
|
||||||
|
|
||||||
dSprintf(name, 31, "heading%d", i+1);
|
dSprintf(name, 31, "heading%d", i+1);
|
||||||
headingNodes[i] = getShape()->findNode(name);
|
headingNodes[i] = shape->findNode(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve weapon mount point node indexes
|
// Resolve weapon mount point node indexes
|
||||||
for (U32 i = 0; i < ShapeBase::MaxMountedImages; i++) {
|
for (U32 i = 0; i < ShapeBase::MaxMountedImages; i++) {
|
||||||
char fullName[256];
|
char fullName[256];
|
||||||
dSprintf(fullName,sizeof(fullName),"weaponMount%d",i);
|
dSprintf(fullName,sizeof(fullName),"weaponMount%d",i);
|
||||||
weaponMountNode[i] = getShape()->findNode(fullName);
|
weaponMountNode[i] = shape->findNode(fullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recoil animations
|
// Recoil animations
|
||||||
recoilSequence[0] = getShape()->findSequence("light_recoil");
|
recoilSequence[0] = shape->findSequence("light_recoil");
|
||||||
recoilSequence[1] = getShape()->findSequence("medium_recoil");
|
recoilSequence[1] = shape->findSequence("medium_recoil");
|
||||||
recoilSequence[2] = getShape()->findSequence("heavy_recoil");
|
recoilSequence[2] = shape->findSequence("heavy_recoil");
|
||||||
|
|
||||||
// Optional sequences used when the turret rotates
|
// Optional sequences used when the turret rotates
|
||||||
pitchSequence = getShape()->findSequence("pitch");
|
pitchSequence = shape->findSequence("pitch");
|
||||||
headingSequence = getShape()->findSequence("heading");
|
headingSequence = shape->findSequence("heading");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,9 @@ bool FlyingVehicleData::preload(bool server, String &errorStr)
|
||||||
if (!Parent::preload(server, errorStr))
|
if (!Parent::preload(server, errorStr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
TSShapeInstance* si = new TSShapeInstance(getShape(), false);
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
|
TSShapeInstance* si = new TSShapeInstance(shape, false);
|
||||||
|
|
||||||
// Resolve objects transmitted from server
|
// Resolve objects transmitted from server
|
||||||
if (!server) {
|
if (!server) {
|
||||||
|
|
@ -165,7 +167,7 @@ bool FlyingVehicleData::preload(bool server, String &errorStr)
|
||||||
|
|
||||||
// Resolve jet nodes
|
// Resolve jet nodes
|
||||||
for (S32 j = 0; j < MaxJetNodes; j++)
|
for (S32 j = 0; j < MaxJetNodes; j++)
|
||||||
jetNode[j] = getShape()->findNode(sJetNode[j]);
|
jetNode[j] = shape->findNode(sJetNode[j]);
|
||||||
|
|
||||||
//
|
//
|
||||||
maxSpeed = maneuveringForce / minDrag;
|
maxSpeed = maneuveringForce / minDrag;
|
||||||
|
|
|
||||||
|
|
@ -332,9 +332,12 @@ bool HoverVehicleData::preload(bool server, String &errorStr)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
// Resolve jet nodes
|
// Resolve jet nodes
|
||||||
for (S32 j = 0; j < MaxJetNodes; j++)
|
for (S32 j = 0; j < MaxJetNodes; j++)
|
||||||
jetNode[j] = getShape()->findNode(sJetNode[j]);
|
jetNode[j] = shape->findNode(sJetNode[j]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ bool VehicleData::preload(bool server, String &errorStr)
|
||||||
if (!collisionDetails.size() || collisionDetails[0] == -1)
|
if (!collisionDetails.size() || collisionDetails[0] == -1)
|
||||||
{
|
{
|
||||||
Con::errorf("VehicleData::preload failed: Vehicle models must define a collision-1 detail");
|
Con::errorf("VehicleData::preload failed: Vehicle models must define a collision-1 detail");
|
||||||
errorStr = String::ToString("VehicleData: Couldn't load shape asset \"%s\"", getShapeAsset().getAssetId());
|
errorStr = String::ToString("VehicleData: Couldn't load shape asset \"%s\"", shapeAssetRef.assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,24 +86,28 @@ WheeledVehicleTire::WheeledVehicleTire()
|
||||||
longitudinalDamping = 1;
|
longitudinalDamping = 1;
|
||||||
longitudinalRelaxation = 1;
|
longitudinalRelaxation = 1;
|
||||||
mass = 1.f;
|
mass = 1.f;
|
||||||
mShapeAsset.registerRefreshNotify(this);
|
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WheeledVehicleTire::preload(bool server, String &errorStr)
|
bool WheeledVehicleTire::preload(bool server, String &errorStr)
|
||||||
{
|
{
|
||||||
// Load up the tire shape. ShapeBase has an option to force a
|
// Load up the tire shape. ShapeBase has an option to force a
|
||||||
// CRC check, this is left out here, but could be easily added.
|
// CRC check, this is left out here, but could be easily added.
|
||||||
if (!getShape())
|
if (!shapeAssetRef.isNull())
|
||||||
{
|
{
|
||||||
errorStr = String::ToString("WheeledVehicleTire: Couldn't load shape \"%s\"", _getShapeAssetId());
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
return false;
|
if (shape)
|
||||||
}
|
{
|
||||||
else
|
// Determinw wheel radius from the shape's bounding box.
|
||||||
{
|
|
||||||
// Determinw wheel radius from the shape's bounding box.
|
|
||||||
// The tire should be built with it's hub axis along the
|
// The tire should be built with it's hub axis along the
|
||||||
// object's Y axis.
|
// object's Y axis.
|
||||||
radius = getShape()->mBounds.len_z() / 2;
|
radius = shape->mBounds.len_z() / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorStr = String::ToString("WheeledVehicleTire::preload Couldn't load shape \"%s\"", shapeAssetRef.assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -112,7 +116,8 @@ bool WheeledVehicleTire::preload(bool server, String &errorStr)
|
||||||
void WheeledVehicleTire::initPersistFields()
|
void WheeledVehicleTire::initPersistFields()
|
||||||
{
|
{
|
||||||
docsURL;
|
docsURL;
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, WheeledVehicleTire, "The shape to use for the wheel.");
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, WheeledVehicleTire))
|
||||||
|
.doc("The shape to use for the wheel.");
|
||||||
|
|
||||||
addFieldV( "mass", TypeRangedF32, Offset(mass, WheeledVehicleTire), &CommonValidators::PositiveFloat,
|
addFieldV( "mass", TypeRangedF32, Offset(mass, WheeledVehicleTire), &CommonValidators::PositiveFloat,
|
||||||
"The mass of the wheel.\nCurrently unused." );
|
"The mass of the wheel.\nCurrently unused." );
|
||||||
|
|
@ -177,7 +182,7 @@ void WheeledVehicleTire::packData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::packData(stream);
|
Parent::packData(stream);
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(Shape);
|
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||||
|
|
||||||
stream->write(mass);
|
stream->write(mass);
|
||||||
stream->write(staticFriction);
|
stream->write(staticFriction);
|
||||||
|
|
@ -196,7 +201,7 @@ void WheeledVehicleTire::unpackData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::unpackData(stream);
|
Parent::unpackData(stream);
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
|
||||||
stream->read(&mass);
|
stream->read(&mass);
|
||||||
stream->read(&staticFriction);
|
stream->read(&staticFriction);
|
||||||
|
|
@ -340,9 +345,11 @@ bool WheeledVehicleData::preload(bool server, String &errorStr)
|
||||||
if (!Parent::preload(server, errorStr))
|
if (!Parent::preload(server, errorStr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
|
||||||
// A temporary shape instance is created so that we can
|
// A temporary shape instance is created so that we can
|
||||||
// animate the shape and extract wheel information.
|
// animate the shape and extract wheel information.
|
||||||
TSShapeInstance* si = new TSShapeInstance(getShape(), false);
|
TSShapeInstance* si = new TSShapeInstance(shape, false);
|
||||||
|
|
||||||
// Resolve objects transmitted from server
|
// Resolve objects transmitted from server
|
||||||
if (!server) {
|
if (!server) {
|
||||||
|
|
@ -367,14 +374,14 @@ bool WheeledVehicleData::preload(bool server, String &errorStr)
|
||||||
|
|
||||||
// The wheel must have a hub node to operate at all.
|
// The wheel must have a hub node to operate at all.
|
||||||
dSprintf(buff,sizeof(buff),"hub%d",i);
|
dSprintf(buff,sizeof(buff),"hub%d",i);
|
||||||
wp->springNode = getShape()->findNode(buff);
|
wp->springNode = shape->findNode(buff);
|
||||||
if (wp->springNode != -1) {
|
if (wp->springNode != -1) {
|
||||||
|
|
||||||
// Check for spring animation.. If there is none we just grab
|
// Check for spring animation.. If there is none we just grab
|
||||||
// the current position of the hub. Otherwise we'll animate
|
// the current position of the hub. Otherwise we'll animate
|
||||||
// and get the position at time 0.
|
// and get the position at time 0.
|
||||||
dSprintf(buff,sizeof(buff),"spring%d",i);
|
dSprintf(buff,sizeof(buff),"spring%d",i);
|
||||||
wp->springSequence = getShape()->findSequence(buff);
|
wp->springSequence = shape->findSequence(buff);
|
||||||
if (wp->springSequence == -1)
|
if (wp->springSequence == -1)
|
||||||
si->mNodeTransforms[wp->springNode].getColumn(3, &wp->pos);
|
si->mNodeTransforms[wp->springNode].getColumn(3, &wp->pos);
|
||||||
else {
|
else {
|
||||||
|
|
@ -403,17 +410,17 @@ bool WheeledVehicleData::preload(bool server, String &errorStr)
|
||||||
// Check for steering. Should think about normalizing the
|
// Check for steering. Should think about normalizing the
|
||||||
// steering animation the way the suspension is, but I don't
|
// steering animation the way the suspension is, but I don't
|
||||||
// think it's as critical.
|
// think it's as critical.
|
||||||
steeringSequence = getShape()->findSequence("steering");
|
steeringSequence = shape->findSequence("steering");
|
||||||
|
|
||||||
// Brakes
|
// Brakes
|
||||||
brakeLightSequence = getShape()->findSequence("brakelight");
|
brakeLightSequence = shape->findSequence("brakelight");
|
||||||
|
|
||||||
// Extract collision planes from shape collision detail level
|
// Extract collision planes from shape collision detail level
|
||||||
if (collisionDetails[0] != -1) {
|
if (collisionDetails[0] != -1) {
|
||||||
MatrixF imat(1);
|
MatrixF imat(1);
|
||||||
SphereF sphere;
|
SphereF sphere;
|
||||||
sphere.center = getShape()->center;
|
sphere.center = shape->center;
|
||||||
sphere.radius = getShape()->mRadius;
|
sphere.radius = shape->mRadius;
|
||||||
PlaneExtractorPolyList polyList;
|
PlaneExtractorPolyList polyList;
|
||||||
polyList.mPlaneList = &rigidBody.mPlaneList;
|
polyList.mPlaneList = &rigidBody.mPlaneList;
|
||||||
polyList.setTransform(&imat, Point3F(1,1,1));
|
polyList.setTransform(&imat, Point3F(1,1,1));
|
||||||
|
|
@ -1581,8 +1588,15 @@ void WheeledVehicle::unpackUpdate(NetConnection *con, BitStream *stream)
|
||||||
|
|
||||||
// Create an instance of the tire for rendering
|
// Create an instance of the tire for rendering
|
||||||
delete wheel->shapeInstance;
|
delete wheel->shapeInstance;
|
||||||
wheel->shapeInstance = (wheel->tire->getShape() == NULL) ? 0:
|
|
||||||
new TSShapeInstance(wheel->tire->getShape());
|
if (wheel->tire->shapeAssetRef.notNull())
|
||||||
|
{
|
||||||
|
Resource<TSShape> shape = wheel->tire->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (shape)
|
||||||
|
{
|
||||||
|
wheel->shapeInstance = new TSShapeInstance(shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ struct WheeledVehicleTire: public SimDataBlock, protected AssetPtrCallback
|
||||||
{
|
{
|
||||||
typedef SimDataBlock Parent;
|
typedef SimDataBlock Parent;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(WheeledVehicleTire, Shape)
|
AssetRef<ShapeAsset> shapeAssetRef;
|
||||||
|
|
||||||
// Physical properties
|
// Physical properties
|
||||||
F32 mass; // Mass of the whole wheel
|
F32 mass; // Mass of the whole wheel
|
||||||
|
|
|
||||||
|
|
@ -241,13 +241,13 @@ afxMagicMissileData::afxMagicMissileData()
|
||||||
|
|
||||||
caster_safety_time = U32_MAX;
|
caster_safety_time = U32_MAX;
|
||||||
|
|
||||||
mProjectileShapeAsset.registerRefreshNotify(this);
|
projectileShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
projectileShape = NULL;
|
projectileShape = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
afxMagicMissileData::afxMagicMissileData(const afxMagicMissileData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
afxMagicMissileData::afxMagicMissileData(const afxMagicMissileData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||||
{
|
{
|
||||||
mProjectileShapeAsset = other.mProjectileShapeAsset;
|
projectileShapeAssetRef = other.projectileShapeAssetRef;
|
||||||
projectileShape = other.projectileShape; // -- TSShape loads using projectileShapeName
|
projectileShape = other.projectileShape; // -- TSShape loads using projectileShapeName
|
||||||
CLONE_ASSET(ProjectileSound);
|
CLONE_ASSET(ProjectileSound);
|
||||||
splash = other.splash;
|
splash = other.splash;
|
||||||
|
|
@ -307,8 +307,6 @@ afxMagicMissileData::~afxMagicMissileData()
|
||||||
{
|
{
|
||||||
if (wiggle_axis)
|
if (wiggle_axis)
|
||||||
delete [] wiggle_axis;
|
delete [] wiggle_axis;
|
||||||
|
|
||||||
mProjectileShapeAsset.unregisterRefreshNotify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afxMagicMissileData* afxMagicMissileData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
|
afxMagicMissileData* afxMagicMissileData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
|
||||||
|
|
@ -338,7 +336,8 @@ void afxMagicMissileData::initPersistFields()
|
||||||
static IRangeValidatorScaled ticksFromMS(TickMs, 0, MaxLifetimeTicks);
|
static IRangeValidatorScaled ticksFromMS(TickMs, 0, MaxLifetimeTicks);
|
||||||
|
|
||||||
addGroup("Shapes");
|
addGroup("Shapes");
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(ProjectileShape, afxMagicMissileData, "Shape for the projectile");
|
ADD_FIELD("projectileShapeAsset", TypeShapeAssetRef, Offset(projectileShapeAssetRef, afxMagicMissileData))
|
||||||
|
.doc("Shape for the projectile");
|
||||||
addField("scale", TypePoint3F, Offset(scale, afxMagicMissileData));
|
addField("scale", TypePoint3F, Offset(scale, afxMagicMissileData));
|
||||||
addField("missileShapeScale", TypePoint3F, myOffset(scale));
|
addField("missileShapeScale", TypePoint3F, myOffset(scale));
|
||||||
endGroup("Shapes");
|
endGroup("Shapes");
|
||||||
|
|
@ -532,15 +531,19 @@ bool afxMagicMissileData::preload(bool server, String &errorStr)
|
||||||
Con::errorf(ConsoleLogEntry::General, "afxMagicMissileData::preload: Invalid packet, bad datablockid(lightDesc): %d", lightDescId);
|
Con::errorf(ConsoleLogEntry::General, "afxMagicMissileData::preload: Invalid packet, bad datablockid(lightDesc): %d", lightDescId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getProjectileShape())
|
if (projectileShapeAssetRef.notNull())
|
||||||
{
|
{
|
||||||
TSShapeInstance* pDummy = new TSShapeInstance(getProjectileShape(), !server);
|
Resource<TSShape> shape = projectileShapeAssetRef.assetPtr->getShapeResource();
|
||||||
delete pDummy;
|
if (shape)
|
||||||
}
|
{
|
||||||
else if (mProjectileShapeAsset.notNull())
|
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||||
{
|
delete pDummy;
|
||||||
errorStr = String::ToString("afxMagicMissileData::preload: Couldn't load shape \"%s\"", _getProjectileShapeAssetId());
|
}
|
||||||
return false;
|
else
|
||||||
|
{
|
||||||
|
errorStr = String::ToString("afxMagicMissileData(%s)::preload: Couldn't load shape \"%s\"", getName(), projectileShapeAssetRef.assetId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -580,7 +583,7 @@ void afxMagicMissileData::packData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::packData(stream);
|
Parent::packData(stream);
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(ProjectileShape);
|
AssetDatabase.packDataAsset(stream, projectileShapeAssetRef.assetId);
|
||||||
|
|
||||||
/* From stock Projectile code...
|
/* From stock Projectile code...
|
||||||
stream->writeFlag(faceViewer);
|
stream->writeFlag(faceViewer);
|
||||||
|
|
@ -691,7 +694,7 @@ void afxMagicMissileData::unpackData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::unpackData(stream);
|
Parent::unpackData(stream);
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(ProjectileShape);
|
projectileShapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
/* From stock Projectile code...
|
/* From stock Projectile code...
|
||||||
faceViewer = stream->readFlag();
|
faceViewer = stream->readFlag();
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ public:
|
||||||
public:
|
public:
|
||||||
// variables set in datablock definition:
|
// variables set in datablock definition:
|
||||||
// Shape related
|
// Shape related
|
||||||
DECLARE_SHAPEASSET_REFACTOR(afxMagicMissileData, ProjectileShape)
|
AssetRef<ShapeAsset> projectileShapeAssetRef;
|
||||||
//StringTableEntry projectileShapeName;
|
//StringTableEntry projectileShapeName;
|
||||||
|
|
||||||
//bool hasLight;
|
//bool hasLight;
|
||||||
|
|
|
||||||
|
|
@ -79,12 +79,12 @@ afxModelData::afxModelData()
|
||||||
shadowProjectionDistance = 10.0f;
|
shadowProjectionDistance = 10.0f;
|
||||||
shadowSphereAdjust = 1.0;
|
shadowSphereAdjust = 1.0;
|
||||||
|
|
||||||
mShapeAsset.registerRefreshNotify(this);
|
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
afxModelData::afxModelData(const afxModelData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
afxModelData::afxModelData(const afxModelData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||||
{
|
{
|
||||||
mShapeAsset = other.mShapeAsset;
|
shapeAssetRef = other.shapeAssetRef;
|
||||||
sequence = other.sequence;
|
sequence = other.sequence;
|
||||||
seq_rate = other.seq_rate;
|
seq_rate = other.seq_rate;
|
||||||
seq_offset = other.seq_offset;
|
seq_offset = other.seq_offset;
|
||||||
|
|
@ -114,8 +114,6 @@ afxModelData::~afxModelData()
|
||||||
{
|
{
|
||||||
if (remap_buffer)
|
if (remap_buffer)
|
||||||
dFree(remap_buffer);
|
dFree(remap_buffer);
|
||||||
|
|
||||||
mShapeAsset.unregisterRefreshNotify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool afxModelData::preload(bool server, String &errorStr)
|
bool afxModelData::preload(bool server, String &errorStr)
|
||||||
|
|
@ -127,7 +125,11 @@ bool afxModelData::preload(bool server, String &errorStr)
|
||||||
if (server)
|
if (server)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (getShape())
|
if (shapeAssetRef.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (shape)
|
||||||
{
|
{
|
||||||
// just parse up the string and collect the remappings in txr_tag_remappings.
|
// just parse up the string and collect the remappings in txr_tag_remappings.
|
||||||
if (remap_txr_tags != ST_NULLSTRING)
|
if (remap_txr_tags != ST_NULLSTRING)
|
||||||
|
|
@ -157,13 +159,13 @@ bool afxModelData::preload(bool server, String &errorStr)
|
||||||
if (txr_tag_remappings.size() == 0)
|
if (txr_tag_remappings.size() == 0)
|
||||||
{
|
{
|
||||||
// this little hack forces the textures to preload
|
// this little hack forces the textures to preload
|
||||||
TSShapeInstance* pDummy = new TSShapeInstance(getShape());
|
TSShapeInstance* pDummy = new TSShapeInstance(shape);
|
||||||
delete pDummy;
|
delete pDummy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errorStr = String::ToString("afxModelData::load: Failed to load shape \"%s\"", _getShapeAssetId());
|
errorStr = String::ToString("afxModelData::load: Failed to load shape \"%s\"", shapeAssetRef.assetId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -175,7 +177,8 @@ void afxModelData::initPersistFields()
|
||||||
{
|
{
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup("Shapes");
|
addGroup("Shapes");
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, afxModelData, "The name of a .dts format file to use for the model.");
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, afxModelData))
|
||||||
|
.doc("The id of a shapeAsset to use for the shape.");
|
||||||
endGroup("Shapes");
|
endGroup("Shapes");
|
||||||
|
|
||||||
addGroup("Animation");
|
addGroup("Animation");
|
||||||
|
|
@ -259,7 +262,8 @@ void afxModelData::packData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::packData(stream);
|
Parent::packData(stream);
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(Shape);
|
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||||
|
|
||||||
stream->writeString(sequence);
|
stream->writeString(sequence);
|
||||||
stream->write(seq_rate);
|
stream->write(seq_rate);
|
||||||
stream->write(seq_offset);
|
stream->write(seq_offset);
|
||||||
|
|
@ -290,7 +294,8 @@ void afxModelData::unpackData(BitStream* stream)
|
||||||
{
|
{
|
||||||
Parent::unpackData(stream);
|
Parent::unpackData(stream);
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
|
||||||
sequence = stream->readSTString();
|
sequence = stream->readSTString();
|
||||||
stream->read(&seq_rate);
|
stream->read(&seq_rate);
|
||||||
stream->read(&seq_offset);
|
stream->read(&seq_offset);
|
||||||
|
|
@ -319,9 +324,15 @@ void afxModelData::unpackData(BitStream* stream)
|
||||||
|
|
||||||
void afxModelData::onPerformSubstitutions()
|
void afxModelData::onPerformSubstitutions()
|
||||||
{
|
{
|
||||||
if (!getShape())
|
if (!shapeAssetRef.isNull())
|
||||||
{
|
{
|
||||||
Con::errorf("afxModelData::onPerformSubstitutions: Failed to load shape \"%s\"", _getShapeAssetId());
|
Con::errorf("afxModelData::onPerformSubstitutions: Failed to load shape asset \"%s\"", shapeAssetRef.assetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
|
{
|
||||||
|
Con::errorf("afxModelData::onPerformSubstitutions: Failed to load shape \"%s\"", shapeAssetRef.assetId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -395,19 +406,22 @@ bool afxModel::onAdd()
|
||||||
if (!conn || !Parent::onAdd())
|
if (!conn || !Parent::onAdd())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// setup our bounding box
|
Resource<TSShape> shape;
|
||||||
if (mDataBlock->getShape())
|
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
|
||||||
mObjBox = mDataBlock->getShape()->mBounds;
|
if (!mDataBlock->shapeAssetRef.isNull())
|
||||||
else
|
{
|
||||||
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
|
shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (shape)
|
||||||
|
mObjBox = shape->mBounds;
|
||||||
|
}
|
||||||
|
|
||||||
// setup the shape instance and sequence
|
// setup the shape instance and sequence
|
||||||
if (mDataBlock->getShape())
|
if (shape)
|
||||||
{
|
{
|
||||||
if (/*isClientObject() && */mDataBlock->txr_tag_remappings.size() > 0)
|
if (/*isClientObject() && */mDataBlock->txr_tag_remappings.size() > 0)
|
||||||
{
|
{
|
||||||
// temporarily substitute material tags with alternates
|
// temporarily substitute material tags with alternates
|
||||||
TSMaterialList* mat_list = mDataBlock->getShape()->materialList;
|
TSMaterialList* mat_list = shape->materialList;
|
||||||
if (mat_list)
|
if (mat_list)
|
||||||
{
|
{
|
||||||
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
||||||
|
|
@ -428,7 +442,7 @@ bool afxModel::onAdd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shape_inst = new TSShapeInstance(mDataBlock->getShape());
|
shape_inst = new TSShapeInstance(shape);
|
||||||
|
|
||||||
if (true) // isClientObject())
|
if (true) // isClientObject())
|
||||||
{
|
{
|
||||||
|
|
@ -437,7 +451,7 @@ bool afxModel::onAdd()
|
||||||
// restore the material tags to original form
|
// restore the material tags to original form
|
||||||
if (mDataBlock->txr_tag_remappings.size() > 0)
|
if (mDataBlock->txr_tag_remappings.size() > 0)
|
||||||
{
|
{
|
||||||
TSMaterialList* mat_list = mDataBlock->getShape()->materialList;
|
TSMaterialList* mat_list = shape->materialList;
|
||||||
if (mat_list)
|
if (mat_list)
|
||||||
{
|
{
|
||||||
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
||||||
|
|
@ -466,7 +480,6 @@ bool afxModel::onAdd()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// here we start the default animation sequence
|
// here we start the default animation sequence
|
||||||
TSShape* shape = shape_inst->getShape();
|
|
||||||
main_seq_id = shape->findSequence(mDataBlock->sequence);
|
main_seq_id = shape->findSequence(mDataBlock->sequence);
|
||||||
if (main_seq_id != -1)
|
if (main_seq_id != -1)
|
||||||
{
|
{
|
||||||
|
|
@ -503,14 +516,14 @@ bool afxModel::onAdd()
|
||||||
|
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
|
|
||||||
if (mDataBlock->getShape())
|
if (shape)
|
||||||
{
|
{
|
||||||
// Scan out the collision hulls...
|
// Scan out the collision hulls...
|
||||||
static const String sCollisionStr( "collision-" );
|
static const String sCollisionStr( "collision-" );
|
||||||
|
|
||||||
for (U32 i = 0; i < mDataBlock->getShape()->details.size(); i++)
|
for (U32 i = 0; i < shape->details.size(); i++)
|
||||||
{
|
{
|
||||||
const String &name = mDataBlock->getShape()->names[mDataBlock->getShape()->details[i].nameIndex];
|
const String &name = shape->names[shape->details[i].nameIndex];
|
||||||
|
|
||||||
if (name.compare( sCollisionStr, sCollisionStr.length(), String::NoCase ) == 0)
|
if (name.compare( sCollisionStr, sCollisionStr.length(), String::NoCase ) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -524,7 +537,7 @@ bool afxModel::onAdd()
|
||||||
|
|
||||||
char buff[128];
|
char buff[128];
|
||||||
dSprintf(buff, sizeof(buff), "LOS-%d", i + 1 + 8/*MaxCollisionShapes*/);
|
dSprintf(buff, sizeof(buff), "LOS-%d", i + 1 + 8/*MaxCollisionShapes*/);
|
||||||
U32 los = mDataBlock->getShape()->findDetail(buff);
|
U32 los = shape->findDetail(buff);
|
||||||
if (los == -1)
|
if (los == -1)
|
||||||
mLOSDetails.last() = i;
|
mLOSDetails.last() = i;
|
||||||
else
|
else
|
||||||
|
|
@ -535,9 +548,9 @@ bool afxModel::onAdd()
|
||||||
// Snag any "unmatched" LOS details
|
// Snag any "unmatched" LOS details
|
||||||
static const String sLOSStr( "LOS-" );
|
static const String sLOSStr( "LOS-" );
|
||||||
|
|
||||||
for (U32 i = 0; i < mDataBlock->getShape()->details.size(); i++)
|
for (U32 i = 0; i < shape->details.size(); i++)
|
||||||
{
|
{
|
||||||
const String &name = mDataBlock->getShape()->names[mDataBlock->getShape()->details[i].nameIndex];
|
const String &name = shape->names[shape->details[i].nameIndex];
|
||||||
|
|
||||||
if (name.compare( sLOSStr, sLOSStr.length(), String::NoCase ) == 0)
|
if (name.compare( sLOSStr, sLOSStr.length(), String::NoCase ) == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ struct afxModelData : public GameBaseData, protected AssetPtrCallback
|
||||||
{
|
{
|
||||||
typedef GameBaseData Parent;
|
typedef GameBaseData Parent;
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(afxModelData, Shape)
|
AssetRef<ShapeAsset> shapeAssetRef;
|
||||||
|
|
||||||
StringTableEntry sequence;
|
StringTableEntry sequence;
|
||||||
|
|
||||||
|
|
@ -155,9 +155,21 @@ public:
|
||||||
void setSequenceRateFactor(F32 factor);
|
void setSequenceRateFactor(F32 factor);
|
||||||
void setSortPriority(S8 priority) { sort_priority = priority; }
|
void setSortPriority(S8 priority) { sort_priority = priority; }
|
||||||
|
|
||||||
const char* getShapeFileName() const { return mDataBlock->getShapeFile(); }
|
const char* getShapeFileName() const
|
||||||
|
{
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return mDataBlock->shapeAssetRef.assetPtr->getShapeFile();
|
||||||
|
}
|
||||||
void setVisibility(bool flag) { is_visible = flag; }
|
void setVisibility(bool flag) { is_visible = flag; }
|
||||||
TSShape* getTSShape() { return mDataBlock->getShape(); }
|
TSShape* getTSShape()
|
||||||
|
{
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return mDataBlock->shapeAssetRef.assetPtr->getShape();
|
||||||
|
}
|
||||||
TSShapeInstance* getTSShapeInstance() { return shape_inst; }
|
TSShapeInstance* getTSShapeInstance() { return shape_inst; }
|
||||||
|
|
||||||
U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans);
|
U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans);
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,13 @@ public:
|
||||||
U32 packUpdate(NetConnection*, U32, BitStream*) override;
|
U32 packUpdate(NetConnection*, U32, BitStream*) override;
|
||||||
void unpackUpdate(NetConnection*, BitStream*) override;
|
void unpackUpdate(NetConnection*, BitStream*) override;
|
||||||
|
|
||||||
const char* getShapeFileName() const { return mDataBlock->getShapeFile(); }
|
const char* getShapeFileName() const
|
||||||
|
{
|
||||||
|
if (mDataBlock->shapeAssetRef.isNull())
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return mDataBlock->shapeAssetRef.assetPtr->getShapeFile();
|
||||||
|
}
|
||||||
void setVisibility(bool flag) { mIs_visible = flag; }
|
void setVisibility(bool flag) { mIs_visible = flag; }
|
||||||
|
|
||||||
DECLARE_CONOBJECT(afxStaticShape);
|
DECLARE_CONOBJECT(afxStaticShape);
|
||||||
|
|
|
||||||
|
|
@ -182,4 +182,54 @@ public:
|
||||||
bool isValid(void) const { return notNull() && static_cast<AssetBase*>(mpAsset.getObject())->isAssetValid(); }
|
bool isValid(void) const { return notNull() && static_cast<AssetBase*>(mpAsset.getObject())->isAssetValid(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// AssetRef is a simple struct that contains an asset Id and an AssetPtr.
|
||||||
|
// This is used in cases where we want to be able to track the asset Id even if the asset pointer is null (e.g. when the asset fails to load and we want to keep the asset Id around so that we can retry loading it later).
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
|
struct AssetRef
|
||||||
|
{
|
||||||
|
StringTableEntry assetId;
|
||||||
|
AssetPtr<T> assetPtr;
|
||||||
|
|
||||||
|
AssetRef()
|
||||||
|
{
|
||||||
|
assetId = StringTable->EmptyString();
|
||||||
|
}
|
||||||
|
AssetRef<T>& operator=(const char* pAssetId)
|
||||||
|
{
|
||||||
|
assetId = StringTable->insert(pAssetId);
|
||||||
|
assetPtr = pAssetId;
|
||||||
|
|
||||||
|
// Return Reference.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
AssetRef<T>& operator=(const AssetPtr<T>& pAssetPtr)
|
||||||
|
{
|
||||||
|
if (pAssetPtr.notNull())
|
||||||
|
assetId = StringTable->insert(pAssetPtr->getAssetId());
|
||||||
|
|
||||||
|
assetPtr = pAssetPtr;
|
||||||
|
|
||||||
|
// Return Reference.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
AssetRef<T>& operator=(const AssetRef<T>& pAssetRef)
|
||||||
|
{
|
||||||
|
assetId = pAssetRef.assetId;
|
||||||
|
assetPtr = pAssetRef.assetPtr;
|
||||||
|
|
||||||
|
// Return Reference.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTableEntry getAssetId(void) const { return assetId; }
|
||||||
|
bool isAssetId(const char* pAssetId) const { return assetId == StringTable->insert(pAssetId); }
|
||||||
|
bool hasAssetId() const { return assetId != StringTable->EmptyString(); }
|
||||||
|
|
||||||
|
/// Validity.
|
||||||
|
bool isNull(void) const { return assetPtr.isNull(); }
|
||||||
|
bool notNull(void) const { return !assetPtr.isNull(); }
|
||||||
|
bool isValid(void) const { return notNull() && static_cast<AssetBase*>(assetPtr)->isAssetValid(); }
|
||||||
|
};
|
||||||
#endif // _ASSET_PTR_H_
|
#endif // _ASSET_PTR_H_
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,9 @@ void VolumetricFog::initPersistFields()
|
||||||
docsURL;
|
docsURL;
|
||||||
Parent::initPersistFields();
|
Parent::initPersistFields();
|
||||||
addGroup("Shapes");
|
addGroup("Shapes");
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, VolumetricFog, "The source shape asset.");
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(mShapeAssetRef, VolumetricFog))
|
||||||
|
.doc("The source shape asset.")
|
||||||
|
.network(FogShapeMask);
|
||||||
endGroup("Shapes");
|
endGroup("Shapes");
|
||||||
|
|
||||||
addGroup("VolumetricFogData");
|
addGroup("VolumetricFogData");
|
||||||
|
|
@ -340,7 +342,7 @@ void VolumetricFog::handleResize(VolumetricFogRTManager *RTM, bool resize)
|
||||||
|
|
||||||
bool VolumetricFog::setShapeAsset(const StringTableEntry shapeAssetId)
|
bool VolumetricFog::setShapeAsset(const StringTableEntry shapeAssetId)
|
||||||
{
|
{
|
||||||
_setShape(shapeAssetId);
|
mShapeAssetRef = shapeAssetId;
|
||||||
|
|
||||||
LoadShape();
|
LoadShape();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -349,27 +351,28 @@ bool VolumetricFog::setShapeAsset(const StringTableEntry shapeAssetId)
|
||||||
bool VolumetricFog::LoadShape()
|
bool VolumetricFog::LoadShape()
|
||||||
{
|
{
|
||||||
GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip };
|
GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip };
|
||||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
|
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAssetRef.assetPtr);
|
||||||
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
||||||
{
|
{
|
||||||
Con::errorf("[VolumetricFog] Failed to load shape asset.");
|
Con::errorf("[VolumetricFog] Failed to load shape asset.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getShape())
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
|
if (!shape)
|
||||||
{
|
{
|
||||||
Con::errorf("VolumetricFog::_createShape() - Shape Asset had no valid shape!");
|
Con::errorf("VolumetricFog::_createShape() - Shape Asset had no valid shape!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mObjBox = getShape()->mBounds;
|
mObjBox = shape->mBounds;
|
||||||
mRadius = getShape()->mRadius;
|
mRadius = shape->mRadius;
|
||||||
resetWorldBox();
|
resetWorldBox();
|
||||||
|
|
||||||
if (!isClientObject())
|
if (!isClientObject())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
TSShapeInstance *mShapeInstance = new TSShapeInstance(getShape(), false);
|
TSShapeInstance *mShapeInstance = new TSShapeInstance(shape, false);
|
||||||
meshes mesh_detail;
|
meshes mesh_detail;
|
||||||
|
|
||||||
for (S32 i = 0; i < det_size.size(); i++)
|
for (S32 i = 0; i < det_size.size(); i++)
|
||||||
|
|
@ -385,9 +388,9 @@ bool VolumetricFog::LoadShape()
|
||||||
|
|
||||||
// browsing model for detail levels
|
// browsing model for detail levels
|
||||||
|
|
||||||
for (U32 i = 0; i < getShape()->details.size(); i++)
|
for (U32 i = 0; i < shape->details.size(); i++)
|
||||||
{
|
{
|
||||||
const TSDetail *detail = &getShape()->details[i];
|
const TSDetail *detail = &shape->details[i];
|
||||||
mesh_detail.det_size = detail->size;
|
mesh_detail.det_size = detail->size;
|
||||||
mesh_detail.sub_shape = detail->subShapeNum;
|
mesh_detail.sub_shape = detail->subShapeNum;
|
||||||
mesh_detail.obj_det = detail->objectDetailNum;
|
mesh_detail.obj_det = detail->objectDetailNum;
|
||||||
|
|
@ -403,8 +406,8 @@ bool VolumetricFog::LoadShape()
|
||||||
const S32 ss = det_size[i].sub_shape;
|
const S32 ss = det_size[i].sub_shape;
|
||||||
if (ss >= 0)
|
if (ss >= 0)
|
||||||
{
|
{
|
||||||
const S32 start = getShape()->subShapeFirstObject[ss];
|
const S32 start = shape->subShapeFirstObject[ss];
|
||||||
const S32 end = start + getShape()->subShapeNumObjects[ss];
|
const S32 end = start + shape->subShapeNumObjects[ss];
|
||||||
for (S32 j = start; j < end; j++)
|
for (S32 j = start; j < end; j++)
|
||||||
{
|
{
|
||||||
// Loading shape, only the first mesh for each detail will be used!
|
// Loading shape, only the first mesh for each detail will be used!
|
||||||
|
|
@ -566,14 +569,17 @@ U32 VolumetricFog::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
||||||
}
|
}
|
||||||
if (stream->writeFlag(mask & FogShapeMask))
|
if (stream->writeFlag(mask & FogShapeMask))
|
||||||
{
|
{
|
||||||
PACK_ASSET_REFACTOR(con, Shape);
|
AssetDatabase.packUpdateAsset(conn, mask, stream, mShapeAssetRef.assetId);
|
||||||
|
|
||||||
mathWrite(*stream, getTransform());
|
mathWrite(*stream, getTransform());
|
||||||
mathWrite(*stream, getScale());
|
mathWrite(*stream, getScale());
|
||||||
|
|
||||||
if (mShapeAsset.notNull())
|
if (mShapeAssetRef.isValid())
|
||||||
{
|
{
|
||||||
mObjBox = mShapeAsset->getShapeResource()->mBounds;
|
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||||
mRadius = mShapeAsset->getShapeResource()->mRadius;
|
|
||||||
|
mObjBox = shape->mBounds;
|
||||||
|
mRadius = shape->mRadius;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -595,8 +601,8 @@ void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream)
|
||||||
VectorF scale;
|
VectorF scale;
|
||||||
VectorF mOldScale = getScale();
|
VectorF mOldScale = getScale();
|
||||||
StringTableEntry oldTextureName = mTextureAsset.getAssetId();
|
StringTableEntry oldTextureName = mTextureAsset.getAssetId();
|
||||||
StringTableEntry oldShapeAsset = _getShapeAssetId();
|
StringTableEntry oldShapeAsset = mShapeAssetRef.assetId;
|
||||||
StringTableEntry oldShape = getShapeFile();
|
StringTableEntry oldShape = mShapeAssetRef.assetPtr->getShapeFile();
|
||||||
|
|
||||||
if (stream->readFlag())// Fog color
|
if (stream->readFlag())// Fog color
|
||||||
stream->read(&mFogColor);
|
stream->read(&mFogColor);
|
||||||
|
|
@ -665,11 +671,11 @@ void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream)
|
||||||
}
|
}
|
||||||
if (stream->readFlag())//Fog shape
|
if (stream->readFlag())//Fog shape
|
||||||
{
|
{
|
||||||
UNPACK_ASSET_REFACTOR(con, Shape);
|
mShapeAssetRef = AssetDatabase.unpackUpdateAsset(conn, stream);
|
||||||
|
|
||||||
mathRead(*stream, &mat);
|
mathRead(*stream, &mat);
|
||||||
mathRead(*stream, &scale);
|
mathRead(*stream, &scale);
|
||||||
if (strcmp(oldShapeAsset, _getShapeAssetId()) != 0 || strcmp(oldShape, getShapeFile()) != 0)
|
if (strcmp(oldShapeAsset, mShapeAssetRef.assetId) != 0 || strcmp(oldShape, mShapeAssetRef.assetPtr->getShapeFile()) != 0)
|
||||||
{
|
{
|
||||||
mIsVBDirty = true;
|
mIsVBDirty = true;
|
||||||
mShapeLoaded = LoadShape();
|
mShapeLoaded = LoadShape();
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ class VolumetricFog : public SceneObject
|
||||||
Vector <U32> *indices;
|
Vector <U32> *indices;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(VolumetricFog, Shape)
|
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Rendertargets;
|
// Rendertargets;
|
||||||
|
|
|
||||||
|
|
@ -54,15 +54,15 @@ ForestItemData::ForestItemData()
|
||||||
mDampingCoefficient( 0.7f )
|
mDampingCoefficient( 0.7f )
|
||||||
{
|
{
|
||||||
mShape = NULL;
|
mShape = NULL;
|
||||||
mShapeAsset.registerRefreshNotify(this);
|
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForestItemData::initPersistFields()
|
void ForestItemData::initPersistFields()
|
||||||
{
|
{
|
||||||
docsURL;
|
docsURL;
|
||||||
addGroup( "Shapes" );
|
addGroup( "Shapes" );
|
||||||
|
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, ForestItemData))
|
||||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, ForestItemData, "Shape asset for this item type");
|
.doc("Shape asset for this item type");
|
||||||
|
|
||||||
endGroup( "Shapes" );
|
endGroup( "Shapes" );
|
||||||
|
|
||||||
|
|
@ -163,7 +163,7 @@ void ForestItemData::packData(BitStream* stream)
|
||||||
|
|
||||||
stream->write( localName );
|
stream->write( localName );
|
||||||
|
|
||||||
PACKDATA_ASSET_REFACTOR(Shape);
|
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||||
|
|
||||||
stream->writeFlag( mCollidable );
|
stream->writeFlag( mCollidable );
|
||||||
|
|
||||||
|
|
@ -189,7 +189,7 @@ void ForestItemData::unpackData(BitStream* stream)
|
||||||
stream->read( &localName );
|
stream->read( &localName );
|
||||||
setInternalName( localName );
|
setInternalName( localName );
|
||||||
|
|
||||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||||
|
|
||||||
mCollidable = stream->readFlag();
|
mCollidable = stream->readFlag();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DECLARE_SHAPEASSET_REFACTOR(ForestItemData, Shape)
|
AssetRef<ShapeAsset> shapeAssetRef;
|
||||||
|
|
||||||
/// This is the radius used during placement to ensure
|
/// This is the radius used during placement to ensure
|
||||||
/// the element isn't crowded up against other trees.
|
/// the element isn't crowded up against other trees.
|
||||||
|
|
|
||||||
|
|
@ -99,13 +99,13 @@ void TSForestItemData::inspectPostApply()
|
||||||
|
|
||||||
void TSForestItemData::_onResourceChanged( const Torque::Path &path )
|
void TSForestItemData::_onResourceChanged( const Torque::Path &path )
|
||||||
{
|
{
|
||||||
U32 assetStatus = ShapeAsset::getAssetErrCode(_getShapeAssetId());
|
U32 assetStatus = ShapeAsset::getAssetErrCode(shapeAssetRef.assetPtr);
|
||||||
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( path != Path(getShapeFile()) )
|
if ( path != Path(shapeAssetRef.assetPtr->getShapeFile()) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SAFE_DELETE( mShapeInstance );
|
SAFE_DELETE( mShapeInstance );
|
||||||
|
|
@ -116,8 +116,11 @@ void TSForestItemData::_onResourceChanged( const Torque::Path &path )
|
||||||
|
|
||||||
void TSForestItemData::_loadShape()
|
void TSForestItemData::_loadShape()
|
||||||
{
|
{
|
||||||
mShape = getShape();
|
if (shapeAssetRef.assetPtr.isNull())
|
||||||
U32 assetStatus = ShapeAsset::getAssetErrCode(_getShapeAssetId());
|
return;
|
||||||
|
|
||||||
|
mShape = shapeAssetRef.assetPtr->getShape();
|
||||||
|
U32 assetStatus = ShapeAsset::getAssetErrCode(shapeAssetRef.assetPtr);
|
||||||
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -127,7 +130,7 @@ void TSForestItemData::_loadShape()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( mIsClientObject &&
|
if ( mIsClientObject &&
|
||||||
!mShape->preloadMaterialList(getShapeFile()) )
|
!mShape->preloadMaterialList(shapeAssetRef.assetPtr->getShapeFile()) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Lets add an autobillboard detail if don't have one.
|
// Lets add an autobillboard detail if don't have one.
|
||||||
|
|
@ -165,7 +168,7 @@ TSShapeInstance* TSForestItemData::_getShapeInstance() const
|
||||||
|
|
||||||
void TSForestItemData::_checkLastDetail()
|
void TSForestItemData::_checkLastDetail()
|
||||||
{
|
{
|
||||||
U32 assetStatus = ShapeAsset::getAssetErrCode(_getShapeAssetId());
|
U32 assetStatus = ShapeAsset::getAssetErrCode(shapeAssetRef.assetPtr);
|
||||||
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -177,7 +180,7 @@ void TSForestItemData::_checkLastDetail()
|
||||||
// TODO: Expose some real parameters to the datablock maybe?
|
// TODO: Expose some real parameters to the datablock maybe?
|
||||||
if ( detail->subShapeNum != -1 )
|
if ( detail->subShapeNum != -1 )
|
||||||
{
|
{
|
||||||
mShape->addImposter(getShapeFile(), 10, 4, 0, 0, 256, 0, 0);
|
mShape->addImposter(shapeAssetRef.assetPtr->getShapeFile(), 10, 4, 0, 0, 256, 0, 0);
|
||||||
|
|
||||||
// HACK: If i don't do this it crashes!
|
// HACK: If i don't do this it crashes!
|
||||||
while ( mShape->detailCollisionAccelerators.size() < mShape->details.size() )
|
while ( mShape->detailCollisionAccelerators.size() < mShape->details.size() )
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue