mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-06-05 13:06:43 +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"
|
||||
|
||||
StringTableEntry ShapeAsset::smNoShapeAssetFallback = NULL;
|
||||
AssetPtr<ShapeAsset> ShapeAsset::smNoShapeAssetFallbackAssetPtr = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(ShapeAsset);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// REFACTOR
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_STRUCT(AssetPtr<ShapeAsset>, AssetPtrShapeAsset, , "")
|
||||
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[] =
|
||||
{
|
||||
|
|
@ -170,7 +208,7 @@ void ShapeAsset::consoleInit()
|
|||
Con::addVariable("$Core::NoShapeAssetFallback", TypeString, &smNoShapeAssetFallback,
|
||||
"The assetId of the shape to display when the requested shape asset is missing.\n"
|
||||
"@ingroup GFX\n");
|
||||
|
||||
|
||||
smNoShapeAssetFallback = StringTable->insert(Con::getVariable("$Core::NoShapeAssetFallback"));
|
||||
}
|
||||
|
||||
|
|
@ -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()
|
||||
{
|
||||
// Call parent.
|
||||
|
|
@ -239,6 +263,16 @@ void ShapeAsset::initializeAsset()
|
|||
String normalPath = String(mShapeFile) + "_imposter_normals.dds";
|
||||
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)
|
||||
|
|
@ -313,9 +347,9 @@ void ShapeAsset::setNormalImposterFile(const char* pImageFile)
|
|||
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;
|
||||
|
||||
refreshAsset();
|
||||
|
|
@ -325,117 +359,64 @@ U32 ShapeAsset::load()
|
|||
{
|
||||
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);
|
||||
|
||||
if (!mShape)
|
||||
{
|
||||
mLoadedState = BadFileReference;
|
||||
|
||||
return mLoadedState; //if it failed to load, bail out
|
||||
}
|
||||
|
||||
// Construct billboards if not done already
|
||||
if (GFXDevice::devicePresent())
|
||||
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;
|
||||
|
||||
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
|
||||
U32 ShapeAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAsset>* shapeAsset)
|
||||
|
|
@ -560,6 +541,44 @@ U32 ShapeAsset::getAssetById(StringTableEntry assetId, AssetPtr<ShapeAsset>* sha
|
|||
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)
|
||||
|
|
@ -589,10 +608,10 @@ void ShapeAsset::onTamlPreWrite(void)
|
|||
Parent::onTamlPreWrite();
|
||||
|
||||
// ensure paths are collapsed.
|
||||
mShapeFile = collapseAssetFilePath(mShapeFile);
|
||||
mConstructorFileName = collapseAssetFilePath(mConstructorFileName);
|
||||
mDiffuseImposterFileName = collapseAssetFilePath(mDiffuseImposterFileName);
|
||||
mNormalImposterFileName = collapseAssetFilePath(mNormalImposterFileName);
|
||||
mShapeFile = collapseAssetFilePath(mShapeFile);
|
||||
mConstructorFileName = collapseAssetFilePath(mConstructorFileName);
|
||||
mDiffuseImposterFileName = collapseAssetFilePath(mDiffuseImposterFileName);
|
||||
mNormalImposterFileName = collapseAssetFilePath(mNormalImposterFileName);
|
||||
}
|
||||
|
||||
void ShapeAsset::onTamlPostWrite(void)
|
||||
|
|
@ -601,42 +620,10 @@ void ShapeAsset::onTamlPostWrite(void)
|
|||
Parent::onTamlPostWrite();
|
||||
|
||||
// ensure paths are expanded.
|
||||
mShapeFile = expandAssetFilePath(mShapeFile);
|
||||
mConstructorFileName = expandAssetFilePath(mConstructorFileName);
|
||||
mDiffuseImposterFileName = expandAssetFilePath(mDiffuseImposterFileName);
|
||||
mNormalImposterFileName = expandAssetFilePath(mNormalImposterFileName);
|
||||
}
|
||||
|
||||
void ShapeAsset::SplitSequencePathAndName(String& srcPath, String& srcName)
|
||||
{
|
||||
srcName = "";
|
||||
|
||||
// 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;
|
||||
mShapeFile = expandAssetFilePath(mShapeFile);
|
||||
mConstructorFileName = expandAssetFilePath(mConstructorFileName);
|
||||
mDiffuseImposterFileName = expandAssetFilePath(mDiffuseImposterFileName);
|
||||
mNormalImposterFileName = expandAssetFilePath(mNormalImposterFileName);
|
||||
}
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
|
|
@ -655,7 +642,7 @@ const char* ShapeAsset::generateCachedPreviewImage(S32 resolution, String overri
|
|||
|
||||
if (overrideMaterial.isNotEmpty())
|
||||
{
|
||||
Material *tMat = dynamic_cast<Material*>(Sim::findObject(overrideMaterial));
|
||||
Material* tMat = dynamic_cast<Material*>(Sim::findObject(overrideMaterial));
|
||||
if (tMat)
|
||||
shape->reSkin(tMat->mMapTo, mShape->materialList->getMaterialName(0));
|
||||
}
|
||||
|
|
@ -702,7 +689,7 @@ const char* ShapeAsset::generateCachedPreviewImage(S32 resolution, String overri
|
|||
dSprintf(returnBuffer, 128, "%s", dumpPath.c_str());
|
||||
|
||||
imposter->writeBitmap("png", dumpPath);
|
||||
|
||||
|
||||
delete imposter;
|
||||
delete imposterNrml;
|
||||
|
||||
|
|
@ -714,6 +701,13 @@ const char* ShapeAsset::generateCachedPreviewImage(S32 resolution, String overri
|
|||
}
|
||||
#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, (), ,
|
||||
"Gets the number of materials for this shape asset.\n"
|
||||
"@return Material count.\n")
|
||||
|
|
@ -721,14 +715,7 @@ DefineEngineMethod(ShapeAsset, getMaterialCount, S32, (), ,
|
|||
return object->getMaterialCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod(ShapeAsset, getAnimationCount, S32, (), ,
|
||||
"Gets the number of animations for this shape asset.\n"
|
||||
"@return Animation count.\n")
|
||||
{
|
||||
return object->getAnimationCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod(ShapeAsset, getAnimation, ShapeAnimationAsset*, (S32 index), (0),
|
||||
DefineEngineMethod(ShapeAsset, getAnimation, const char*, (S32 index), (0),
|
||||
"Gets a particular shape animation asset for this shape.\n"
|
||||
"@param animation asset index.\n"
|
||||
"@return Shape Animation Asset.\n")
|
||||
|
|
@ -736,6 +723,13 @@ DefineEngineMethod(ShapeAsset, getAnimation, ShapeAnimationAsset*, (S32 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*, (), ,
|
||||
"Gets the shape's file path\n"
|
||||
"@return The filename of the shape file")
|
||||
|
|
@ -784,7 +778,7 @@ ConsoleDocClass(GuiInspectorTypeShapeAssetPtr,
|
|||
"@brief Inspector field type for Shapes\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
);
|
||||
|
||||
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 (!AssetDatabase.isDeclaredAsset(previewImage))
|
||||
{
|
||||
mPreviewImage->_setBitmap(StringTable->EmptyString());
|
||||
mPreviewImage->setBitmap(StringTable->EmptyString());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -953,7 +947,7 @@ void GuiInspectorTypeShapeAssetPtr::updatePreviewImage()
|
|||
}
|
||||
|
||||
if (mPreviewImage->getBitmapAsset().isNull())
|
||||
mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||
mPreviewImage->setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||
}
|
||||
|
||||
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 (!AssetDatabase.isDeclaredAsset(assetId))
|
||||
{
|
||||
mPreviewImage->_setBitmap(StringTable->EmptyString());
|
||||
mPreviewImage->setBitmap(StringTable->EmptyString());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -974,7 +968,7 @@ void GuiInspectorTypeShapeAssetPtr::setPreviewImage(StringTableEntry assetId)
|
|||
}
|
||||
|
||||
if (mPreviewImage->getBitmapAsset().isNull())
|
||||
mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||
mPreviewImage->setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||
}
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeShapeAssetId);
|
||||
|
|
@ -991,4 +985,204 @@ void GuiInspectorTypeShapeAssetId::consoleInit()
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -77,9 +77,10 @@ public:
|
|||
};
|
||||
|
||||
static StringTableEntry smNoShapeAssetFallback;
|
||||
static AssetPtr<ShapeAsset> smNoShapeAssetFallbackAssetPtr;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -94,14 +95,6 @@ private:
|
|||
StringTableEntry mDiffuseImposterFileName;
|
||||
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;
|
||||
public:
|
||||
|
||||
|
|
@ -115,39 +108,17 @@ public:
|
|||
static void initPersistFields();
|
||||
void copyTo(SimObject* object) override;
|
||||
|
||||
virtual void setDataField(StringTableEntry slotName, StringTableEntry array, StringTableEntry value);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(ShapeAsset);
|
||||
|
||||
U32 load() override;
|
||||
bool preloadMaterialList();
|
||||
|
||||
TSShape* getShape() { load(); return mShape; }
|
||||
|
||||
Resource<TSShape> getShapeResource() { load(); return mShape; }
|
||||
|
||||
void SplitSequencePathAndName(String& srcPath, String& srcName);
|
||||
TSShape* getShape();
|
||||
Resource<TSShape> getShapeResource();
|
||||
|
||||
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 setShapeFile(const char* pScriptFile);
|
||||
|
|
@ -163,11 +134,18 @@ public:
|
|||
void setNormalImposterFile(const char* pImageFile);
|
||||
inline StringTableEntry getNormalImposterFile(void) const { return mNormalImposterFileName; };
|
||||
|
||||
|
||||
static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAsset>* shapeAsset);
|
||||
|
||||
static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
|
||||
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
|
||||
const char* generateCachedPreviewImage(S32 resolution, String overrideMaterial = "");
|
||||
#endif
|
||||
|
|
@ -201,6 +179,9 @@ DefineConsoleType(TypeShapeAssetId, String)
|
|||
DECLARE_STRUCT(AssetPtr<ShapeAsset>)
|
||||
DefineConsoleType(TypeShapeAssetPtr, AssetPtr<ShapeAsset>)
|
||||
|
||||
DECLARE_STRUCT(AssetRef<ShapeAsset>)
|
||||
DefineConsoleType(TypeShapeAssetRef, AssetRef<ShapeAsset>)
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
|
|
@ -236,255 +217,29 @@ public:
|
|||
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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ DebrisData::DebrisData()
|
|||
terminalVelocity = 0.0f;
|
||||
ignoreWater = true;
|
||||
|
||||
mShapeAsset.registerRefreshNotify(this);
|
||||
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
//#define TRACK_DEBRIS_DATA_CLONES
|
||||
|
|
@ -152,7 +152,7 @@ DebrisData::DebrisData(const DebrisData& other, bool temp_clone) : GameBaseData(
|
|||
terminalVelocity = other.terminalVelocity;
|
||||
ignoreWater = other.ignoreWater;
|
||||
|
||||
mShapeAsset = other.mShapeAsset;
|
||||
shapeAssetRef = other.shapeAssetRef;
|
||||
|
||||
textureName = other.textureName;
|
||||
explosionId = other.explosionId; // -- for pack/unpack of explosion ptr
|
||||
|
|
@ -190,8 +190,8 @@ DebrisData* DebrisData::cloneAndPerformSubstitutions(const SimObject* owner, S32
|
|||
}
|
||||
|
||||
void DebrisData::onPerformSubstitutions()
|
||||
{
|
||||
_setShape(_getShapeAssetId());
|
||||
{
|
||||
shapeAssetRef = shapeAssetRef.assetId;
|
||||
}
|
||||
|
||||
bool DebrisData::onAdd()
|
||||
|
|
@ -278,17 +278,21 @@ bool DebrisData::preload(bool server, String &errorStr)
|
|||
|
||||
if( server ) return true;
|
||||
|
||||
if (getShape())
|
||||
if (!shapeAssetRef.isNull())
|
||||
{
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(getShape(), !server);
|
||||
delete pDummy;
|
||||
if (!server && !getShape()->preloadMaterialList(getShapeFile()) && NetConnection::filesWereDownloaded())
|
||||
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("DebrisData(%s)::preload: Couldn't load shape \"%s\"", getName(), shapeAssetRef.assetId);
|
||||
return false;
|
||||
}
|
||||
else if (!mShapeAsset.isNull())
|
||||
{
|
||||
errorStr = String::ToString("DebrisData::load: Couldn't load shape \"%s\"", _getShapeAssetId());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -305,7 +309,8 @@ void DebrisData::initPersistFields()
|
|||
addGroup("Shapes");
|
||||
addField("texture", TypeString, Offset(textureName, DebrisData),
|
||||
"@brief Texture imagemap to use for this debris object.\n\nNot used any more.\n", AbstractClassRep::FIELD_HideInInspectors);
|
||||
INITPERSISTFIELD_SHAPEASSET_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");
|
||||
|
||||
addGroup("Particle Effects");
|
||||
|
|
@ -390,7 +395,7 @@ void DebrisData::packData(BitStream* stream)
|
|||
|
||||
stream->writeString( textureName );
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(Shape);
|
||||
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||
|
||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
|
|
@ -434,7 +439,7 @@ void DebrisData::unpackData(BitStream* stream)
|
|||
|
||||
textureName = stream->readSTString();
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
||||
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
|
||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
|
|
@ -677,18 +682,19 @@ bool Debris::onAdd()
|
|||
mFriction = mDataBlock->friction;
|
||||
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
|
||||
shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
mObjBox = shape->mBounds;
|
||||
}
|
||||
|
||||
if( mDataBlock->getShape())
|
||||
if(shape)
|
||||
{
|
||||
mShape = new TSShapeInstance( mDataBlock->getShape(), true);
|
||||
mShape = new TSShapeInstance(shape, true);
|
||||
}
|
||||
|
||||
if( mPart )
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ struct DebrisData : public GameBaseData, protected AssetPtrCallback
|
|||
F32 terminalVelocity; // max velocity magnitude
|
||||
bool ignoreWater;
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(DebrisData, Shape)
|
||||
AssetRef<ShapeAsset> shapeAssetRef;
|
||||
|
||||
StringTableEntry textureName;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
IMPLEMENT_CO_NETOBJECT_V1(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 "
|
||||
"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 "
|
||||
|
|
@ -74,7 +74,9 @@ void RenderShapeExample::initPersistFields()
|
|||
docsURL;
|
||||
Parent::initPersistFields();
|
||||
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" );
|
||||
|
||||
// SceneObject already handles exposing the transform
|
||||
|
|
@ -83,10 +85,6 @@ void RenderShapeExample::initPersistFields()
|
|||
void RenderShapeExample::inspectPostApply()
|
||||
{
|
||||
Parent::inspectPostApply();
|
||||
|
||||
// Flag the network mask to send the updates
|
||||
// to the client object
|
||||
setMaskBits( UpdateMask );
|
||||
}
|
||||
|
||||
bool RenderShapeExample::onAdd()
|
||||
|
|
@ -146,7 +144,7 @@ U32 RenderShapeExample::packUpdate( NetConnection *conn, U32 mask, BitStream *st
|
|||
// Write out any of the updated editable properties
|
||||
if ( stream->writeFlag( mask & UpdateMask ) )
|
||||
{
|
||||
PACK_ASSET_REFACTOR(conn, Shape);
|
||||
AssetDatabase.packUpdateAsset(conn, mask, stream, mShapeAssetRef.assetId);
|
||||
|
||||
// Allow the server object a chance to handle a new shape
|
||||
createShape();
|
||||
|
|
@ -170,7 +168,7 @@ void RenderShapeExample::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
|
||||
if ( stream->readFlag() ) // UpdateMask
|
||||
{
|
||||
UNPACK_ASSET_REFACTOR(conn, Shape);
|
||||
mShapeAssetRef = AssetDatabase.unpackUpdateAsset(conn, stream);
|
||||
|
||||
if ( isProperlyAdded() )
|
||||
createShape();
|
||||
|
|
@ -182,28 +180,35 @@ void RenderShapeExample::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
//-----------------------------------------------------------------------------
|
||||
void RenderShapeExample::createShape()
|
||||
{
|
||||
if ( mShapeAsset.isNull() )
|
||||
return;
|
||||
|
||||
// Clean up our previous shape
|
||||
if ( 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
|
||||
if ( isClientObject() &&
|
||||
!getShape()->preloadMaterialList(getShapeFile()) &&
|
||||
!mShapeAssetRef.assetPtr->preloadMaterialList() &&
|
||||
NetConnection::filesWereDownloaded() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the bounding box
|
||||
mObjBox = getShape()->mBounds;
|
||||
mObjBox = shape->mBounds;
|
||||
resetWorldBox();
|
||||
setRenderTransform(mObjToWorld);
|
||||
|
||||
// Create the TSShapeInstance
|
||||
mShapeInstance = new TSShapeInstance(getShape(), isClientObject() );
|
||||
mShapeInstance = new TSShapeInstance(shape, isClientObject() );
|
||||
}
|
||||
|
||||
void RenderShapeExample::prepRenderImage( SceneRenderState *state )
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class RenderShapeExample : public SceneObject
|
|||
//--------------------------------------------------------------------------
|
||||
// Rendering variables
|
||||
//--------------------------------------------------------------------------
|
||||
DECLARE_SHAPEASSET_REFACTOR(RenderShapeExample, Shape)
|
||||
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||
|
||||
// The actual shape instance
|
||||
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);
|
||||
playSpeed = 1.0f;
|
||||
|
||||
mExplosionShapeAsset.registerRefreshNotify(this);
|
||||
explosionShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
|
||||
explosionAnimation = -1;
|
||||
|
||||
|
|
@ -315,7 +315,7 @@ ExplosionData::ExplosionData(const ExplosionData& other, bool temp_clone) : Game
|
|||
particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr
|
||||
explosionScale = other.explosionScale;
|
||||
playSpeed = other.playSpeed;
|
||||
mExplosionShapeAsset = other.mExplosionShapeAsset;
|
||||
explosionShapeAssetRef = other.explosionShapeAssetRef;
|
||||
explosionAnimation = other.explosionAnimation; // -- from explosionShape sequence "ambient"
|
||||
dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) );
|
||||
dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs
|
||||
|
|
@ -360,8 +360,6 @@ ExplosionData::~ExplosionData()
|
|||
if (!isTempClone())
|
||||
return;
|
||||
|
||||
mExplosionShapeAsset.unregisterRefreshNotify();
|
||||
|
||||
// particleEmitter, emitterList[*], debrisList[*], explosionList[*] will delete themselves
|
||||
|
||||
#ifdef TRACK_EXPLOSION_DATA_CLONES
|
||||
|
|
@ -395,8 +393,9 @@ void ExplosionData::initPersistFields()
|
|||
{
|
||||
docsURL;
|
||||
addGroup("Shapes");
|
||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(ExplosionShape, ExplosionData, "@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.");
|
||||
ADD_FIELD("explosionShapeAsset", TypeShapeAssetRef, Offset(explosionShapeAssetRef, ExplosionData))
|
||||
.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");
|
||||
|
||||
addGroup("Sounds");
|
||||
|
|
@ -673,7 +672,7 @@ void ExplosionData::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(ExplosionShape);
|
||||
AssetDatabase.packDataAsset(stream, explosionShapeAssetRef.assetId);
|
||||
|
||||
//PACKDATA_SOUNDASSET(Sound);
|
||||
PACKDATA_ASSET(Sound);
|
||||
|
|
@ -778,7 +777,7 @@ void ExplosionData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(ExplosionShape);
|
||||
explosionShapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
|
||||
UNPACKDATA_ASSET(Sound);
|
||||
|
||||
|
|
@ -913,23 +912,21 @@ bool ExplosionData::preload(bool server, String &errorStr)
|
|||
}
|
||||
}
|
||||
|
||||
if (getExplosionShape()) {
|
||||
|
||||
// Resolve animations
|
||||
explosionAnimation = getExplosionShape()->findSequence("ambient");
|
||||
|
||||
// Preload textures with a dummy instance...
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(getExplosionShape(), !server);
|
||||
delete pDummy;
|
||||
|
||||
}
|
||||
else if (mExplosionShapeAsset.notNull())
|
||||
if (!explosionShapeAssetRef.isNull())
|
||||
{
|
||||
errorStr = String::ToString("ExplosionData::preload: Couldn't load shape \"%s\"", _getExplosionShapeAssetId());
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
explosionAnimation = -1;
|
||||
Resource<TSShape> shape = explosionShapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
{
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||
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;
|
||||
|
|
@ -1417,8 +1414,12 @@ bool Explosion::explode()
|
|||
launchDebris( mInitialNormal );
|
||||
spawnSubExplosions();
|
||||
|
||||
if (bool(mDataBlock->getExplosionShape()) && mDataBlock->explosionAnimation != -1) {
|
||||
mExplosionInstance = new TSShapeInstance(mDataBlock->getExplosionShape(), true);
|
||||
Resource<TSShape> eShape;
|
||||
if (mDataBlock->explosionShapeAssetRef.notNull())
|
||||
eShape = mDataBlock->explosionShapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
if (bool(eShape) && mDataBlock->explosionAnimation != -1) {
|
||||
mExplosionInstance = new TSShapeInstance(eShape, true);
|
||||
|
||||
mExplosionThread = mExplosionInstance->addThread();
|
||||
mExplosionInstance->setSequence(mExplosionThread, mDataBlock->explosionAnimation, 0);
|
||||
|
|
@ -1428,7 +1429,7 @@ bool Explosion::explode()
|
|||
mEndingMS = U32(mExplosionInstance->getScaledDuration(mExplosionThread) * 1000.0f);
|
||||
|
||||
mObjScale.convolve(mDataBlock->explosionScale);
|
||||
mObjBox = mDataBlock->getExplosionShape()->mBounds;
|
||||
mObjBox = eShape->mBounds;
|
||||
resetWorldBox();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class ExplosionData : public GameBaseData, protected AssetPtrCallback {
|
|||
Point3F explosionScale;
|
||||
F32 playSpeed;
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(ExplosionData, ExplosionShape)
|
||||
AssetRef<ShapeAsset> explosionShapeAssetRef;
|
||||
|
||||
S32 explosionAnimation;
|
||||
|
||||
|
|
|
|||
|
|
@ -513,9 +513,6 @@ GroundCover::GroundCover()
|
|||
mLayerAsset[i] = NULL;
|
||||
mLayerFile[i] = StringTable->EmptyString();
|
||||
|
||||
mShapeAsset[i] = NULL;
|
||||
mShapeFile[i] = StringTable->EmptyString();
|
||||
|
||||
mInvertLayer[i] = NULL;
|
||||
|
||||
mMinClumpCount[i] = 1;
|
||||
|
|
@ -526,7 +523,7 @@ GroundCover::GroundCover()
|
|||
mBillboardRects[i].point.set( 0.0f, 0.0f );
|
||||
mBillboardRects[i].extent.set( 1.0f, 1.0f );
|
||||
|
||||
mShapeAsset[i].registerRefreshNotify(this);
|
||||
mShapeAssetRef[i].assetPtr.registerRefreshNotify(this);
|
||||
|
||||
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." );
|
||||
|
||||
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.");
|
||||
|
||||
|
|
@ -773,10 +773,11 @@ U32 GroundCover::packUpdate( NetConnection *connection, U32 mask, BitStream *str
|
|||
stream->write( mBillboardRects[i].point.y );
|
||||
stream->write( mBillboardRects[i].extent.x );
|
||||
stream->write( mBillboardRects[i].extent.y );
|
||||
|
||||
AssetDatabase.packUpdateAsset(connection, mask, stream, mShapeAssetRef[i].assetId);
|
||||
}
|
||||
|
||||
PACK_ASSET_ARRAY_REFACTOR(connection, Layer, MAX_COVERTYPES)
|
||||
PACK_ASSET_ARRAY_REFACTOR(connection, Shape, MAX_COVERTYPES)
|
||||
|
||||
stream->writeFlag( mDebugRenderCells );
|
||||
stream->writeFlag( mDebugNoBillboards );
|
||||
|
|
@ -844,12 +845,12 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream )
|
|||
stream->read( &mBillboardRects[i].point.y );
|
||||
stream->read( &mBillboardRects[i].extent.x );
|
||||
stream->read( &mBillboardRects[i].extent.y );
|
||||
|
||||
mShapeAssetRef[i] = AssetDatabase.unpackUpdateAsset(connection, stream);
|
||||
}
|
||||
|
||||
UNPACK_ASSET_ARRAY_REFACTOR(connection, Layer, MAX_COVERTYPES)
|
||||
|
||||
UNPACK_ASSET_ARRAY_REFACTOR(connection, Shape, MAX_COVERTYPES)
|
||||
|
||||
mDebugRenderCells = stream->readFlag();
|
||||
mDebugNoBillboards = stream->readFlag();
|
||||
mDebugNoShapes = stream->readFlag();
|
||||
|
|
@ -895,17 +896,21 @@ void GroundCover::_initShapes()
|
|||
|
||||
for ( S32 i=0; i < MAX_COVERTYPES; i++ )
|
||||
{
|
||||
if ( mShapeAsset[i].isNull() || getShape(i) == NULL)
|
||||
if ( mShapeAssetRef[i].isNull())
|
||||
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;
|
||||
}
|
||||
|
||||
// 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];
|
||||
|
||||
/// The cover shape filenames.
|
||||
DECLARE_SHAPEASSET_ARRAY_NET_REFACTOR(GroundCover, Shape, MAX_COVERTYPES, -1)
|
||||
AssetRef<ShapeAsset> mShapeAssetRef[MAX_COVERTYPES];
|
||||
|
||||
/// The cover shape instances.
|
||||
TSShapeInstance* mShapeInstances[MAX_COVERTYPES];
|
||||
|
|
|
|||
|
|
@ -850,9 +850,6 @@ ConsoleSetType(TypeParticleList)
|
|||
const char* values = argv[0];
|
||||
numUnits = StringUnit::getUnitCount(values, " ");
|
||||
|
||||
if (numUnits > 1)
|
||||
bool dafgdf = true;
|
||||
|
||||
for (U32 i = 0; i < numUnits; i++)
|
||||
{
|
||||
const char* value = StringUnit::getUnit(values, i, " ");
|
||||
|
|
@ -877,7 +874,6 @@ ConsoleSetType(TypeParticleList)
|
|||
Con::printf("TypeParticleList vec results: %s", testVec[x]);
|
||||
}
|
||||
}
|
||||
bool test = false;
|
||||
}
|
||||
|
||||
#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.
|
||||
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;
|
||||
}
|
||||
|
||||
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->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:
|
||||
mOrbitPos = mModelInstance->getShape()->center;
|
||||
|
|
@ -284,7 +291,7 @@ void GuiMaterialPreview::setObjectModel(StringTableEntry modelName)
|
|||
lastRenderTime = Platform::getVirtualMilliseconds();
|
||||
}
|
||||
|
||||
void GuiMaterialPreview::deleteModel()
|
||||
void GuiMaterialPreview::deleteShape()
|
||||
{
|
||||
SAFE_DELETE(mModelInstance);
|
||||
runThread = 0;
|
||||
|
|
@ -499,17 +506,32 @@ ConsoleDocClass( GuiMaterialPreview,
|
|||
);
|
||||
|
||||
// Set the model.
|
||||
DefineEngineMethod(GuiMaterialPreview, setModel, void, ( const char* shapeName ),,
|
||||
"Sets the model to be displayed in this control\n\n"
|
||||
"@param shapeName Name of the model to display.\n")
|
||||
DefineEngineMethod(GuiMaterialPreview, setModel, void, ( const char* assetId ),,
|
||||
"Sets the shape to be displayed in this control\n\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, (),,
|
||||
"Deletes the preview model.\n"
|
||||
"@Deprecated\n\n")
|
||||
{
|
||||
object->deleteShape();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiMaterialPreview, deleteShape, void, (), ,
|
||||
"Deletes the preview model.\n")
|
||||
{
|
||||
object->deleteModel();
|
||||
object->deleteShape();
|
||||
}
|
||||
|
||||
// Set orbit distance around the model.
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ protected:
|
|||
|
||||
MouseState mMouseState;
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(GuiMaterialPreview, Model)
|
||||
DECLARE_SHAPEASSET_REFACTOR(GuiMaterialPreview, MountedModel)
|
||||
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||
AssetRef<ShapeAsset> mMountedShapeAssetRef;
|
||||
|
||||
TSShapeInstance* mModelInstance;
|
||||
TSShapeInstance* mMountedModelInstance;
|
||||
|
|
@ -110,8 +110,8 @@ public:
|
|||
// For changing the ambient light color.
|
||||
void setAmbientLightColor( F32 r, F32 g, F32 b );
|
||||
|
||||
void setObjectModel(const char * modelName);
|
||||
void deleteModel();
|
||||
void setObjectShape(const char * assetId);
|
||||
void deleteShape();
|
||||
void resetViewport();
|
||||
void setOrbitDistance(F32 distance);
|
||||
|
||||
|
|
|
|||
|
|
@ -134,11 +134,16 @@ GuiObjectView::~GuiObjectView()
|
|||
void GuiObjectView::initPersistFields()
|
||||
{
|
||||
docsURL;
|
||||
addGroup( "Model" );
|
||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Model, GuiObjectView, "The source shape asset.");
|
||||
addGroup( "Shape" );
|
||||
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 ),
|
||||
"The skin to use on the object model." );
|
||||
endGroup( "Model" );
|
||||
endGroup( "Shape" );
|
||||
|
||||
addGroup( "Animation" );
|
||||
|
||||
|
|
@ -147,8 +152,12 @@ void GuiObjectView::initPersistFields()
|
|||
|
||||
endGroup( "Animation" );
|
||||
|
||||
addGroup( "Mounting" );
|
||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(MountedModel, GuiObjectView, "The mounted shape asset.");
|
||||
addGroup( "Mounting" );
|
||||
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 ),
|
||||
"Skin name used on mounted shape file." );
|
||||
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;
|
||||
|
||||
// Load the shape if its not the one already set.
|
||||
if (modelName.c_str() != _getModelAssetId())
|
||||
_setModel(modelName.c_str());
|
||||
if (assetId.c_str() != mShapeAssetRef.assetId)
|
||||
mShapeAssetRef = assetId.c_str();
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
mModelInstance = new TSShapeInstance(getModel(), true );
|
||||
mModelInstance = new TSShapeInstance(shape, true );
|
||||
mModelInstance->resetMaterialList();
|
||||
mModelInstance->cloneMaterialList();
|
||||
|
||||
|
|
@ -357,12 +373,12 @@ bool GuiObjectView::setObjectModel( const String& modelName )
|
|||
mModelInstance->reSkin( mSkinName );
|
||||
|
||||
TSMaterialList* pMatList = mModelInstance->getMaterialList();
|
||||
pMatList->setTextureLookupPath(mModelAsset->getShapeFile());
|
||||
pMatList->setTextureLookupPath(mShapeAssetRef.assetPtr->getShapeFile());
|
||||
mModelInstance->initMaterialList();
|
||||
// Initialize camera values.
|
||||
|
||||
mOrbitPos = getModel()->center;
|
||||
mMinOrbitDist = getModel()->mRadius;
|
||||
mOrbitPos = shape->center;
|
||||
mMinOrbitDist = shape->mRadius;
|
||||
|
||||
// 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..
|
||||
if (modelName.c_str() != _getMountedModelAssetId())
|
||||
_setMountedModel(modelName.c_str());
|
||||
if (assetId.c_str() != mMountedShapeAssetRef.assetId)
|
||||
mMountedShapeAssetRef = assetId.c_str();
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
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->cloneMaterialList();
|
||||
|
||||
|
|
@ -628,22 +651,27 @@ void GuiObjectView::setLightDirection( const Point3F& direction )
|
|||
|
||||
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 )
|
||||
return;
|
||||
|
||||
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
// Look up sequence by name.
|
||||
|
||||
if( !mAnimationSeqName.isEmpty() )
|
||||
{
|
||||
mAnimationSeq = getModel()->findSequence( mAnimationSeqName );
|
||||
mAnimationSeq = shape->findSequence( mAnimationSeqName );
|
||||
|
||||
if( mAnimationSeq == -1 )
|
||||
{
|
||||
Con::errorf( "GuiObjectView::_initAnimation - Cannot find animation sequence '%s' on '%s'",
|
||||
mAnimationSeqName.c_str(),
|
||||
_getModelAssetId()
|
||||
mShapeAssetRef.assetId
|
||||
);
|
||||
|
||||
return;
|
||||
|
|
@ -654,11 +682,11 @@ void GuiObjectView::_initAnimation()
|
|||
|
||||
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'",
|
||||
mAnimationSeq,
|
||||
_getModelAssetId()
|
||||
mShapeAssetRef.assetId
|
||||
);
|
||||
|
||||
mAnimationSeq = -1;
|
||||
|
|
@ -682,6 +710,8 @@ void GuiObjectView::_initMount()
|
|||
|
||||
if( !mModelInstance)
|
||||
return;
|
||||
|
||||
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
mMountTransform.identity();
|
||||
|
||||
|
|
@ -689,12 +719,12 @@ void GuiObjectView::_initMount()
|
|||
|
||||
if( !mMountNodeName.isEmpty() )
|
||||
{
|
||||
mMountNode = getModel()->findNode( mMountNodeName );
|
||||
mMountNode = shape->findNode( mMountNodeName );
|
||||
if( mMountNode == -1 )
|
||||
{
|
||||
Con::errorf( "GuiObjectView::_initMount - No node '%s' on '%s'",
|
||||
mMountNodeName.c_str(),
|
||||
_getModelAssetId()
|
||||
mShapeAssetRef.assetId
|
||||
);
|
||||
|
||||
return;
|
||||
|
|
@ -703,24 +733,28 @@ void GuiObjectView::_initMount()
|
|||
|
||||
// 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'",
|
||||
mMountNode,
|
||||
_getModelAssetId()
|
||||
mShapeAssetRef.assetId
|
||||
);
|
||||
|
||||
mMountNode = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
Resource<TSShape> mountShape;
|
||||
if (mMountedShapeAssetRef.notNull())
|
||||
mountShape = mMountedShapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
// Look up node on the mounted model from
|
||||
// which to mount to the primary model's node.
|
||||
if (!getMountedModel()) return;
|
||||
S32 mountPoint = getMountedModel()->findNode( "mountPoint" );
|
||||
if (!mountShape) return;
|
||||
S32 mountPoint = mountShape->findNode( "mountPoint" );
|
||||
if( mountPoint != -1 )
|
||||
{
|
||||
getMountedModel()->getNodeWorldTransform(mountPoint, &mMountTransform),
|
||||
mountShape->getNodeWorldTransform(mountPoint, &mMountTransform),
|
||||
mMountTransform.inverse();
|
||||
}
|
||||
}
|
||||
|
|
@ -738,26 +772,28 @@ DefineEngineMethod( GuiObjectView, getModel, const char*, (),,
|
|||
"// Request the displayed model name from the GuiObjectView object.\n"
|
||||
"%modelName = %thisGuiObjectView.getModel();\n"
|
||||
"@endtsexample\n\n"
|
||||
"@return Name of the displayed model.\n\n"
|
||||
"@see GuiControl")
|
||||
"@return Id of the displayed shape.\n\n"
|
||||
"@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"
|
||||
"@param shapeName Name of the model to display.\n"
|
||||
"@param shapassetIdeName Name of the shapeAsset to display.\n"
|
||||
"@tsexample\n"
|
||||
"// Define the model we want to display\n"
|
||||
"%shapeName = \"gideon.dts\";\n\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.setModel(%shapeName);\n"
|
||||
"%thisGuiObjectView.setModel(%assetId);\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"
|
||||
"@endtsexample\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"
|
||||
"@param shapeName Name of the model to mount.\n"
|
||||
"@param assetId Name of the shapeAsset to mount.\n"
|
||||
"@tsexample\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"
|
||||
"%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"
|
||||
"@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"
|
||||
"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"
|
||||
"@tsexample\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"
|
||||
"%mountNodeIndexOrName = \"3\";\n"
|
||||
"//OR:\n"
|
||||
"%mountNodeIndexOrName = \"Face\";\n\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"
|
||||
"@see GuiControl")
|
||||
{
|
||||
|
|
@ -895,7 +992,7 @@ DefineEngineMethod( GuiObjectView, setMount, void, ( const char* shapeName, cons
|
|||
else
|
||||
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.
|
||||
DECLARE_SHAPEASSET_REFACTOR(GuiObjectView, Model)
|
||||
///Shape loaded for display.
|
||||
///
|
||||
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||
|
||||
TSShapeInstance* mModelInstance;
|
||||
/// Name of skin to use on model.
|
||||
|
|
@ -102,7 +103,7 @@ class GuiObjectView : public GuiTSCtrl, protected AssetPtrCallback
|
|||
/// @{
|
||||
|
||||
///Model to mount to the primary model.
|
||||
DECLARE_SHAPEASSET_REFACTOR(GuiObjectView, MountedModel)
|
||||
AssetRef<ShapeAsset> mMountedShapeAssetRef;
|
||||
TSShapeInstance* mMountedModelInstance;
|
||||
|
||||
///
|
||||
|
|
@ -176,8 +177,11 @@ class GuiObjectView : public GuiTSCtrl, protected AssetPtrCallback
|
|||
/// Set the skin to use on the primary model.
|
||||
void setSkin( const String& name );
|
||||
|
||||
/// Set the model to show in this view.
|
||||
bool setObjectModel( const String& modelName );
|
||||
/// Set the shape to show in this view.
|
||||
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 );
|
||||
|
||||
///
|
||||
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:
|
||||
void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override
|
||||
{
|
||||
if (getModel())
|
||||
setObjectModel(_getModelAssetId());
|
||||
if (mShapeAssetRef.notNull())
|
||||
setObjectShape(mShapeAssetRef.assetId);
|
||||
|
||||
if (getMountedModel())
|
||||
setMountedObject(_getMountedModelAssetId());
|
||||
if (mMountedShapeAssetRef.notNull())
|
||||
setMountedShape(mMountedShapeAssetRef.assetId);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -657,11 +657,18 @@ void Item::setTransform(const MatrixF& mat)
|
|||
//----------------------------------------------------------------------------
|
||||
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...
|
||||
//
|
||||
Point3F scaledVelocity = mVelocity * dt * TickSec;
|
||||
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,
|
||||
// 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;
|
||||
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)
|
||||
{
|
||||
if (mDataBlock->getShape())
|
||||
mShapeInstance = new TSShapeInstance(mDataBlock->getShape());
|
||||
if (mDataBlock->shapeAssetRef.notNull())
|
||||
{
|
||||
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
mShapeInstance = new TSShapeInstance(shape);
|
||||
}
|
||||
}
|
||||
}
|
||||
stream->read(&mSpawnName);
|
||||
|
|
|
|||
|
|
@ -74,12 +74,11 @@ PhysicsDebrisData::PhysicsDebrisData()
|
|||
lifetime = 5.0f;
|
||||
lifetimeVariance = 0.0f;
|
||||
|
||||
mShapeAsset.registerRefreshNotify(this);
|
||||
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
PhysicsDebrisData::~PhysicsDebrisData()
|
||||
{
|
||||
mShapeAsset.unregisterRefreshNotify();
|
||||
}
|
||||
|
||||
bool PhysicsDebrisData::onAdd()
|
||||
|
|
@ -97,17 +96,21 @@ bool PhysicsDebrisData::preload( bool server, String &errorStr )
|
|||
|
||||
if ( server ) return true;
|
||||
|
||||
if ( getShape() )
|
||||
if (!shapeAssetRef.isNull())
|
||||
{
|
||||
// Create a dummy shape to force the generation of shaders and materials
|
||||
// during the level load and not during gameplay.
|
||||
TSShapeInstance *pDummy = new TSShapeInstance( getShape(), !server);
|
||||
delete pDummy;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorStr = String::ToString("PhysicsDebrisData::load: Couldn't load shape asset \"%s\"", _getShapeAssetId());
|
||||
return false;
|
||||
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
{
|
||||
// Create a dummy shape to force the generation of shaders and materials
|
||||
// during the level load and not during gameplay.
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||
delete pDummy;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorStr = String::ToString("PhysicsDebrisData(%s)::preload: Couldn't load shape asset\"%s\"", getName(), shapeAssetRef.assetId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -118,8 +121,9 @@ void PhysicsDebrisData::initPersistFields()
|
|||
docsURL;
|
||||
addGroup( "Shapes" );
|
||||
|
||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, PhysicsDebrisData, "@brief Shape to use with this debris.\n\n"
|
||||
"Compatable with Live-Asset Reloading.");
|
||||
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, PhysicsDebrisData))
|
||||
.doc("@brief Shape to use with this debris.\n\n"
|
||||
"Compatable with Live-Asset Reloading.");
|
||||
|
||||
endGroup( "Shapes" );
|
||||
|
||||
|
|
@ -218,7 +222,7 @@ void PhysicsDebrisData::packData(BitStream* stream)
|
|||
stream->write( waterDampingScale );
|
||||
stream->write( buoyancyDensity );
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(Shape);
|
||||
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||
}
|
||||
|
||||
void PhysicsDebrisData::unpackData(BitStream* stream)
|
||||
|
|
@ -239,7 +243,7 @@ void PhysicsDebrisData::unpackData(BitStream* stream)
|
|||
stream->read( &waterDampingScale );
|
||||
stream->read( &buoyancyDensity );
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
||||
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
}
|
||||
|
||||
DefineEngineMethod( PhysicsDebrisData, preload, void, (), ,
|
||||
|
|
@ -250,7 +254,7 @@ DefineEngineMethod( PhysicsDebrisData, preload, void, (), ,
|
|||
{
|
||||
String errorStr;
|
||||
|
||||
object->_setShape(object->_getShapeAssetId());
|
||||
object->shapeAssetRef = object->shapeAssetRef.assetId;
|
||||
|
||||
if( !object->preload( false, errorStr ) )
|
||||
Con::errorf( "PhsysicsDebrisData::preload - error: %s", errorStr.c_str() );
|
||||
|
|
@ -356,6 +360,19 @@ bool PhysicsDebris::onAdd()
|
|||
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 ( mDataBlock->lifetime > 0.0f )
|
||||
{
|
||||
|
|
@ -364,7 +381,7 @@ bool PhysicsDebris::onAdd()
|
|||
}
|
||||
|
||||
// Setup our bounding box
|
||||
mObjBox = mDataBlock->getShape()->mBounds;
|
||||
mObjBox = shape->mBounds;
|
||||
resetWorldBox();
|
||||
|
||||
// Add it to the client scene.
|
||||
|
|
@ -627,7 +644,7 @@ void PhysicsDebris::_createFragments()
|
|||
if ( !mWorld )
|
||||
return;
|
||||
|
||||
TSShape *shape = mDataBlock->getShape();
|
||||
TSShape *shape = mDataBlock->shapeAssetRef.assetPtr->getShape();
|
||||
|
||||
mShapeInstance = new TSShapeInstance( shape, true );
|
||||
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
|
||||
// 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;
|
||||
itr = shape->nodes[itr].firstChild;
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public:
|
|||
/// Is rendererd during shadow passes.
|
||||
bool castShadows;
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(PhysicsDebrisData, Shape)
|
||||
AssetRef<ShapeAsset> shapeAssetRef;
|
||||
|
||||
PhysicsDebrisData();
|
||||
virtual ~PhysicsDebrisData();
|
||||
|
|
|
|||
|
|
@ -78,12 +78,11 @@ PhysicsShapeData::PhysicsShapeData()
|
|||
buoyancyDensity( 0.0f ),
|
||||
simType( SimType_ClientServer )
|
||||
{
|
||||
mShapeAsset.registerRefreshNotify(this);
|
||||
shapeAsset.assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
PhysicsShapeData::~PhysicsShapeData()
|
||||
{
|
||||
mShapeAsset.unregisterRefreshNotify();
|
||||
}
|
||||
|
||||
void PhysicsShapeData::initPersistFields()
|
||||
|
|
@ -91,8 +90,9 @@ void PhysicsShapeData::initPersistFields()
|
|||
docsURL;
|
||||
addGroup("Shapes");
|
||||
|
||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, PhysicsShapeData, "@brief Shape asset to be used with this physics object.\n\n"
|
||||
"Compatable with Live-Asset Reloading. ")
|
||||
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAsset, PhysicsShapeData))
|
||||
. 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 ),
|
||||
"@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 );
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(Shape);
|
||||
AssetDatabase.packDataAsset(stream, shapeAsset.assetId);
|
||||
|
||||
stream->write( mass );
|
||||
stream->write( dynamicFriction );
|
||||
|
|
@ -205,7 +205,7 @@ void PhysicsShapeData::unpackData( BitStream *stream )
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
||||
shapeAsset = AssetDatabase.unpackDataAsset(stream);
|
||||
|
||||
stream->read( &mass );
|
||||
stream->read( &dynamicFriction );
|
||||
|
|
@ -242,27 +242,28 @@ void PhysicsShapeData::onRemove()
|
|||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ( path != Path(mShapeAsset->getShapeFile()) )
|
||||
|
||||
if ( path != Path(shapeAsset.assetPtr->getShapeFile()) )
|
||||
return;
|
||||
|
||||
_setShape(_getShapeAssetId());
|
||||
shapeAsset = shapeAsset.assetId;
|
||||
|
||||
// Reload the changed shape.
|
||||
PhysicsCollisionRef reloadcolShape;
|
||||
|
||||
if ( !getShape())
|
||||
Resource<TSShape> shape = shapeAsset.assetPtr->getShapeResource();
|
||||
if ( !shape)
|
||||
{
|
||||
Con::warnf( ConsoleLogEntry::General, "PhysicsShapeData::_onResourceChanged: Could not reload %s.", path.getFileName().c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
// Reload the collision shape.
|
||||
reloadcolShape = getShape()->buildColShape( false, Point3F::One );
|
||||
reloadcolShape = shape->buildColShape( false, Point3F::One );
|
||||
|
||||
if ( bool(reloadcolShape))
|
||||
colShape = reloadcolShape;
|
||||
|
|
@ -283,34 +284,41 @@ bool PhysicsShapeData::preload( bool server, String &errorBuffer )
|
|||
return false;
|
||||
}
|
||||
|
||||
bool shapeError = false;
|
||||
|
||||
if (getShape())
|
||||
if (shapeAsset.isNull())
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
// we need to fail... can't have a shape without collision.
|
||||
if ( !colShape )
|
||||
{
|
||||
//no collision so we create a simple box collision shape from the shapes bounds and alert the user
|
||||
Con::warnf( "PhysicsShapeData::preload - No collision found for shape '%s', auto-creating one", _getShapeAssetId());
|
||||
Point3F halfWidth = getShape()->mBounds.getExtents() * 0.5f;
|
||||
Con::warnf( "PhysicsShapeData::preload - No collision found for shape '%s', auto-creating one", shapeAsset.assetId);
|
||||
Point3F halfWidth = shape->mBounds.getExtents() * 0.5f;
|
||||
colShape = PHYSICSMGR->createCollision();
|
||||
MatrixF centerXfm(true);
|
||||
centerXfm.setPosition(getShape()->mBounds.getCenter());
|
||||
centerXfm.setPosition(shape->mBounds.getCenter());
|
||||
colShape->addBox(halfWidth, centerXfm);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -703,11 +711,12 @@ bool PhysicsShape::_createShape()
|
|||
mAmbientSeq = -1;
|
||||
|
||||
PhysicsShapeData *db = getDataBlock();
|
||||
if ( !db || !db->getShape())
|
||||
Resource<TSShape> shape;
|
||||
if ( !db || !(shape = db->shapeAsset.assetPtr->getShapeResource()))
|
||||
return false;
|
||||
|
||||
// Set the world box.
|
||||
mObjBox = db->getShape()->mBounds;
|
||||
mObjBox = shape->mBounds;
|
||||
resetWorldBox();
|
||||
|
||||
// If this is the server and its a client only simulation
|
||||
|
|
@ -721,11 +730,11 @@ bool PhysicsShape::_createShape()
|
|||
}
|
||||
|
||||
// Create the shape instance.
|
||||
mShapeInst = new TSShapeInstance( db->getShape(), isClientObject() );
|
||||
mShapeInst = new TSShapeInstance(shape, isClientObject() );
|
||||
|
||||
if ( isClientObject() )
|
||||
{
|
||||
mAmbientSeq = db->getShape()->findSequence( "ambient" );
|
||||
mAmbientSeq = shape->findSequence( "ambient" );
|
||||
_initAmbient();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(PhysicsShapeData, Shape)
|
||||
AssetRef<ShapeAsset> shapeAsset;
|
||||
|
||||
/// The shared unscaled collision shape.
|
||||
PhysicsCollisionRef colShape;
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ PlayerData::PlayerData()
|
|||
imageAnimPrefixFP = StringTable->EmptyString();
|
||||
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
||||
{
|
||||
mShapeFPAsset[i].registerRefreshNotify(this);
|
||||
shapeFPAssetRef[i].assetPtr.registerRefreshNotify(this);
|
||||
mCRCFP[i] = 0;
|
||||
mValidShapeFP[i] = false;
|
||||
}
|
||||
|
|
@ -506,12 +506,16 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
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
|
||||
// setup animations and sequences.
|
||||
if (getShape())
|
||||
if (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();
|
||||
|
||||
// Extract ground transform velocity from animations
|
||||
|
|
@ -522,7 +526,7 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
ActionAnimationDef *sp = &ActionAnimationList[i];
|
||||
dp->name = sp->name;
|
||||
dp->dir.set(sp->dir.x,sp->dir.y,sp->dir.z);
|
||||
dp->sequence = getShape()->findSequence(sp->name);
|
||||
dp->sequence = shape->findSequence(sp->name);
|
||||
|
||||
// If this is a sprint action and is missing a sequence, attempt to use
|
||||
// the standard run ones.
|
||||
|
|
@ -530,7 +534,7 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
{
|
||||
S32 offset = i-SprintRootAnim;
|
||||
ActionAnimationDef *standDef = &ActionAnimationList[RootAnim+offset];
|
||||
dp->sequence = getShape()->findSequence(standDef->name);
|
||||
dp->sequence = shape->findSequence(standDef->name);
|
||||
}
|
||||
|
||||
dp->velocityScale = true;
|
||||
|
|
@ -538,12 +542,12 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
if (dp->sequence != -1)
|
||||
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))
|
||||
{
|
||||
dp->sequence = b;
|
||||
dp->name = getShape()->getName(getShape()->sequences[b].nameIndex);
|
||||
dp->name = shape->getName(shape->sequences[b].nameIndex);
|
||||
dp->velocityScale = false;
|
||||
getGroundInfo(si,thread,dp++);
|
||||
}
|
||||
|
|
@ -560,17 +564,17 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
lookAction = c;
|
||||
|
||||
// Resolve spine
|
||||
spineNode[0] = getShape()->findNode("Bip01 Pelvis");
|
||||
spineNode[1] = getShape()->findNode("Bip01 Spine");
|
||||
spineNode[2] = getShape()->findNode("Bip01 Spine1");
|
||||
spineNode[3] = getShape()->findNode("Bip01 Spine2");
|
||||
spineNode[4] = getShape()->findNode("Bip01 Neck");
|
||||
spineNode[5] = getShape()->findNode("Bip01 Head");
|
||||
spineNode[0] = shape->findNode("Bip01 Pelvis");
|
||||
spineNode[1] = shape->findNode("Bip01 Spine");
|
||||
spineNode[2] = shape->findNode("Bip01 Spine1");
|
||||
spineNode[3] = shape->findNode("Bip01 Spine2");
|
||||
spineNode[4] = shape->findNode("Bip01 Neck");
|
||||
spineNode[5] = shape->findNode("Bip01 Head");
|
||||
|
||||
// Recoil animations
|
||||
recoilSequence[0] = getShape()->findSequence("light_recoil");
|
||||
recoilSequence[1] = getShape()->findSequence("medium_recoil");
|
||||
recoilSequence[2] = getShape()->findSequence("heavy_recoil");
|
||||
recoilSequence[0] = shape->findSequence("light_recoil");
|
||||
recoilSequence[1] = shape->findSequence("medium_recoil");
|
||||
recoilSequence[2] = shape->findSequence("heavy_recoil");
|
||||
}
|
||||
|
||||
// Convert pickupRadius to a delta of boundingBox
|
||||
|
|
@ -613,40 +617,44 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (!server && !getShapeFP(i)->preloadMaterialList(getShapeFPFile(i)) && NetConnection::filesWereDownloaded())
|
||||
shapeError = true;
|
||||
|
||||
if (computeCRC)
|
||||
if (server)
|
||||
mCRCFP[i] = fileRef->getChecksum();
|
||||
else if (mCRCFP[i] != fileRef->getChecksum())
|
||||
{
|
||||
Con::printf("Validation required for mounted image %d shape: %s", i, _getShapeFPAssetId(i));
|
||||
|
||||
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;
|
||||
}
|
||||
errorStr = String::ToString("PlayerData: Mounted image %d shape \"%s\" does not match version on server.", i, shapeFPAssetRef[i].assetId);
|
||||
return false;
|
||||
}
|
||||
|
||||
mValidShapeFP[i] = true;
|
||||
}
|
||||
|
||||
mValidShapeFP[i] = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1150,7 +1158,9 @@ void PlayerData::initPersistFields()
|
|||
// Mounted images arrays
|
||||
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 "
|
||||
"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");
|
||||
|
|
@ -1357,9 +1367,9 @@ void PlayerData::packData(BitStream* stream)
|
|||
{
|
||||
stream->write(mCRCFP[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PACKDATA_ASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages)
|
||||
AssetDatabase.packDataAsset(stream, shapeFPAssetRef[i].assetId);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerData::unpackData(BitStream* stream)
|
||||
|
|
@ -1539,9 +1549,10 @@ void PlayerData::unpackData(BitStream* stream)
|
|||
{
|
||||
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)
|
||||
{
|
||||
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();
|
||||
|
||||
|
|
@ -6166,6 +6181,13 @@ void Player::buildConvex(const Box3F& box, Convex* convex)
|
|||
|
||||
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
|
||||
// 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
|
||||
|
|
@ -6173,7 +6195,7 @@ void Player::updateWorkingCollisionSet()
|
|||
// box by the possible movement in that tick.
|
||||
Point3F scaledVelocity = mVelocity * TickSec;
|
||||
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,
|
||||
// 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)
|
||||
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;
|
||||
if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size())
|
||||
return mDataBlock->getShape()->sequences[seq_id].duration;
|
||||
if (seq_id >= 0 && seq_id < shape->sequences.size())
|
||||
return shape->sequences[seq_id].duration;
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
|
@ -7584,10 +7614,16 @@ bool Player::isBlendAnimation(const char* name)
|
|||
if (anim_id == BAD_ANIM_ID)
|
||||
return false;
|
||||
|
||||
S32 seq_id = mDataBlock->actionList[anim_id].sequence;
|
||||
if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size())
|
||||
return mDataBlock->getShape()->sequences[seq_id].isBlend();
|
||||
if (mDataBlock->shapeAssetRef.isNull())
|
||||
return false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
/// need to.
|
||||
|
||||
DECLARE_SHAPEASSET_ARRAY_REFACTOR(PlayerData, ShapeFP, ShapeBase::MaxMountedImages)
|
||||
AssetRef<ShapeAsset> shapeFPAssetRef[ShapeBase::MaxMountedImages];
|
||||
|
||||
StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify
|
||||
/// animation sequences played in first person. [optional]
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ U32 Projectile::smProjectileWarpTicks = 5;
|
|||
//
|
||||
ProjectileData::ProjectileData()
|
||||
{
|
||||
mProjectileShapeAsset.registerRefreshNotify(this);
|
||||
projectileShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
|
||||
INIT_ASSET(ProjectileSound);
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : G
|
|||
CLONE_ASSET(ProjectileSound);
|
||||
lightDesc = other.lightDesc;
|
||||
lightDescId = other.lightDescId; // -- for pack/unpack of lightDesc ptr
|
||||
mProjectileShapeAsset = other.mProjectileShapeAsset;// -- TSShape loads using mProjectileShapeName
|
||||
projectileShapeAssetRef = other.projectileShapeAssetRef;// -- TSShape loads using projectileShapeAssetRef
|
||||
activateSeq = other.activateSeq; // -- from projectileShape sequence "activate"
|
||||
maintainSeq = other.maintainSeq; // -- from projectileShape sequence "maintain"
|
||||
particleEmitter = other.particleEmitter;
|
||||
|
|
@ -237,7 +237,8 @@ void ProjectileData::initPersistFields()
|
|||
{
|
||||
docsURL;
|
||||
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),
|
||||
"@brief Scale to apply to the projectile's size.\n\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);
|
||||
}
|
||||
|
||||
if (getProjectileShape())
|
||||
if (!projectileShapeAssetRef.isNull())
|
||||
{
|
||||
activateSeq = getProjectileShape()->findSequence("activate");
|
||||
maintainSeq = getProjectileShape()->findSequence("maintain");
|
||||
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(getProjectileShape(), !server);
|
||||
delete pDummy;
|
||||
}
|
||||
else if (mProjectileShapeAsset.notNull())
|
||||
{
|
||||
errorStr = String::ToString("ProjectileData::preload: Couldn't load shape \"%s\"", _getProjectileShapeAssetId());
|
||||
return false;
|
||||
Resource<TSShape> shape = projectileShapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
{
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||
delete pDummy;
|
||||
if (!server && !projectileShapeAssetRef.assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorStr = String::ToString("ProjectileData(%s)::preload: Couldn't load shape \"%s\"", getName(), projectileShapeAssetRef.assetId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -444,7 +448,7 @@ void ProjectileData::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(ProjectileShape);
|
||||
AssetDatabase.packDataAsset(stream, projectileShapeAssetRef.assetId);;
|
||||
|
||||
stream->writeFlag(faceViewer);
|
||||
if(stream->writeFlag(scale.x != 1 || scale.y != 1 || scale.z != 1))
|
||||
|
|
@ -509,7 +513,7 @@ void ProjectileData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(ProjectileShape);
|
||||
projectileShapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
|
||||
faceViewer = stream->readFlag();
|
||||
if(stream->readFlag())
|
||||
|
|
@ -808,6 +812,8 @@ bool Projectile::onAdd()
|
|||
return false;
|
||||
}
|
||||
|
||||
Resource<TSShape> pShape;
|
||||
|
||||
if (isServerObject())
|
||||
{
|
||||
ShapeBase* ptr;
|
||||
|
|
@ -835,15 +841,19 @@ bool Projectile::onAdd()
|
|||
}
|
||||
else
|
||||
{
|
||||
if (bool(mDataBlock->getProjectileShape()))
|
||||
if (mDataBlock->projectileShapeAssetRef.notNull())
|
||||
{
|
||||
mProjectileShape = new TSShapeInstance(mDataBlock->getProjectileShape(), isClientObject());
|
||||
|
||||
if (mDataBlock->activateSeq != -1)
|
||||
pShape = mDataBlock->projectileShapeAssetRef.assetPtr->getShapeResource();
|
||||
if (pShape)
|
||||
{
|
||||
mActivateThread = mProjectileShape->addThread();
|
||||
mProjectileShape->setTimeScale(mActivateThread, 1);
|
||||
mProjectileShape->setSequence(mActivateThread, mDataBlock->activateSeq, 0);
|
||||
mProjectileShape = new TSShapeInstance(pShape, isClientObject());
|
||||
|
||||
if (mDataBlock->activateSeq != -1)
|
||||
{
|
||||
mActivateThread = mProjectileShape->addThread();
|
||||
mProjectileShape->setTimeScale(mActivateThread, 1);
|
||||
mProjectileShape->setSequence(mActivateThread, mDataBlock->activateSeq, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mDataBlock->particleEmitter != NULL)
|
||||
|
|
@ -876,8 +886,8 @@ bool Projectile::onAdd()
|
|||
processAfter(mSourceObject);
|
||||
|
||||
// Setup our bounding box
|
||||
if (bool(mDataBlock->getProjectileShape()) == true)
|
||||
mObjBox = mDataBlock->getProjectileShape()->mBounds;
|
||||
if (bool(pShape) == true)
|
||||
mObjBox = pShape->mBounds;
|
||||
else
|
||||
mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0));
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ protected:
|
|||
bool onAdd() override;
|
||||
|
||||
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
|
||||
bool faceViewer;
|
||||
|
|
|
|||
|
|
@ -144,11 +144,15 @@ bool ProximityMineData::preload( bool server, String& errorStr )
|
|||
}
|
||||
}
|
||||
|
||||
if ( getShape() )
|
||||
if (shapeAssetRef.notNull())
|
||||
{
|
||||
// Lookup animation sequences
|
||||
armingSequence = getShape()->findSequence( "armed" );
|
||||
triggerSequence = getShape()->findSequence( "triggered" );
|
||||
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
{
|
||||
// Lookup animation sequences
|
||||
armingSequence = shape->findSequence("armed");
|
||||
triggerSequence = shape->findSequence("triggered");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -281,7 +281,8 @@ RigidShapeData::RigidShapeData()
|
|||
|
||||
dustTrailEmitter = NULL;
|
||||
dustTrailID = 0;
|
||||
_setShape(ShapeAsset::smNoShapeAssetFallback);
|
||||
|
||||
shapeAssetRef = ShapeAsset::smNoShapeAssetFallback;
|
||||
}
|
||||
|
||||
RigidShapeData::~RigidShapeData()
|
||||
|
|
@ -340,7 +341,7 @@ bool RigidShapeData::preload(bool server, String &errorStr)
|
|||
if (!collisionDetails.size() || collisionDetails[0] == -1)
|
||||
{
|
||||
Con::errorf("RigidShapeData::preload failed: Rigid shapes must define a collision-1 detail");
|
||||
errorStr = String::ToString("RigidShapeData: Couldn't load shape asset \"%s\"", getShapeAsset().getAssetId());
|
||||
errorStr = String::ToString("RigidShapeData: Couldn't load shape asset \"%s\"", shapeAssetRef.assetId);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1443,13 +1444,20 @@ void RigidShape::updateWorkingCollisionSet(const U32 mask)
|
|||
{
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
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
|
||||
convexBox.minExtents -= Point3F(l, l, l);
|
||||
convexBox.maxExtents += Point3F(l, l, l);
|
||||
|
|
|
|||
|
|
@ -205,8 +205,8 @@ ShapeBaseData::ShapeBaseData()
|
|||
remap_txr_tags = NULL;
|
||||
remap_buffer = NULL;
|
||||
silent_bbox_check = false;
|
||||
mShapeAsset.registerRefreshNotify(this);
|
||||
mDebrisShapeAsset.registerRefreshNotify(this);
|
||||
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
debrisShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
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;
|
||||
shadowSphereAdjust = other.shadowSphereAdjust;
|
||||
cloakTexName = other.cloakTexName;
|
||||
mShapeAsset = other.mShapeAsset;
|
||||
shapeAssetRef = other.shapeAssetRef;
|
||||
cubeDescName = other.cubeDescName;
|
||||
cubeDescId = other.cubeDescId;
|
||||
reflectorDesc = other.reflectorDesc;
|
||||
debris = other.debris;
|
||||
debrisID = other.debrisID; // -- for pack/unpack of debris ptr
|
||||
mDebrisShapeAsset = other.mDebrisShapeAsset;
|
||||
debrisShapeAssetRef = other.debrisShapeAssetRef;
|
||||
explosion = other.explosion;
|
||||
explosionID = other.explosionID; // -- for pack/unpack of explosion ptr
|
||||
underwaterExplosion = other.underwaterExplosion;
|
||||
|
|
@ -299,12 +299,8 @@ static ShapeBaseDataProto gShapeBaseDataProto;
|
|||
|
||||
ShapeBaseData::~ShapeBaseData()
|
||||
{
|
||||
|
||||
if (remap_buffer && !isTempClone())
|
||||
dFree(remap_buffer);
|
||||
|
||||
mShapeAsset.unregisterRefreshNotify();
|
||||
mDebrisShapeAsset.unregisterRefreshNotify();
|
||||
}
|
||||
|
||||
bool ShapeBaseData::preload(bool server, String &errorStr)
|
||||
|
|
@ -350,32 +346,38 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
|||
"ShapeBaseData::preload: invalid debris data");
|
||||
}
|
||||
|
||||
if(getDebrisShape())
|
||||
if (debrisShapeAssetRef.notNull())
|
||||
{
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(getDebrisShape(), !server);
|
||||
delete pDummy;
|
||||
Resource<TSShape> dShape = debrisShapeAssetRef.assetPtr->getShapeResource();
|
||||
if (dShape)
|
||||
{
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(dShape, !server);
|
||||
delete pDummy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Resource<TSShape> shape;
|
||||
|
||||
S32 i;
|
||||
if (getShape())
|
||||
if (shapeAssetRef.notNull() && (shape = shapeAssetRef.assetPtr->getShapeResource()))
|
||||
{
|
||||
//mShapeAsset->load();
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(shapeAssetRef.assetPtr);
|
||||
if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback)
|
||||
{
|
||||
if (!server && !getShape()->preloadMaterialList(getShapeFile()) && NetConnection::filesWereDownloaded())
|
||||
if (!server && !shapeAssetRef.assetPtr->preloadMaterialList() && NetConnection::filesWereDownloaded())
|
||||
shapeError = true;
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -383,36 +385,36 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
|||
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;
|
||||
}
|
||||
}
|
||||
// Resolve details and camera node indexes.
|
||||
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)
|
||||
{
|
||||
collisionDetails.push_back(i);
|
||||
collisionBounds.increment();
|
||||
|
||||
getShape()->computeBounds(collisionDetails.last(), collisionBounds.last());
|
||||
getShape()->getAccelerator(collisionDetails.last());
|
||||
shape->computeBounds(collisionDetails.last(), collisionBounds.last());
|
||||
shape->getAccelerator(collisionDetails.last());
|
||||
|
||||
if (!getShape()->mBounds.isContained(collisionBounds.last()))
|
||||
if (!shape->mBounds.isContained(collisionBounds.last()))
|
||||
{
|
||||
if (!silent_bbox_check)
|
||||
Con::warnf("Warning: shape asset %s collision detail %d (Collision-%d) bounds exceed that of shape.", mShapeAsset.getAssetId(), collisionDetails.size() - 1, collisionDetails.last());
|
||||
collisionBounds.last() = getShape()->mBounds;
|
||||
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() = shape->mBounds;
|
||||
}
|
||||
else if (collisionBounds.last().isValidBox() == false)
|
||||
{
|
||||
if (!silent_bbox_check)
|
||||
Con::errorf("Error: shape asset %s-collision detail %d (Collision-%d) bounds box invalid!", mShapeAsset.getAssetId(), collisionDetails.size() - 1, collisionDetails.last());
|
||||
collisionBounds.last() = getShape()->mBounds;
|
||||
Con::errorf("Error: shape asset %s-collision detail %d (Collision-%d) bounds box invalid!", shapeAssetRef.assetId, collisionDetails.size() - 1, collisionDetails.last());
|
||||
collisionBounds.last() = shape->mBounds;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
String buff = String::ToString("LOS-%d", i + 1 + MaxCollisionShapes);
|
||||
U32 los = getShape()->findDetail(buff);
|
||||
U32 los = shape->findDetail(buff);
|
||||
if (los == -1)
|
||||
LOSDetails.last() = i;
|
||||
else
|
||||
|
|
@ -433,9 +435,9 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
|||
// Snag any "unmatched" LOS details
|
||||
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)
|
||||
{
|
||||
|
|
@ -455,12 +457,12 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
|||
}
|
||||
}
|
||||
|
||||
debrisDetail = getShape()->findDetail("Debris-17");
|
||||
eyeNode = getShape()->findNode("eye");
|
||||
earNode = getShape()->findNode("ear");
|
||||
debrisDetail = shape->findDetail("Debris-17");
|
||||
eyeNode = shape->findNode("eye");
|
||||
earNode = shape->findNode("ear");
|
||||
if (earNode == -1)
|
||||
earNode = eyeNode;
|
||||
cameraNode = getShape()->findNode("cam");
|
||||
cameraNode = shape->findNode("cam");
|
||||
if (cameraNode == -1)
|
||||
cameraNode = eyeNode;
|
||||
|
||||
|
|
@ -468,18 +470,18 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
|||
for (i = 0; i < SceneObject::NumMountPoints; i++) {
|
||||
char fullName[256];
|
||||
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...
|
||||
mountPointNode[AIRepairNode] = getShape()->findNode("AIRepairNode");
|
||||
mountPointNode[AIRepairNode] = shape->findNode("AIRepairNode");
|
||||
|
||||
//
|
||||
hulkSequence = getShape()->findSequence("Visibility");
|
||||
damageSequence = getShape()->findSequence("Damage");
|
||||
hulkSequence = shape->findSequence("Visibility");
|
||||
damageSequence = shape->findSequence("Damage");
|
||||
|
||||
//
|
||||
F32 w = getShape()->mBounds.len_y() / 2;
|
||||
F32 w = shape->mBounds.len_y() / 2;
|
||||
if (cameraMaxDist < w)
|
||||
cameraMaxDist = w;
|
||||
// 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
|
||||
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)
|
||||
|
|
@ -557,12 +559,14 @@ void ShapeBaseData::initPersistFields()
|
|||
{
|
||||
docsURL;
|
||||
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),
|
||||
"If true, verify that the CRC of the client's shape model matches the "
|
||||
"server's CRC for the shape model when loaded by the client.");
|
||||
addField("silentBBoxValidation", TypeBool, Offset(silent_bbox_check, ShapeBaseData));
|
||||
INITPERSISTFIELD_SHAPEASSET_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" );
|
||||
addGroup("Movement");
|
||||
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")
|
||||
{
|
||||
if (bool(object->getShape()) == false)
|
||||
if (object->shapeAssetRef.isNull())
|
||||
return false;
|
||||
|
||||
Resource<TSShape> shape = object->shapeAssetRef.assetPtr->getShapeResource();
|
||||
if (bool(shape) == false)
|
||||
return false;
|
||||
|
||||
MatrixF mat = txfm.getMatrix();
|
||||
|
||||
Box3F objBox = object->getShape()->mBounds;
|
||||
Box3F objBox = shape->mBounds;
|
||||
Point3F boxCenter = (objBox.minExtents + objBox.maxExtents) * 0.5f;
|
||||
objBox.minExtents = boxCenter + (objBox.minExtents - boxCenter) * 0.9f;
|
||||
objBox.maxExtents = boxCenter + (objBox.maxExtents - boxCenter) * 0.9f;
|
||||
|
|
@ -766,8 +774,8 @@ void ShapeBaseData::packData(BitStream* stream)
|
|||
stream->write(shadowProjectionDistance);
|
||||
stream->write(shadowSphereAdjust);
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(Shape);
|
||||
PACKDATA_ASSET_REFACTOR(DebrisShape);
|
||||
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||
AssetDatabase.packDataAsset(stream, debrisShapeAssetRef.assetId);
|
||||
|
||||
stream->writeString(cloakTexName);
|
||||
if(stream->writeFlag(mass != gShapeBaseDataProto.mass))
|
||||
|
|
@ -843,8 +851,8 @@ void ShapeBaseData::unpackData(BitStream* stream)
|
|||
stream->read(&shadowProjectionDistance);
|
||||
stream->read(&shadowSphereAdjust);
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
||||
UNPACKDATA_ASSET_REFACTOR(DebrisShape);
|
||||
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
debrisShapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
|
||||
cloakTexName = stream->readSTString();
|
||||
if(stream->readFlag())
|
||||
|
|
@ -1224,12 +1232,14 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
|
||||
// Even if loadShape succeeds, there may not actually be
|
||||
// a shape assigned to this object.
|
||||
if (bool(mDataBlock->getShape())) {
|
||||
Resource<TSShape> shape;
|
||||
if (bool(mDataBlock->shapeAssetRef.notNull() && (shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource())))
|
||||
{
|
||||
delete mShapeInstance;
|
||||
if (isClientObject() && mDataBlock->txr_tag_remappings.size() > 0)
|
||||
{
|
||||
// temporarily substitute material tags with alternates
|
||||
TSMaterialList* mat_list = mDataBlock->getShape()->materialList;
|
||||
TSMaterialList* mat_list = shape->materialList;
|
||||
if (mat_list)
|
||||
{
|
||||
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())
|
||||
{
|
||||
mShapeInstance->cloneMaterialList();
|
||||
|
|
@ -1257,7 +1267,7 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
// restore the material tags to original form
|
||||
if (mDataBlock->txr_tag_remappings.size() > 0)
|
||||
{
|
||||
TSMaterialList* mat_list = mDataBlock->getShape()->materialList;
|
||||
TSMaterialList* mat_list = shape->materialList;
|
||||
if (mat_list)
|
||||
{
|
||||
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();
|
||||
|
||||
// Set the initial mesh hidden state.
|
||||
mMeshHidden.setSize(mDataBlock->getShape()->objects.size());
|
||||
mMeshHidden.setSize(shape->objects.size());
|
||||
mMeshHidden.clear();
|
||||
|
||||
// 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?");
|
||||
|
||||
const TSShape* prevShape = prevDB->getShape();
|
||||
const TSShape* prevShape = prevDB->shapeAssetRef.assetPtr->getShape();
|
||||
const TSShape::Sequence& prevSeq = prevShape->sequences[st.sequence];
|
||||
const String& prevSeqName = prevShape->names[prevSeq.nameIndex];
|
||||
|
||||
st.sequence = mDataBlock->getShape()->findSequence(prevSeqName);
|
||||
st.sequence = shape->findSequence(prevSeqName);
|
||||
|
||||
if (st.sequence != -1)
|
||||
{
|
||||
|
|
@ -1991,13 +2001,14 @@ void ShapeBase::blowUp()
|
|||
|
||||
TSShapeInstance *debShape = NULL;
|
||||
|
||||
if( mDataBlock->getDebrisShape() == NULL)
|
||||
Resource<TSShape> debrisShape;
|
||||
if( mDataBlock->debrisShapeAssetRef.isNull() || !(debrisShape = mDataBlock->debrisShapeAssetRef.assetPtr->getShapeResource()) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
MatrixF nodeTransform(xfm);
|
||||
|
|
@ -2236,7 +2251,9 @@ void ShapeBase::getNodeTransform(const char* nodeName, const MatrixF& xfm, Matri
|
|||
if (!mShapeInstance)
|
||||
return;
|
||||
|
||||
S32 nodeIDx = mDataBlock->getShape()->findNode(nodeName);
|
||||
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
S32 nodeIDx = shape->findNode(nodeName);
|
||||
|
||||
MatrixF nodeTransform(xfm);
|
||||
const Point3F& scale = getScale();
|
||||
|
|
@ -5045,7 +5062,14 @@ void ShapeBase::_updateHiddenMeshes()
|
|||
|
||||
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 )
|
||||
|
|
@ -5114,7 +5138,8 @@ void ShapeBase::dumpMeshVisibility()
|
|||
{
|
||||
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",
|
||||
i,
|
||||
|
|
@ -5395,9 +5420,16 @@ F32 ShapeBase::getAnimationDurationByID(U32 anim_id)
|
|||
if (anim_id == BAD_ANIM_ID)
|
||||
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;
|
||||
if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size())
|
||||
return mDataBlock->getShape()->sequences[seq_id].duration;
|
||||
if (seq_id >= 0 && seq_id < shape->sequences.size())
|
||||
return shape->sequences[seq_id].duration;
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
|
@ -5408,9 +5440,16 @@ bool ShapeBase::isBlendAnimation(const char* name)
|
|||
if (anim_id == BAD_ANIM_ID)
|
||||
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;
|
||||
if (seq_id >= 0 && seq_id < mDataBlock->getShape()->sequences.size())
|
||||
return mDataBlock->getShape()->sequences[seq_id].isBlend();
|
||||
if (seq_id >= 0 && seq_id < shape->sequences.size())
|
||||
return shape->sequences[seq_id].isBlend();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -5420,13 +5459,20 @@ const char* ShapeBase::getLastClipName(U32 clip_tag)
|
|||
if (clip_tag != last_anim_tag)
|
||||
return "";
|
||||
|
||||
if (mDataBlock->shapeAssetRef.isNull())
|
||||
return "";
|
||||
|
||||
Resource<TSShape> shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||
if (!shape)
|
||||
return "";
|
||||
|
||||
S32 seq_id = (S32) last_anim_id;
|
||||
|
||||
S32 idx = mDataBlock->getShape()->sequences[seq_id].nameIndex;
|
||||
if (idx < 0 || idx >= mDataBlock->getShape()->names.size())
|
||||
S32 idx = shape->sequences[seq_id].nameIndex;
|
||||
if (idx < 0 || idx >= shape->names.size())
|
||||
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
|
||||
///< 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
|
||||
/// animation sequences played in 3rd person. [optional]
|
||||
|
|
@ -556,7 +556,7 @@ public:
|
|||
F32 shadowProjectionDistance;
|
||||
F32 shadowSphereAdjust;
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(ShapeBaseData, Shape)
|
||||
AssetRef<ShapeAsset> shapeAssetRef;
|
||||
|
||||
StringTableEntry cloakTexName;
|
||||
|
||||
|
|
@ -572,7 +572,7 @@ public:
|
|||
DebrisData * debris;
|
||||
S32 debrisID;
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(ShapeBaseData, DebrisShape)
|
||||
AssetRef<ShapeAsset> debrisShapeAssetRef;
|
||||
|
||||
ExplosionData* explosion;
|
||||
S32 explosionID;
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ ShapeBaseImageData::ShapeBaseImageData()
|
|||
isAnimated[i] = false;
|
||||
hasFlash[i] = false;
|
||||
shapeIsValid[i] = false;
|
||||
mShapeAsset[i].registerRefreshNotify(this);
|
||||
shapeAssetRef[i].assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
shakeCamera = false;
|
||||
|
|
@ -439,7 +439,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
|
||||
if (i == FirstPersonImageShape)
|
||||
{
|
||||
if ((useEyeOffset || useEyeNode) && !mShapeAsset[i].isNull())
|
||||
if ((useEyeOffset || useEyeNode) && !shapeAssetRef[i].isNull())
|
||||
{
|
||||
// Make use of the first person shape
|
||||
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))) {
|
||||
errorStr = String::ToString("Unable to load shape asset: %s", mShapeAsset[i]->getAssetId());
|
||||
Resource<TSShape> shape = shapeAssetRef[i].assetPtr->getShapeResource();
|
||||
if (!shape) {
|
||||
errorStr = String::ToString("ShapeBaseImageData(%s)::preload: Couldn't to load shape asset: %s", getName(), shapeAssetRef[i].assetId);
|
||||
return false;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -475,29 +476,29 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve nodes & build mount transform
|
||||
eyeMountNode[i] = getShape(i)->findNode("eyeMount");
|
||||
eyeNode[i] = getShape(i)->findNode("eye");
|
||||
eyeMountNode[i] = shape->findNode("eyeMount");
|
||||
eyeNode[i] = shape->findNode("eye");
|
||||
if (eyeNode[i] == -1)
|
||||
eyeNode[i] = eyeMountNode[i];
|
||||
ejectNode[i] = getShape(i)->findNode("ejectPoint");
|
||||
muzzleNode[i] = getShape(i)->findNode("muzzlePoint");
|
||||
retractNode[i] = getShape(i)->findNode("retractionPoint");
|
||||
ejectNode[i] = shape->findNode("ejectPoint");
|
||||
muzzleNode[i] = shape->findNode("muzzlePoint");
|
||||
retractNode[i] = shape->findNode("retractionPoint");
|
||||
mountTransform[i] = mountOffset;
|
||||
S32 node = getShape(i)->findNode("mountPoint");
|
||||
S32 node = shape->findNode("mountPoint");
|
||||
if (node != -1) {
|
||||
MatrixF total(1);
|
||||
do {
|
||||
MatrixF nmat;
|
||||
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);
|
||||
node = getShape(i)->nodes[node].parentIndex;
|
||||
node = shape->nodes[node].parentIndex;
|
||||
}
|
||||
while(node != -1);
|
||||
total.inverse();
|
||||
|
|
@ -510,7 +511,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
for (U32 j = 0; j < MaxStates; j++) {
|
||||
StateData& s = state[j];
|
||||
if (stateSequence[j] && stateSequence[j][0])
|
||||
s.sequence[i] = getShape(i)->findSequence(stateSequence[j]);
|
||||
s.sequence[i] = shape->findSequence(stateSequence[j]);
|
||||
if (s.sequence[i] != -1)
|
||||
{
|
||||
// This state has an animation sequence
|
||||
|
|
@ -521,7 +522,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
char bufferVis[128];
|
||||
dStrncpy(bufferVis, stateSequence[j], 100);
|
||||
dStrcat(bufferVis, "_vis", 128);
|
||||
s.sequenceVis[i] = getShape(i)->findSequence(bufferVis);
|
||||
s.sequenceVis[i] = shape->findSequence(bufferVis);
|
||||
}
|
||||
if (s.sequenceVis[i] != -1)
|
||||
{
|
||||
|
|
@ -533,13 +534,13 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
s.ignoreLoadedForReady = stateIgnoreLoadedForReady[j];
|
||||
|
||||
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)
|
||||
s.emitterNode[i] = muzzleNode[i];
|
||||
}
|
||||
|
||||
ambientSequence[i] = getShape(i)->findSequence("ambient");
|
||||
spinSequence[i] = getShape(i)->findSequence("spin");
|
||||
ambientSequence[i] = shape->findSequence("ambient");
|
||||
spinSequence[i] = shape->findSequence("spin");
|
||||
|
||||
shapeIsValid[i] = true;
|
||||
}
|
||||
|
|
@ -564,7 +565,9 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -625,7 +628,9 @@ void ShapeBaseImageData::initPersistFields()
|
|||
{
|
||||
docsURL;
|
||||
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),
|
||||
"@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(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();
|
||||
imageAnimPrefixFP = stream->readSTString();
|
||||
|
|
@ -2139,9 +2150,17 @@ S32 ShapeBase::getNodeIndex(U32 imageSlot,StringTableEntry nodeName)
|
|||
{
|
||||
MountedImage& image = mMountedImageList[imageSlot];
|
||||
if (image.dataBlock)
|
||||
return image.dataBlock->getShape(getImageShapeIndex(image))->findNode(nodeName);
|
||||
else
|
||||
return -1;
|
||||
{
|
||||
U32 imageShapeidx = getImageShapeIndex(image);
|
||||
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
|
||||
|
|
@ -2329,7 +2348,10 @@ void ShapeBase::setImage( U32 imageSlot,
|
|||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++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())
|
||||
|
|
|
|||
|
|
@ -152,14 +152,14 @@ TSStatic::TSStatic()
|
|||
mAnimOffset = 0.0f;
|
||||
mAnimSpeed = 1.0f;
|
||||
|
||||
mShapeAsset.registerRefreshNotify(this);
|
||||
mShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
TSStatic::~TSStatic()
|
||||
{
|
||||
delete mConvexList;
|
||||
mConvexList = NULL;
|
||||
mShapeAsset.unregisterRefreshNotify();
|
||||
|
||||
if (mCubeReflector)
|
||||
{
|
||||
mCubeReflector->unregisterReflector();
|
||||
|
|
@ -187,7 +187,9 @@ void TSStatic::initPersistFields()
|
|||
docsURL;
|
||||
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");
|
||||
|
||||
|
|
@ -403,17 +405,26 @@ bool TSStatic::_createShape()
|
|||
mAmbientThread = 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() &&
|
||||
!getShape()->preloadMaterialList(getShapeFile()) &&
|
||||
!mShapeAssetRef.assetPtr->preloadMaterialList() &&
|
||||
NetConnection::filesWereDownloaded())
|
||||
return false;
|
||||
|
||||
mObjBox = getShape()->mBounds;
|
||||
mObjBox = shape->mBounds;
|
||||
resetWorldBox();
|
||||
|
||||
mShapeInstance = new TSShapeInstance(getShape(), true);
|
||||
mShapeInstance = new TSShapeInstance(shape, true);
|
||||
mShapeInstance->resetMaterialList();
|
||||
mShapeInstance->cloneMaterialList();
|
||||
|
||||
|
|
@ -429,7 +440,7 @@ bool TSStatic::_createShape()
|
|||
prepCollision();
|
||||
|
||||
// Find the "ambient" animation if it exists
|
||||
S32 ambientSeq = getShape()->findSequence("ambient");
|
||||
S32 ambientSeq = shape->findSequence("ambient");
|
||||
|
||||
if (ambientSeq > -1 && !mAmbientThread)
|
||||
mAmbientThread = mShapeInstance->addThread();
|
||||
|
|
@ -449,77 +460,13 @@ bool TSStatic::_createShape()
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
// Let the client know that the collision was updated
|
||||
|
|
@ -536,22 +483,24 @@ void TSStatic::prepCollision()
|
|||
mLOSDetails.clear();
|
||||
mConvexList->nukeList();
|
||||
|
||||
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
if (mCollisionType == CollisionMesh || mCollisionType == VisibleMesh)
|
||||
{
|
||||
getShape()->findColDetails(mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails, mCollisionLOD);
|
||||
shape->findColDetails(mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails, mCollisionLOD);
|
||||
if (mDecalType == mCollisionType)
|
||||
{
|
||||
mDecalDetailsPtr = &mCollisionDetails;
|
||||
}
|
||||
else if (mDecalType == CollisionMesh || mDecalType == VisibleMesh)
|
||||
{
|
||||
getShape()->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD);
|
||||
shape->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD);
|
||||
mDecalDetailsPtr = &mDecalDetails;
|
||||
}
|
||||
}
|
||||
else if (mDecalType == CollisionMesh || mDecalType == VisibleMesh)
|
||||
{
|
||||
getShape()->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD);
|
||||
shape->findColDetails(mDecalType == VisibleMesh, &mDecalDetails, 0, mCollisionLOD);
|
||||
mDecalDetailsPtr = &mDecalDetails;
|
||||
}
|
||||
|
||||
|
|
@ -565,16 +514,18 @@ void TSStatic::_updatePhysics()
|
|||
if (!PHYSICSMGR || mCollisionType == None)
|
||||
return;
|
||||
|
||||
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
PhysicsCollision* colShape = NULL;
|
||||
if (mCollisionType == Bounds)
|
||||
{
|
||||
MatrixF offset(true);
|
||||
offset.setPosition(getShape()->center);
|
||||
offset.setPosition(shape->center);
|
||||
colShape = PHYSICSMGR->createCollision();
|
||||
colShape->addBox(getObjBox().getExtents() * 0.5f * mObjScale, offset);
|
||||
}
|
||||
else
|
||||
colShape = getShape()->buildColShape(mCollisionType == VisibleMesh, getScale());
|
||||
colShape = shape->buildColShape(mCollisionType == VisibleMesh, getScale());
|
||||
|
||||
if (colShape)
|
||||
{
|
||||
|
|
@ -727,7 +678,7 @@ void TSStatic::_updateShouldTick()
|
|||
|
||||
void TSStatic::prepRenderImage(SceneRenderState* state)
|
||||
{
|
||||
if (!mShapeAsset.isValid() || !mShapeInstance)
|
||||
if (!mShapeAssetRef.isValid() || !mShapeInstance)
|
||||
return;
|
||||
|
||||
Point3F cameraOffset;
|
||||
|
|
@ -967,7 +918,7 @@ U32 TSStatic::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
|||
|
||||
if (stream->writeFlag(mask & AdvancedStaticOptionsMask))
|
||||
{
|
||||
PACK_ASSET_REFACTOR(con, Shape);
|
||||
AssetDatabase.packUpdateAsset(con, mask, stream, mShapeAssetRef.assetId);
|
||||
|
||||
stream->writeInt(mDecalType,4);
|
||||
|
||||
|
|
@ -1086,7 +1037,7 @@ void TSStatic::unpackUpdate(NetConnection* con, BitStream* stream)
|
|||
|
||||
if (stream->readFlag()) // AdvancedStaticOptionsMask
|
||||
{
|
||||
UNPACK_ASSET_REFACTOR(con, Shape);
|
||||
mShapeAssetRef = AssetDatabase.unpackUpdateAsset(con, stream);
|
||||
|
||||
mDecalType = (MeshType)stream->readInt(4);
|
||||
|
||||
|
|
@ -1611,10 +1562,10 @@ void TSStatic::updateMaterials()
|
|||
TSMaterialList* pMatList = mShapeInstance->getMaterialList();
|
||||
|
||||
String path;
|
||||
if (mShapeAsset->isAssetValid())
|
||||
path = mShapeAsset->getShapeFile();
|
||||
if (mShapeAssetRef.assetPtr->isAssetValid())
|
||||
path = mShapeAssetRef.assetPtr->getShapeFile();
|
||||
else
|
||||
path = mShapeFile;
|
||||
return;
|
||||
|
||||
pMatList->setTextureLookupPath(path);
|
||||
|
||||
|
|
@ -1643,10 +1594,10 @@ void TSStatic::updateMaterials()
|
|||
|
||||
void TSStatic::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
|
||||
{
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAssetRef.assetPtr);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
S32 matIndex = shapeMaterialList->getMaterialNameList().find_next(String(mapTo));
|
||||
|
|
@ -1836,7 +1796,11 @@ DefineEngineMethod(TSStatic, getModelFile, const char*, (), ,
|
|||
"@endtsexample\n"
|
||||
)
|
||||
{
|
||||
return object->getShapeFile();
|
||||
const AssetPtr<ShapeAsset> shapeAsset = object->getShapeAsset();
|
||||
if (shapeAsset.isNull())
|
||||
return "";
|
||||
|
||||
return shapeAsset->getShapeFile();
|
||||
}
|
||||
|
||||
void TSStatic::set_special_typing()
|
||||
|
|
@ -1880,15 +1844,27 @@ void TSStatic::setSelectionFlags(U8 flags)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
const Point3F& scale = getScale();
|
||||
|
|
|
|||
|
|
@ -176,8 +176,6 @@ protected:
|
|||
void interpolateTick(F32 delta) override;
|
||||
void advanceTime(F32 dt) override;
|
||||
|
||||
void onDynamicModified(const char* slotName, const char* newValue) override;
|
||||
|
||||
/// Start or stop processing ticks depending on our state.
|
||||
void _updateShouldTick();
|
||||
|
||||
|
|
@ -196,7 +194,7 @@ protected:
|
|||
|
||||
Convex* mConvexList;
|
||||
|
||||
DECLARE_SHAPEASSET_NET_REFACTOR(TSStatic, Shape, AdvancedStaticOptionsMask)
|
||||
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||
|
||||
U32 mShapeHash;
|
||||
Vector<S32> mCollisionDetails;
|
||||
|
|
@ -244,7 +242,7 @@ public:
|
|||
DECLARE_CATEGORY("Object \t Simple");
|
||||
static void initPersistFields();
|
||||
/// 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 bool _setFieldSkin(void* object, const char* index, const char* data);
|
||||
static const char* _getFieldSkin(void* object, const char* data);
|
||||
|
|
@ -289,6 +287,8 @@ public:
|
|||
|
||||
void getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList) override;
|
||||
|
||||
const AssetPtr<ShapeAsset>& getShapeAsset() const { return mShapeAssetRef.assetPtr; }
|
||||
|
||||
private:
|
||||
void onStaticModified(const char* slotName, const char* newValue = NULL) override;
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -245,9 +245,11 @@ bool AITurretShapeData::preload(bool server, String &errorStr)
|
|||
if (!Parent::preload(server, errorStr))
|
||||
return false;
|
||||
|
||||
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
// We have mShape at this point. Resolve nodes.
|
||||
scanNode = getShape()->findNode("scanPoint");
|
||||
aimNode = getShape()->findNode("aimPoint");
|
||||
scanNode = shape->findNode("scanPoint");
|
||||
aimNode = shape->findNode("aimPoint");
|
||||
|
||||
if (scanNode == -1) scanNode = pitchNode;
|
||||
if (scanNode == -1) scanNode = headingNode;
|
||||
|
|
@ -259,7 +261,7 @@ bool AITurretShapeData::preload(bool server, String &errorStr)
|
|||
for (U32 j = 0; j < MaxStates; j++) {
|
||||
StateData& s = state[j];
|
||||
if (stateSequence[j] && stateSequence[j][0])
|
||||
s.sequence = getShape()->findSequence(stateSequence[j]);
|
||||
s.sequence = shape->findSequence(stateSequence[j]);
|
||||
if (s.sequence != -1)
|
||||
{
|
||||
// This state has an animation sequence
|
||||
|
|
|
|||
|
|
@ -216,36 +216,43 @@ bool TurretShapeData::preload(bool server, String &errorStr)
|
|||
if (!Parent::preload(server, errorStr))
|
||||
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.
|
||||
headingNode = getShape()->findNode("heading");
|
||||
pitchNode = getShape()->findNode("pitch");
|
||||
headingNode = shape->findNode("heading");
|
||||
pitchNode = shape->findNode("pitch");
|
||||
|
||||
// Find any mirror pitch nodes
|
||||
for (U32 i = 0; i < NumMirrorDirectionNodes; ++i)
|
||||
{
|
||||
char name[32];
|
||||
dSprintf(name, 31, "pitch%d", i+1);
|
||||
pitchNodes[i] = getShape()->findNode(name);
|
||||
pitchNodes[i] = shape->findNode(name);
|
||||
|
||||
dSprintf(name, 31, "heading%d", i+1);
|
||||
headingNodes[i] = getShape()->findNode(name);
|
||||
headingNodes[i] = shape->findNode(name);
|
||||
}
|
||||
|
||||
// Resolve weapon mount point node indexes
|
||||
for (U32 i = 0; i < ShapeBase::MaxMountedImages; i++) {
|
||||
char fullName[256];
|
||||
dSprintf(fullName,sizeof(fullName),"weaponMount%d",i);
|
||||
weaponMountNode[i] = getShape()->findNode(fullName);
|
||||
weaponMountNode[i] = shape->findNode(fullName);
|
||||
}
|
||||
|
||||
// Recoil animations
|
||||
recoilSequence[0] = getShape()->findSequence("light_recoil");
|
||||
recoilSequence[1] = getShape()->findSequence("medium_recoil");
|
||||
recoilSequence[2] = getShape()->findSequence("heavy_recoil");
|
||||
recoilSequence[0] = shape->findSequence("light_recoil");
|
||||
recoilSequence[1] = shape->findSequence("medium_recoil");
|
||||
recoilSequence[2] = shape->findSequence("heavy_recoil");
|
||||
|
||||
// Optional sequences used when the turret rotates
|
||||
pitchSequence = getShape()->findSequence("pitch");
|
||||
headingSequence = getShape()->findSequence("heading");
|
||||
pitchSequence = shape->findSequence("pitch");
|
||||
headingSequence = shape->findSequence("heading");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,7 +135,9 @@ bool FlyingVehicleData::preload(bool server, String &errorStr)
|
|||
if (!Parent::preload(server, errorStr))
|
||||
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
|
||||
if (!server) {
|
||||
|
|
@ -165,7 +167,7 @@ bool FlyingVehicleData::preload(bool server, String &errorStr)
|
|||
|
||||
// Resolve jet nodes
|
||||
for (S32 j = 0; j < MaxJetNodes; j++)
|
||||
jetNode[j] = getShape()->findNode(sJetNode[j]);
|
||||
jetNode[j] = shape->findNode(sJetNode[j]);
|
||||
|
||||
//
|
||||
maxSpeed = maneuveringForce / minDrag;
|
||||
|
|
|
|||
|
|
@ -332,9 +332,12 @@ bool HoverVehicleData::preload(bool server, String &errorStr)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
// Resolve jet nodes
|
||||
for (S32 j = 0; j < MaxJetNodes; j++)
|
||||
jetNode[j] = getShape()->findNode(sJetNode[j]);
|
||||
jetNode[j] = shape->findNode(sJetNode[j]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ bool VehicleData::preload(bool server, String &errorStr)
|
|||
if (!collisionDetails.size() || collisionDetails[0] == -1)
|
||||
{
|
||||
Con::errorf("VehicleData::preload failed: Vehicle models must define a collision-1 detail");
|
||||
errorStr = String::ToString("VehicleData: Couldn't load shape asset \"%s\"", getShapeAsset().getAssetId());
|
||||
errorStr = String::ToString("VehicleData: Couldn't load shape asset \"%s\"", shapeAssetRef.assetId);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,24 +86,28 @@ WheeledVehicleTire::WheeledVehicleTire()
|
|||
longitudinalDamping = 1;
|
||||
longitudinalRelaxation = 1;
|
||||
mass = 1.f;
|
||||
mShapeAsset.registerRefreshNotify(this);
|
||||
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
bool WheeledVehicleTire::preload(bool server, String &errorStr)
|
||||
{
|
||||
// Load up the tire shape. ShapeBase has an option to force a
|
||||
// CRC check, this is left out here, but could be easily added.
|
||||
if (!getShape())
|
||||
if (!shapeAssetRef.isNull())
|
||||
{
|
||||
errorStr = String::ToString("WheeledVehicleTire: Couldn't load shape \"%s\"", _getShapeAssetId());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determinw wheel radius from the shape's bounding box.
|
||||
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
{
|
||||
// Determinw wheel radius from the shape's bounding box.
|
||||
// The tire should be built with it's hub axis along the
|
||||
// object's Y axis.
|
||||
radius = 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;
|
||||
|
|
@ -112,7 +116,8 @@ bool WheeledVehicleTire::preload(bool server, String &errorStr)
|
|||
void WheeledVehicleTire::initPersistFields()
|
||||
{
|
||||
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,
|
||||
"The mass of the wheel.\nCurrently unused." );
|
||||
|
|
@ -177,7 +182,7 @@ void WheeledVehicleTire::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(Shape);
|
||||
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||
|
||||
stream->write(mass);
|
||||
stream->write(staticFriction);
|
||||
|
|
@ -196,7 +201,7 @@ void WheeledVehicleTire::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
||||
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
|
||||
stream->read(&mass);
|
||||
stream->read(&staticFriction);
|
||||
|
|
@ -340,9 +345,11 @@ bool WheeledVehicleData::preload(bool server, String &errorStr)
|
|||
if (!Parent::preload(server, errorStr))
|
||||
return false;
|
||||
|
||||
Resource<TSShape> shape = shapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
// A temporary shape instance is created so that we can
|
||||
// animate the shape and extract wheel information.
|
||||
TSShapeInstance* si = new TSShapeInstance(getShape(), false);
|
||||
TSShapeInstance* si = new TSShapeInstance(shape, false);
|
||||
|
||||
// Resolve objects transmitted from 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.
|
||||
dSprintf(buff,sizeof(buff),"hub%d",i);
|
||||
wp->springNode = getShape()->findNode(buff);
|
||||
wp->springNode = shape->findNode(buff);
|
||||
if (wp->springNode != -1) {
|
||||
|
||||
// Check for spring animation.. If there is none we just grab
|
||||
// the current position of the hub. Otherwise we'll animate
|
||||
// and get the position at time 0.
|
||||
dSprintf(buff,sizeof(buff),"spring%d",i);
|
||||
wp->springSequence = getShape()->findSequence(buff);
|
||||
wp->springSequence = shape->findSequence(buff);
|
||||
if (wp->springSequence == -1)
|
||||
si->mNodeTransforms[wp->springNode].getColumn(3, &wp->pos);
|
||||
else {
|
||||
|
|
@ -403,17 +410,17 @@ bool WheeledVehicleData::preload(bool server, String &errorStr)
|
|||
// Check for steering. Should think about normalizing the
|
||||
// steering animation the way the suspension is, but I don't
|
||||
// think it's as critical.
|
||||
steeringSequence = getShape()->findSequence("steering");
|
||||
steeringSequence = shape->findSequence("steering");
|
||||
|
||||
// Brakes
|
||||
brakeLightSequence = getShape()->findSequence("brakelight");
|
||||
brakeLightSequence = shape->findSequence("brakelight");
|
||||
|
||||
// Extract collision planes from shape collision detail level
|
||||
if (collisionDetails[0] != -1) {
|
||||
MatrixF imat(1);
|
||||
SphereF sphere;
|
||||
sphere.center = getShape()->center;
|
||||
sphere.radius = getShape()->mRadius;
|
||||
sphere.center = shape->center;
|
||||
sphere.radius = shape->mRadius;
|
||||
PlaneExtractorPolyList polyList;
|
||||
polyList.mPlaneList = &rigidBody.mPlaneList;
|
||||
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
|
||||
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;
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(WheeledVehicleTire, Shape)
|
||||
AssetRef<ShapeAsset> shapeAssetRef;
|
||||
|
||||
// Physical properties
|
||||
F32 mass; // Mass of the whole wheel
|
||||
|
|
|
|||
|
|
@ -241,13 +241,13 @@ afxMagicMissileData::afxMagicMissileData()
|
|||
|
||||
caster_safety_time = U32_MAX;
|
||||
|
||||
mProjectileShapeAsset.registerRefreshNotify(this);
|
||||
projectileShapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
projectileShape = NULL;
|
||||
}
|
||||
|
||||
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
|
||||
CLONE_ASSET(ProjectileSound);
|
||||
splash = other.splash;
|
||||
|
|
@ -307,8 +307,6 @@ afxMagicMissileData::~afxMagicMissileData()
|
|||
{
|
||||
if (wiggle_axis)
|
||||
delete [] wiggle_axis;
|
||||
|
||||
mProjectileShapeAsset.unregisterRefreshNotify();
|
||||
}
|
||||
|
||||
afxMagicMissileData* afxMagicMissileData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
|
||||
|
|
@ -338,7 +336,8 @@ void afxMagicMissileData::initPersistFields()
|
|||
static IRangeValidatorScaled ticksFromMS(TickMs, 0, MaxLifetimeTicks);
|
||||
|
||||
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("missileShapeScale", TypePoint3F, myOffset(scale));
|
||||
endGroup("Shapes");
|
||||
|
|
@ -531,16 +530,20 @@ bool afxMagicMissileData::preload(bool server, String &errorStr)
|
|||
if (Sim::findObject(lightDescId, lightDesc) == false)
|
||||
Con::errorf(ConsoleLogEntry::General, "afxMagicMissileData::preload: Invalid packet, bad datablockid(lightDesc): %d", lightDescId);
|
||||
}
|
||||
|
||||
if (getProjectileShape())
|
||||
|
||||
if (projectileShapeAssetRef.notNull())
|
||||
{
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(getProjectileShape(), !server);
|
||||
delete pDummy;
|
||||
}
|
||||
else if (mProjectileShapeAsset.notNull())
|
||||
{
|
||||
errorStr = String::ToString("afxMagicMissileData::preload: Couldn't load shape \"%s\"", _getProjectileShapeAssetId());
|
||||
return false;
|
||||
Resource<TSShape> shape = projectileShapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
{
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
|
||||
delete pDummy;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorStr = String::ToString("afxMagicMissileData(%s)::preload: Couldn't load shape \"%s\"", getName(), projectileShapeAssetRef.assetId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -580,7 +583,7 @@ void afxMagicMissileData::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(ProjectileShape);
|
||||
AssetDatabase.packDataAsset(stream, projectileShapeAssetRef.assetId);
|
||||
|
||||
/* From stock Projectile code...
|
||||
stream->writeFlag(faceViewer);
|
||||
|
|
@ -691,7 +694,7 @@ void afxMagicMissileData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(ProjectileShape);
|
||||
projectileShapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
/* From stock Projectile code...
|
||||
faceViewer = stream->readFlag();
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ public:
|
|||
public:
|
||||
// variables set in datablock definition:
|
||||
// Shape related
|
||||
DECLARE_SHAPEASSET_REFACTOR(afxMagicMissileData, ProjectileShape)
|
||||
AssetRef<ShapeAsset> projectileShapeAssetRef;
|
||||
//StringTableEntry projectileShapeName;
|
||||
|
||||
//bool hasLight;
|
||||
|
|
|
|||
|
|
@ -79,12 +79,12 @@ afxModelData::afxModelData()
|
|||
shadowProjectionDistance = 10.0f;
|
||||
shadowSphereAdjust = 1.0;
|
||||
|
||||
mShapeAsset.registerRefreshNotify(this);
|
||||
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
afxModelData::afxModelData(const afxModelData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||
{
|
||||
mShapeAsset = other.mShapeAsset;
|
||||
shapeAssetRef = other.shapeAssetRef;
|
||||
sequence = other.sequence;
|
||||
seq_rate = other.seq_rate;
|
||||
seq_offset = other.seq_offset;
|
||||
|
|
@ -114,8 +114,6 @@ afxModelData::~afxModelData()
|
|||
{
|
||||
if (remap_buffer)
|
||||
dFree(remap_buffer);
|
||||
|
||||
mShapeAsset.unregisterRefreshNotify();
|
||||
}
|
||||
|
||||
bool afxModelData::preload(bool server, String &errorStr)
|
||||
|
|
@ -126,8 +124,12 @@ bool afxModelData::preload(bool server, String &errorStr)
|
|||
// don't need to do this stuff on the server
|
||||
if (server)
|
||||
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.
|
||||
if (remap_txr_tags != ST_NULLSTRING)
|
||||
|
|
@ -157,13 +159,13 @@ bool afxModelData::preload(bool server, String &errorStr)
|
|||
if (txr_tag_remappings.size() == 0)
|
||||
{
|
||||
// this little hack forces the textures to preload
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(getShape());
|
||||
TSShapeInstance* pDummy = new TSShapeInstance(shape);
|
||||
delete pDummy;
|
||||
}
|
||||
}
|
||||
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 true;
|
||||
|
|
@ -175,7 +177,8 @@ void afxModelData::initPersistFields()
|
|||
{
|
||||
docsURL;
|
||||
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");
|
||||
|
||||
addGroup("Animation");
|
||||
|
|
@ -259,7 +262,8 @@ void afxModelData::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(Shape);
|
||||
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||
|
||||
stream->writeString(sequence);
|
||||
stream->write(seq_rate);
|
||||
stream->write(seq_offset);
|
||||
|
|
@ -290,7 +294,8 @@ void afxModelData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
||||
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
|
||||
sequence = stream->readSTString();
|
||||
stream->read(&seq_rate);
|
||||
stream->read(&seq_offset);
|
||||
|
|
@ -319,9 +324,15 @@ void afxModelData::unpackData(BitStream* stream)
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -395,19 +406,22 @@ bool afxModel::onAdd()
|
|||
if (!conn || !Parent::onAdd())
|
||||
return false;
|
||||
|
||||
// setup our bounding box
|
||||
if (mDataBlock->getShape())
|
||||
mObjBox = mDataBlock->getShape()->mBounds;
|
||||
else
|
||||
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
|
||||
Resource<TSShape> shape;
|
||||
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
|
||||
if (!mDataBlock->shapeAssetRef.isNull())
|
||||
{
|
||||
shape = mDataBlock->shapeAssetRef.assetPtr->getShapeResource();
|
||||
if (shape)
|
||||
mObjBox = shape->mBounds;
|
||||
}
|
||||
|
||||
// setup the shape instance and sequence
|
||||
if (mDataBlock->getShape())
|
||||
if (shape)
|
||||
{
|
||||
if (/*isClientObject() && */mDataBlock->txr_tag_remappings.size() > 0)
|
||||
{
|
||||
// temporarily substitute material tags with alternates
|
||||
TSMaterialList* mat_list = mDataBlock->getShape()->materialList;
|
||||
TSMaterialList* mat_list = shape->materialList;
|
||||
if (mat_list)
|
||||
{
|
||||
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())
|
||||
{
|
||||
|
|
@ -437,7 +451,7 @@ bool afxModel::onAdd()
|
|||
// restore the material tags to original form
|
||||
if (mDataBlock->txr_tag_remappings.size() > 0)
|
||||
{
|
||||
TSMaterialList* mat_list = mDataBlock->getShape()->materialList;
|
||||
TSMaterialList* mat_list = shape->materialList;
|
||||
if (mat_list)
|
||||
{
|
||||
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
|
||||
|
|
@ -466,7 +480,6 @@ bool afxModel::onAdd()
|
|||
else
|
||||
{
|
||||
// here we start the default animation sequence
|
||||
TSShape* shape = shape_inst->getShape();
|
||||
main_seq_id = shape->findSequence(mDataBlock->sequence);
|
||||
if (main_seq_id != -1)
|
||||
{
|
||||
|
|
@ -503,14 +516,14 @@ bool afxModel::onAdd()
|
|||
|
||||
resetWorldBox();
|
||||
|
||||
if (mDataBlock->getShape())
|
||||
if (shape)
|
||||
{
|
||||
// Scan out the collision hulls...
|
||||
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)
|
||||
{
|
||||
|
|
@ -524,7 +537,7 @@ bool afxModel::onAdd()
|
|||
|
||||
char buff[128];
|
||||
dSprintf(buff, sizeof(buff), "LOS-%d", i + 1 + 8/*MaxCollisionShapes*/);
|
||||
U32 los = mDataBlock->getShape()->findDetail(buff);
|
||||
U32 los = shape->findDetail(buff);
|
||||
if (los == -1)
|
||||
mLOSDetails.last() = i;
|
||||
else
|
||||
|
|
@ -535,9 +548,9 @@ bool afxModel::onAdd()
|
|||
// Snag any "unmatched" LOS details
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ struct afxModelData : public GameBaseData, protected AssetPtrCallback
|
|||
{
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(afxModelData, Shape)
|
||||
AssetRef<ShapeAsset> shapeAssetRef;
|
||||
|
||||
StringTableEntry sequence;
|
||||
|
||||
|
|
@ -155,9 +155,21 @@ public:
|
|||
void setSequenceRateFactor(F32 factor);
|
||||
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; }
|
||||
TSShape* getTSShape() { return mDataBlock->getShape(); }
|
||||
TSShape* getTSShape()
|
||||
{
|
||||
if (mDataBlock->shapeAssetRef.isNull())
|
||||
return nullptr;
|
||||
|
||||
return mDataBlock->shapeAssetRef.assetPtr->getShape();
|
||||
}
|
||||
TSShapeInstance* getTSShapeInstance() { return shape_inst; }
|
||||
|
||||
U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans);
|
||||
|
|
|
|||
|
|
@ -85,7 +85,13 @@ public:
|
|||
U32 packUpdate(NetConnection*, U32, 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; }
|
||||
|
||||
DECLARE_CONOBJECT(afxStaticShape);
|
||||
|
|
|
|||
|
|
@ -182,4 +182,54 @@ public:
|
|||
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_
|
||||
|
|
|
|||
|
|
@ -162,7 +162,9 @@ void VolumetricFog::initPersistFields()
|
|||
docsURL;
|
||||
Parent::initPersistFields();
|
||||
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");
|
||||
|
||||
addGroup("VolumetricFogData");
|
||||
|
|
@ -340,7 +342,7 @@ void VolumetricFog::handleResize(VolumetricFogRTManager *RTM, bool resize)
|
|||
|
||||
bool VolumetricFog::setShapeAsset(const StringTableEntry shapeAssetId)
|
||||
{
|
||||
_setShape(shapeAssetId);
|
||||
mShapeAssetRef = shapeAssetId;
|
||||
|
||||
LoadShape();
|
||||
return true;
|
||||
|
|
@ -349,27 +351,28 @@ bool VolumetricFog::setShapeAsset(const StringTableEntry shapeAssetId)
|
|||
bool VolumetricFog::LoadShape()
|
||||
{
|
||||
GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip };
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset);
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAssetRef.assetPtr);
|
||||
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
||||
{
|
||||
Con::errorf("[VolumetricFog] Failed to load shape asset.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!getShape())
|
||||
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||
if (!shape)
|
||||
{
|
||||
Con::errorf("VolumetricFog::_createShape() - Shape Asset had no valid shape!");
|
||||
return false;
|
||||
}
|
||||
|
||||
mObjBox = getShape()->mBounds;
|
||||
mRadius = getShape()->mRadius;
|
||||
mObjBox = shape->mBounds;
|
||||
mRadius = shape->mRadius;
|
||||
resetWorldBox();
|
||||
|
||||
if (!isClientObject())
|
||||
return false;
|
||||
|
||||
TSShapeInstance *mShapeInstance = new TSShapeInstance(getShape(), false);
|
||||
TSShapeInstance *mShapeInstance = new TSShapeInstance(shape, false);
|
||||
meshes mesh_detail;
|
||||
|
||||
for (S32 i = 0; i < det_size.size(); i++)
|
||||
|
|
@ -385,9 +388,9 @@ bool VolumetricFog::LoadShape()
|
|||
|
||||
// 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.sub_shape = detail->subShapeNum;
|
||||
mesh_detail.obj_det = detail->objectDetailNum;
|
||||
|
|
@ -403,8 +406,8 @@ bool VolumetricFog::LoadShape()
|
|||
const S32 ss = det_size[i].sub_shape;
|
||||
if (ss >= 0)
|
||||
{
|
||||
const S32 start = getShape()->subShapeFirstObject[ss];
|
||||
const S32 end = start + getShape()->subShapeNumObjects[ss];
|
||||
const S32 start = shape->subShapeFirstObject[ss];
|
||||
const S32 end = start + shape->subShapeNumObjects[ss];
|
||||
for (S32 j = start; j < end; j++)
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
PACK_ASSET_REFACTOR(con, Shape);
|
||||
AssetDatabase.packUpdateAsset(conn, mask, stream, mShapeAssetRef.assetId);
|
||||
|
||||
mathWrite(*stream, getTransform());
|
||||
mathWrite(*stream, getScale());
|
||||
|
||||
if (mShapeAsset.notNull())
|
||||
if (mShapeAssetRef.isValid())
|
||||
{
|
||||
mObjBox = mShapeAsset->getShapeResource()->mBounds;
|
||||
mRadius = mShapeAsset->getShapeResource()->mRadius;
|
||||
Resource<TSShape> shape = mShapeAssetRef.assetPtr->getShapeResource();
|
||||
|
||||
mObjBox = shape->mBounds;
|
||||
mRadius = shape->mRadius;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -595,8 +601,8 @@ void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
VectorF scale;
|
||||
VectorF mOldScale = getScale();
|
||||
StringTableEntry oldTextureName = mTextureAsset.getAssetId();
|
||||
StringTableEntry oldShapeAsset = _getShapeAssetId();
|
||||
StringTableEntry oldShape = getShapeFile();
|
||||
StringTableEntry oldShapeAsset = mShapeAssetRef.assetId;
|
||||
StringTableEntry oldShape = mShapeAssetRef.assetPtr->getShapeFile();
|
||||
|
||||
if (stream->readFlag())// Fog color
|
||||
stream->read(&mFogColor);
|
||||
|
|
@ -665,11 +671,11 @@ void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
}
|
||||
if (stream->readFlag())//Fog shape
|
||||
{
|
||||
UNPACK_ASSET_REFACTOR(con, Shape);
|
||||
mShapeAssetRef = AssetDatabase.unpackUpdateAsset(conn, stream);
|
||||
|
||||
mathRead(*stream, &mat);
|
||||
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;
|
||||
mShapeLoaded = LoadShape();
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class VolumetricFog : public SceneObject
|
|||
Vector <U32> *indices;
|
||||
};
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(VolumetricFog, Shape)
|
||||
AssetRef<ShapeAsset> mShapeAssetRef;
|
||||
|
||||
protected:
|
||||
// Rendertargets;
|
||||
|
|
|
|||
|
|
@ -54,15 +54,15 @@ ForestItemData::ForestItemData()
|
|||
mDampingCoefficient( 0.7f )
|
||||
{
|
||||
mShape = NULL;
|
||||
mShapeAsset.registerRefreshNotify(this);
|
||||
shapeAssetRef.assetPtr.registerRefreshNotify(this);
|
||||
}
|
||||
|
||||
void ForestItemData::initPersistFields()
|
||||
{
|
||||
docsURL;
|
||||
addGroup( "Shapes" );
|
||||
|
||||
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, ForestItemData, "Shape asset for this item type");
|
||||
ADD_FIELD("shapeAsset", TypeShapeAssetRef, Offset(shapeAssetRef, ForestItemData))
|
||||
.doc("Shape asset for this item type");
|
||||
|
||||
endGroup( "Shapes" );
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ void ForestItemData::packData(BitStream* stream)
|
|||
|
||||
stream->write( localName );
|
||||
|
||||
PACKDATA_ASSET_REFACTOR(Shape);
|
||||
AssetDatabase.packDataAsset(stream, shapeAssetRef.assetId);
|
||||
|
||||
stream->writeFlag( mCollidable );
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ void ForestItemData::unpackData(BitStream* stream)
|
|||
stream->read( &localName );
|
||||
setInternalName( localName );
|
||||
|
||||
UNPACKDATA_ASSET_REFACTOR(Shape);
|
||||
shapeAssetRef = AssetDatabase.unpackDataAsset(stream);
|
||||
|
||||
mCollidable = stream->readFlag();
|
||||
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ protected:
|
|||
virtual void _preload() {}
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_SHAPEASSET_REFACTOR(ForestItemData, Shape)
|
||||
|
||||
AssetRef<ShapeAsset> shapeAssetRef;
|
||||
|
||||
/// This is the radius used during placement to ensure
|
||||
/// the element isn't crowded up against other trees.
|
||||
|
|
|
|||
|
|
@ -99,13 +99,13 @@ void TSForestItemData::inspectPostApply()
|
|||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( path != Path(getShapeFile()) )
|
||||
if ( path != Path(shapeAssetRef.assetPtr->getShapeFile()) )
|
||||
return;
|
||||
|
||||
SAFE_DELETE( mShapeInstance );
|
||||
|
|
@ -116,8 +116,11 @@ void TSForestItemData::_onResourceChanged( const Torque::Path &path )
|
|||
|
||||
void TSForestItemData::_loadShape()
|
||||
{
|
||||
mShape = getShape();
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(_getShapeAssetId());
|
||||
if (shapeAssetRef.assetPtr.isNull())
|
||||
return;
|
||||
|
||||
mShape = shapeAssetRef.assetPtr->getShape();
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(shapeAssetRef.assetPtr);
|
||||
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
||||
{
|
||||
return;
|
||||
|
|
@ -127,7 +130,7 @@ void TSForestItemData::_loadShape()
|
|||
return;
|
||||
|
||||
if ( mIsClientObject &&
|
||||
!mShape->preloadMaterialList(getShapeFile()) )
|
||||
!mShape->preloadMaterialList(shapeAssetRef.assetPtr->getShapeFile()) )
|
||||
return;
|
||||
|
||||
// Lets add an autobillboard detail if don't have one.
|
||||
|
|
@ -165,7 +168,7 @@ TSShapeInstance* TSForestItemData::_getShapeInstance() const
|
|||
|
||||
void TSForestItemData::_checkLastDetail()
|
||||
{
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(_getShapeAssetId());
|
||||
U32 assetStatus = ShapeAsset::getAssetErrCode(shapeAssetRef.assetPtr);
|
||||
if (assetStatus != AssetBase::Ok && assetStatus != AssetBase::UsingFallback)
|
||||
{
|
||||
return;
|
||||
|
|
@ -177,7 +180,7 @@ void TSForestItemData::_checkLastDetail()
|
|||
// TODO: Expose some real parameters to the datablock maybe?
|
||||
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!
|
||||
while ( mShape->detailCollisionAccelerators.size() < mShape->details.size() )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue