mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-10 22:24:33 +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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue