mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-06 05:50:31 +00:00
Merge branch 'Preview4_0' into str_cpp_memory_experiment
This commit is contained in:
commit
1e9aa8b86f
4161 changed files with 514029 additions and 215418 deletions
|
|
@ -85,7 +85,7 @@ AccumulationVolume::AccumulationVolume()
|
|||
mWorldToObj.identity();
|
||||
|
||||
// Accumulation Texture.
|
||||
INIT_IMAGEASSET(Texture);
|
||||
INIT_ASSET(Texture);
|
||||
|
||||
resetWorldBox();
|
||||
}
|
||||
|
|
@ -236,7 +236,7 @@ U32 AccumulationVolume::packUpdate( NetConnection *connection, U32 mask, BitStre
|
|||
|
||||
if (stream->writeFlag(mask & InitialUpdateMask))
|
||||
{
|
||||
PACK_IMAGEASSET(connection, Texture);
|
||||
PACK_ASSET(connection, Texture);
|
||||
}
|
||||
|
||||
return retMask;
|
||||
|
|
@ -248,7 +248,7 @@ void AccumulationVolume::unpackUpdate( NetConnection *connection, BitStream *str
|
|||
|
||||
if (stream->readFlag())
|
||||
{
|
||||
UNPACK_IMAGEASSET(connection, Texture);
|
||||
UNPACK_ASSET(connection, Texture);
|
||||
//setTexture(mTextureName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class AccumulationVolume : public ScenePolyhedralSpace
|
|||
virtual void _renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat );
|
||||
|
||||
DECLARE_IMAGEASSET(AccumulationVolume, Texture, onTextureChanged, GFXStaticTextureSRGBProfile);
|
||||
DECLARE_IMAGEASSET_NET_SETGET(AccumulationVolume, Texture, -1);
|
||||
DECLARE_ASSET_NET_SETGET(AccumulationVolume, Texture, -1);
|
||||
|
||||
void onTextureChanged() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ GuiControl* GuiInspectorTypeCubemapAssetPtr::constructEditControl()
|
|||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"CubemapAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getInspectObject(), mCaption);
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
setDataField(StringTable->insert("object"), NULL, String::ToString(mInspector->getInspectObject()).c_str());
|
||||
|
|
|
|||
|
|
@ -65,8 +65,6 @@ ConsoleSetType(TypeGUIAssetPtr)
|
|||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
*((const char**)dptr) = StringTable->insert(argv[0]);
|
||||
|
||||
return;
|
||||
|
|
@ -104,7 +102,7 @@ void GUIAsset::initPersistFields()
|
|||
&setScriptFile, &getScriptFile, "Path to the script file for the gui");
|
||||
|
||||
addProtectedField("GUIFile", TypeAssetLooseFilePath, Offset(mGUIFile, GUIAsset),
|
||||
&setScriptFile, &getScriptFile, "Path to the gui file");
|
||||
&setGUIFile, &getGUIFile, "Path to the gui file");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -117,28 +115,28 @@ void GUIAsset::copyTo(SimObject* object)
|
|||
|
||||
void GUIAsset::initializeAsset()
|
||||
{
|
||||
mGUIPath = getOwned() ? expandAssetFilePath(mGUIFile) : mGUIPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mGUIPath))
|
||||
Con::executeFile(mGUIPath, false, false);
|
||||
|
||||
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
Con::executeFile(mScriptPath, false, false);
|
||||
|
||||
mGUIPath = getOwned() ? expandAssetFilePath(mGUIFile) : mGUIPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mGUIPath))
|
||||
Con::executeFile(mGUIPath, false, false);
|
||||
}
|
||||
|
||||
void GUIAsset::onAssetRefresh()
|
||||
{
|
||||
mGUIPath = getOwned() ? expandAssetFilePath(mGUIFile) : mGUIPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mGUIPath))
|
||||
Con::executeFile(mGUIPath, false, false);
|
||||
|
||||
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
Con::executeFile(mScriptPath, false, false);
|
||||
|
||||
mGUIPath = getOwned() ? expandAssetFilePath(mGUIFile) : mGUIPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mGUIPath))
|
||||
Con::executeFile(mGUIPath, false, false);
|
||||
}
|
||||
|
||||
void GUIAsset::setGUIFile(const char* pScriptFile)
|
||||
|
|
@ -221,6 +219,20 @@ DefineEngineStaticMethod(GUIAsset, getAssetIdByGUIName, const char*, (const char
|
|||
{
|
||||
return GUIAsset::getAssetIdByGUIName(StringTable->insert(guiName));
|
||||
}
|
||||
|
||||
DefineEngineMethod(GUIAsset, getScriptPath, const char*, (), ,
|
||||
"Gets the script file path associated to this asset.\n"
|
||||
"@return The full script file path.")
|
||||
{
|
||||
return object->getScriptPath();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GUIAsset, getGUIPath, const char*, (), ,
|
||||
"Gets the GUI file path associated to this asset.\n"
|
||||
"@return The full script file path.")
|
||||
{
|
||||
return object->getGUIPath();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -252,7 +264,7 @@ GuiControl* GuiInspectorTypeGUIAssetPtr::constructEditControl()
|
|||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"GUIAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ StringTableEntry ImageAsset::smNoImageAssetFallback = NULL;
|
|||
|
||||
IMPLEMENT_CONOBJECT(ImageAsset);
|
||||
|
||||
ConsoleType(ImageAssetPtr, TypeImageAssetPtr, const char*, ASSET_ID_FIELD_PREFIX)
|
||||
ConsoleType(ImageAssetPtr, TypeImageAssetPtr, const char*, "")
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ ConsoleSetType(TypeImageAssetPtr)
|
|||
Con::warnf("(TypeImageAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
ConsoleType(assetIdString, TypeImageAssetId, const char*, ASSET_ID_FIELD_PREFIX)
|
||||
ConsoleType(assetIdString, TypeImageAssetId, const char*, "")
|
||||
|
||||
ConsoleGetType(TypeImageAssetId)
|
||||
{
|
||||
|
|
@ -147,7 +147,7 @@ void ImageAsset::consoleInit()
|
|||
Con::addVariable("$Core::NoImageAssetFallback", TypeString, &smNoImageAssetFallback,
|
||||
"The assetId of the texture to display when the requested image asset is missing.\n"
|
||||
"@ingroup GFX\n");
|
||||
|
||||
|
||||
smNoImageAssetFallback = StringTable->insert(Con::getVariable("$Core::NoImageAssetFallback"));
|
||||
}
|
||||
|
||||
|
|
@ -219,6 +219,10 @@ StringTableEntry ImageAsset::getAssetIdByFilename(StringTableEntry fileName)
|
|||
//acquire and bind the asset, and return it out
|
||||
imageAssetId = query.mAssetList[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetPtr<ImageAsset> imageAsset = imageAssetId; //ensures the fallback is loaded
|
||||
}
|
||||
|
||||
return imageAssetId;
|
||||
}
|
||||
|
|
@ -274,22 +278,8 @@ void ImageAsset::loadImage()
|
|||
|
||||
mLoadedState = Ok;
|
||||
mIsValidImage = true;
|
||||
return;
|
||||
|
||||
//GFXTexHandle texture = getTexture(&GFXStaticTextureSRGBProfile);
|
||||
|
||||
//mTexture.set(mImagePath, &GFXStaticTextureSRGBProfile, avar("%s() - mImage (line %d)", __FUNCTION__, __LINE__));
|
||||
|
||||
/*if (texture.isValid())
|
||||
{
|
||||
mIsValidImage = true;
|
||||
|
||||
//mBitmap = texture.getBitmap();
|
||||
|
||||
return;
|
||||
}*/
|
||||
|
||||
mChangeSignal.trigger();
|
||||
return;
|
||||
}
|
||||
mLoadedState = BadFileReference;
|
||||
|
||||
|
|
@ -494,21 +484,17 @@ GuiControl* GuiInspectorTypeImageAssetPtr::constructEditControl()
|
|||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ImageAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
|
||||
mInspector->getInspectObject()->getIdString(), mCaption);
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
const char* id = mInspector->getInspectObject()->getIdString();
|
||||
|
||||
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
mImageEdButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "ShapeEditorPlugin.openShapeAssetId(%d.getText());", retCtrl->getId());
|
||||
mImageEdButton->setField("Command", szBuffer);
|
||||
|
||||
char bitmapName[512] = "ToolsModule:GameTSCtrl_image";
|
||||
mImageEdButton->setBitmap(StringTable->insert(bitmapName));
|
||||
mImageEdButton->setHidden(true);
|
||||
|
||||
mImageEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mImageEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
|
|
@ -565,11 +551,24 @@ bool GuiInspectorTypeImageAssetPtr::renderTooltip(const Point2I& hoverPos, const
|
|||
if (!filename || !filename[0])
|
||||
return false;
|
||||
|
||||
GFXTexHandle texture(filename, &GFXStaticTextureSRGBProfile, avar("%s() - tooltip texture (line %d)", __FUNCTION__, __LINE__));
|
||||
StringTableEntry previewFilename = filename;
|
||||
if (Con::isFunction("getAssetPreviewImage"))
|
||||
{
|
||||
ConsoleValue consoleRet = Con::executef("getAssetPreviewImage", filename);
|
||||
previewFilename = StringTable->insert(consoleRet.getString());
|
||||
|
||||
if (AssetDatabase.isDeclaredAsset(previewFilename))
|
||||
{
|
||||
ImageAsset* previewAsset = AssetDatabase.acquireAsset<ImageAsset>(previewFilename);
|
||||
previewFilename = previewAsset->getImagePath();
|
||||
}
|
||||
}
|
||||
|
||||
GFXTexHandle texture(previewFilename, &GFXStaticTextureSRGBProfile, avar("%s() - tooltip texture (line %d)", __FUNCTION__, __LINE__));
|
||||
if (texture.isNull())
|
||||
return false;
|
||||
|
||||
// Render image at a reasonable screen size while
|
||||
// Render image at a reasonable screen size while
|
||||
// keeping its aspect ratio...
|
||||
Point2I screensize = getRoot()->getWindowSize();
|
||||
Point2I offset = hoverPos;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
#include "sim/netConnection.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "assetMacroHelpers.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
class ImageAsset : public AssetBase
|
||||
{
|
||||
|
|
@ -248,7 +248,7 @@ public: \
|
|||
Con::errorf("%s(%s)::_set%s() - image asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name), _in, ImageAsset::getAssetErrstrn(m##name##Asset->getStatus()).c_str());\
|
||||
return false; \
|
||||
}\
|
||||
else if (m##name)\
|
||||
else if (!m##name)\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s() - Couldn't load image \"%s\"", macroText(className), getName(), macroText(name), _in);\
|
||||
return false;\
|
||||
|
|
@ -270,46 +270,8 @@ public: \
|
|||
GFXTexHandle get##name##Resource() \
|
||||
{\
|
||||
return m##name;\
|
||||
}
|
||||
|
||||
#define DECLARE_IMAGEASSET_SETGET(className, name)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DECLARE_IMAGEASSET_NET_SETGET(className, name, bitmask)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
if(ret)\
|
||||
object->setMaskBits(bitmask);\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DEF_IMAGEASSET_BINDS(className,name)\
|
||||
DefineEngineMethod(className, get##name, const char*, (), , "get name")\
|
||||
{\
|
||||
return object->get##name(); \
|
||||
}\
|
||||
DefineEngineMethod(className, get##name##Asset, const char*, (), , assetText(name, asset reference))\
|
||||
{\
|
||||
return object->m##name##AssetId; \
|
||||
}\
|
||||
DefineEngineMethod(className, set##name, bool, (const char* map), , assetText(name,assignment. first tries asset then flat file.))\
|
||||
{\
|
||||
return object->_set##name(StringTable->insert(map));\
|
||||
}
|
||||
|
||||
#define INIT_IMAGEASSET(name) \
|
||||
m##name##Name = StringTable->EmptyString(); \
|
||||
m##name##AssetId = StringTable->EmptyString(); \
|
||||
m##name##Asset = NULL;
|
||||
}\
|
||||
bool name##Valid() {return (get##name() != StringTable->EmptyString() && m##name##Asset->getStatus() == AssetBase::Ok); }
|
||||
|
||||
#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
|
|
@ -325,11 +287,6 @@ DefineEngineMethod(className, set##name, bool, (const char* map), , assetText(na
|
|||
|
||||
#endif // SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
#define CLONE_IMAGEASSET(name) \
|
||||
m##name##Name = other.m##name##Name;\
|
||||
m##name##AssetId = other.m##name##AssetId;\
|
||||
m##name##Asset = other.m##name##Asset;
|
||||
|
||||
#define LOAD_IMAGEASSET(name)\
|
||||
if (m##name##AssetId != StringTable->EmptyString())\
|
||||
{\
|
||||
|
|
@ -341,53 +298,19 @@ if (m##name##AssetId != StringTable->EmptyString())\
|
|||
else Con::warnf("Warning: %s::LOAD_IMAGEASSET(%s)-%s", mClassName, m##name##AssetId, ImageAsset::getAssetErrstrn(assetState).c_str());\
|
||||
}
|
||||
|
||||
#define PACKDATA_IMAGEASSET(name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset.getAssetId());\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
#define UNPACKDATA_IMAGEASSET(name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = stream->readSTString();\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
|
||||
#define PACK_IMAGEASSET(netconn, name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
NetStringHandle assetIdStr = m##name##Asset.getAssetId();\
|
||||
netconn->packNetStringHandleU(stream, assetIdStr);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
#define UNPACK_IMAGEASSET(netconn, name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = StringTable->insert(netconn->unpackNetStringHandleU(stream).getString());\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Arrayed Asset Macros
|
||||
|
||||
//Arrayed Assets
|
||||
#define DECLARE_IMAGEASSET_ARRAY(className, name, profile, max) public: \
|
||||
#define DECLARE_IMAGEASSET_ARRAY(className, name, max) public: \
|
||||
static const U32 sm##name##Count = max;\
|
||||
GFXTexHandle m##name[max];\
|
||||
StringTableEntry m##name##Name[max]; \
|
||||
StringTableEntry m##name##AssetId[max];\
|
||||
AssetPtr<ImageAsset> m##name##Asset[max];\
|
||||
GFXTextureProfile * m##name##Profile = &profile;\
|
||||
GFXTextureProfile * m##name##Profile[max];\
|
||||
public: \
|
||||
const StringTableEntry get##name##File(const U32& index) const { return m##name##Name[index]; }\
|
||||
void set##name##File(const FileName &_in, const U32& index) { m##name##Name[index] = StringTable->insert(_in.c_str());}\
|
||||
|
|
@ -451,7 +374,7 @@ public: \
|
|||
}\
|
||||
if (get##name(index) != StringTable->EmptyString() && m##name##Name[index] != StringTable->insert("texhandle"))\
|
||||
{\
|
||||
m##name[index].set(get##name(index), m##name##Profile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));\
|
||||
m##name[index].set(get##name(index), m##name##Profile[index], avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
|
|
@ -467,7 +390,7 @@ public: \
|
|||
Con::errorf("%s(%s)::_set%s(%i) - image asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name), index, _in, ImageAsset::getAssetErrstrn(m##name##Asset[index]->getStatus()).c_str());\
|
||||
return false; \
|
||||
}\
|
||||
else if (bool(m##name[index]) == NULL)\
|
||||
else if (!m##name[index])\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s(%i) - Couldn't load image \"%s\"", macroText(className), getName(), macroText(name), index, _in);\
|
||||
return false; \
|
||||
|
|
@ -482,7 +405,12 @@ public: \
|
|||
else if (m##name##AssetId[index] != StringTable->EmptyString())\
|
||||
return m##name##AssetId[index];\
|
||||
else if (m##name##Name[index] != StringTable->EmptyString())\
|
||||
return StringTable->insert(Platform::makeRelativePathName(m##name##Name[index], Platform::getMainDotCsDir()));\
|
||||
{\
|
||||
if (String(m##name##Name[index]).startsWith("#") || String(m##name##Name[index]).startsWith("$"))\
|
||||
return StringTable->insert(m##name##Name[index]);\
|
||||
else\
|
||||
return StringTable->insert(Platform::makeRelativePathName(m##name##Name[index], Platform::getMainDotCsDir()));\
|
||||
}\
|
||||
else\
|
||||
return StringTable->EmptyString();\
|
||||
}\
|
||||
|
|
@ -491,7 +419,8 @@ public: \
|
|||
if(index >= sm##name##Count || index < 0)\
|
||||
return nullptr;\
|
||||
return m##name[index];\
|
||||
}
|
||||
}\
|
||||
bool name##Valid(const U32& id) {return (get##name(id) != StringTable->EmptyString() && m##name##Asset[id]->getStatus() == AssetBase::Ok); }
|
||||
|
||||
#define DECLARE_IMAGEASSET_ARRAY_SETGET(className, name)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
|
|
@ -521,6 +450,15 @@ public: \
|
|||
return ret;\
|
||||
}
|
||||
|
||||
#define INIT_IMAGEASSET_ARRAY(name, profile, index) \
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString(); \
|
||||
m##name##AssetId[index] = StringTable->EmptyString(); \
|
||||
m##name##Asset[index] = NULL;\
|
||||
m##name[index] = NULL;\
|
||||
m##name##Profile[index] = &profile;\
|
||||
}
|
||||
|
||||
#define DEF_IMAGEASSET_ARRAY_BINDS(className,name)\
|
||||
DefineEngineMethod(className, get##name, const char*, (S32 index), , "get name")\
|
||||
{\
|
||||
|
|
@ -537,13 +475,6 @@ DefineEngineMethod(className, set##name, bool, (const char* map, S32 index), , a
|
|||
return object->_set##name(StringTable->insert(map), index);\
|
||||
}
|
||||
|
||||
#define INIT_IMAGEASSET_ARRAY(name, index) \
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString(); \
|
||||
m##name##AssetId[index] = StringTable->EmptyString(); \
|
||||
m##name##Asset[index] = NULL;\
|
||||
}
|
||||
|
||||
#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
#define INITPERSISTFIELD_IMAGEASSET_ARRAY(name, arraySize, consoleClass, docs) \
|
||||
|
|
@ -558,13 +489,6 @@ DefineEngineMethod(className, set##name, bool, (const char* map, S32 index), , a
|
|||
|
||||
#endif
|
||||
|
||||
#define CLONE_IMAGEASSET_ARRAY(name, index) \
|
||||
{\
|
||||
m##name##Name[index] = other.m##name##Name[index];\
|
||||
m##name##AssetId[index] = other.m##name##AssetId[index];\
|
||||
m##name##Asset[index] = other.m##name##Asset[index];\
|
||||
}
|
||||
|
||||
#define LOAD_IMAGEASSET_ARRAY(name, index)\
|
||||
if (m##name##AssetId[index] != StringTable->EmptyString())\
|
||||
{\
|
||||
|
|
@ -576,41 +500,6 @@ if (m##name##AssetId[index] != StringTable->EmptyString())\
|
|||
else Con::warnf("Warning: %s::LOAD_IMAGEASSET(%s)-%s", mClassName, m##name##AssetId[index], ImageAsset::getAssetErrstrn(assetState).c_str());\
|
||||
}
|
||||
|
||||
#define PACKDATA_IMAGEASSET_ARRAY(name, index)\
|
||||
if (stream->writeFlag(m##name##Asset[index].notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset[index].getAssetId());\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name[index]);
|
||||
|
||||
#define UNPACKDATA_IMAGEASSET_ARRAY(name, index)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId[index] = stream->readSTString();\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name[index] = stream->readSTString();
|
||||
|
||||
#define PACK_IMAGEASSET_ARRAY(netconn, name, index)\
|
||||
if (stream->writeFlag(m##name##Asset[index].notNull()))\
|
||||
{\
|
||||
NetStringHandle assetIdStr = m##name##Asset[index].getAssetId();\
|
||||
netconn->packNetStringHandleU(stream, assetIdStr);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name[index]);
|
||||
|
||||
#define UNPACK_IMAGEASSET_ARRAY(netconn, name, index)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId[index] = StringTable->insert(netconn->unpackNetStringHandleU(stream).getString());\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name[index] = stream->readSTString();
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -391,6 +391,20 @@ DefineEngineMethod(LevelAsset, getDecalsPath, const char*, (), ,
|
|||
return object->getDecalsPath();
|
||||
}
|
||||
|
||||
DefineEngineMethod(LevelAsset, getForestPath, const char*, (), ,
|
||||
"Gets the full path of the asset's defined forest file.\n"
|
||||
"@return The string result of the forest path")
|
||||
{
|
||||
return object->getForestPath();
|
||||
}
|
||||
|
||||
DefineEngineMethod(LevelAsset, getNavmeshPath, const char*, (), ,
|
||||
"Gets the full path of the asset's defined navmesh file.\n"
|
||||
"@return The string result of the navmesh path")
|
||||
{
|
||||
return object->getNavmeshPath();
|
||||
}
|
||||
|
||||
DefineEngineMethod(LevelAsset, loadDependencies, void, (), ,
|
||||
"Initiates the loading of asset dependencies for this level.")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifndef MATERIALASSET_H
|
||||
#include "MaterialAsset.h"
|
||||
|
|
@ -155,8 +154,9 @@ void MaterialAsset::initPersistFields()
|
|||
Parent::initPersistFields();
|
||||
|
||||
//addField("shaderGraph", TypeRealString, Offset(mShaderGraphFile, MaterialAsset), "");
|
||||
addProtectedField("scriptFile", TypeAssetLooseFilePath, Offset(mScriptFile, MaterialAsset),
|
||||
&setScriptFile, &getScriptFile, "Path to the file containing the material definition.");
|
||||
//addProtectedField("scriptFile", TypeAssetLooseFilePath, Offset(mScriptFile, MaterialAsset),
|
||||
// &setScriptFile, &getScriptFile, "Path to the file containing the material definition.");
|
||||
addField("scriptFile", TypeAssetLooseFilePath, Offset(mScriptFile, MaterialAsset), "");
|
||||
|
||||
addField("materialDefinitionName", TypeString, Offset(mMatDefinitionName, MaterialAsset), "Name of the material definition this asset is for.");
|
||||
}
|
||||
|
|
@ -168,8 +168,34 @@ void MaterialAsset::initializeAsset()
|
|||
|
||||
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
Con::executeFile(mScriptPath, false, false);
|
||||
if (mMatDefinitionName == StringTable->EmptyString())
|
||||
{
|
||||
mLoadedState = Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (size() != 0 && mScriptPath == StringTable->EmptyString())
|
||||
{
|
||||
mLoadedState = EmbeddedDefinition;
|
||||
}
|
||||
else if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
{
|
||||
if (!Sim::findObject(mMatDefinitionName))
|
||||
{
|
||||
if (Con::executeFile(mScriptPath, false, false))
|
||||
{
|
||||
mLoadedState = ScriptLoaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLoadedState = Failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLoadedState = DefinitionAlreadyExists;
|
||||
}
|
||||
}
|
||||
|
||||
loadMaterial();
|
||||
}
|
||||
|
|
@ -178,8 +204,28 @@ void MaterialAsset::onAssetRefresh()
|
|||
{
|
||||
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
|
||||
|
||||
if (mMatDefinitionName == StringTable->EmptyString())
|
||||
{
|
||||
mLoadedState = Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
Con::executeFile(mScriptPath, false, false);
|
||||
{
|
||||
//Since we're refreshing, we can assume that the file we're executing WILL have an existing definition.
|
||||
//But that definition, whatever it is, is the 'correct' one, so we enable the Replace Existing behavior
|
||||
//when the engine encounters a named object conflict.
|
||||
String redefineBehaviorPrev = Con::getVariable("$Con::redefineBehavior");
|
||||
Con::setVariable("$Con::redefineBehavior", "replaceExisting");
|
||||
|
||||
if (Con::executeFile(mScriptPath, false, false))
|
||||
mLoadedState = ScriptLoaded;
|
||||
else
|
||||
mLoadedState = Failed;
|
||||
|
||||
//And now that we've executed, switch back to the prior behavior
|
||||
Con::setVariable("$Con::redefineBehavior", redefineBehaviorPrev.c_str());
|
||||
}
|
||||
|
||||
loadMaterial();
|
||||
}
|
||||
|
|
@ -189,7 +235,6 @@ void MaterialAsset::setScriptFile(const char* pScriptFile)
|
|||
// Sanity!
|
||||
AssertFatal(pScriptFile != NULL, "Cannot use a NULL script file.");
|
||||
|
||||
// Fetch image file.
|
||||
pScriptFile = StringTable->insert(pScriptFile, true);
|
||||
|
||||
// Update.
|
||||
|
|
@ -204,9 +249,28 @@ void MaterialAsset::setScriptFile(const char* pScriptFile)
|
|||
void MaterialAsset::loadMaterial()
|
||||
{
|
||||
if (mMaterialDefinition)
|
||||
SAFE_DELETE(mMaterialDefinition);
|
||||
{
|
||||
mMaterialDefinition->safeDeleteObject();
|
||||
}
|
||||
|
||||
if (mMatDefinitionName != StringTable->EmptyString())
|
||||
if (mLoadedState == EmbeddedDefinition)
|
||||
{
|
||||
if (size() != 0)
|
||||
{
|
||||
for (U32 i = 0; i < size(); i++)
|
||||
{
|
||||
mMaterialDefinition = dynamic_cast<Material*>(getObject(i));
|
||||
if (mMaterialDefinition)
|
||||
{
|
||||
mLoadedState = Ok;
|
||||
mMaterialDefinition->setInternalName(getAssetId());
|
||||
mMaterialDefinition->reload();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((mLoadedState == ScriptLoaded || mLoadedState == DefinitionAlreadyExists) && mMatDefinitionName != StringTable->EmptyString())
|
||||
{
|
||||
Material* matDef;
|
||||
if (!Sim::findObject(mMatDefinitionName, matDef))
|
||||
|
|
@ -219,7 +283,7 @@ void MaterialAsset::loadMaterial()
|
|||
mMaterialDefinition = matDef;
|
||||
|
||||
mLoadedState = Ok;
|
||||
|
||||
mMaterialDefinition->setInternalName(getAssetId());
|
||||
mMaterialDefinition->reload();
|
||||
return;
|
||||
}
|
||||
|
|
@ -255,11 +319,11 @@ U32 MaterialAsset::getAssetByMaterialName(StringTableEntry matName, AssetPtr<Mat
|
|||
//handle noshape not being loaded itself
|
||||
if ((*matAsset)->mLoadedState == BadFileReference)
|
||||
{
|
||||
Con::warnf("ShapeAsset::getAssetByMaterialName - Finding of associated with aterial name %s failed, and fallback asset reported error of Bad File Reference.", matName);
|
||||
Con::warnf("MaterialAsset::getAssetByMaterialName - Finding of associated with aterial name %s failed, and fallback asset reported error of Bad File Reference.", matName);
|
||||
return AssetErrCode::BadFileReference;
|
||||
}
|
||||
|
||||
Con::warnf("ShapeAsset::getAssetByMaterialName - Finding of associated with aterial name %s failed, utilizing fallback asset", matName);
|
||||
Con::warnf("MaterialAsset::getAssetByMaterialName - Finding of associated with aterial name %s failed, utilizing fallback asset", matName);
|
||||
|
||||
(*matAsset)->mLoadedState = AssetErrCode::UsingFallback;
|
||||
return AssetErrCode::UsingFallback;
|
||||
|
|
@ -278,6 +342,12 @@ U32 MaterialAsset::getAssetByMaterialName(StringTableEntry matName, AssetPtr<Mat
|
|||
AssetDatabase.releaseAsset(query.mAssetList[i]); //cleanup if that's not the one we needed
|
||||
}
|
||||
}
|
||||
|
||||
//Somehow we failed to bind an asset, so just use the fallback and mark the failure
|
||||
matAsset->setAssetId(MaterialAsset::smNoMaterialAssetFallback);
|
||||
(*matAsset)->mLoadedState = AssetErrCode::UsingFallback;
|
||||
return AssetErrCode::UsingFallback;
|
||||
|
||||
}
|
||||
|
||||
StringTableEntry MaterialAsset::getAssetIdByMaterialName(StringTableEntry matName)
|
||||
|
|
@ -341,6 +411,17 @@ U32 MaterialAsset::getAssetById(StringTableEntry assetId, AssetPtr<MaterialAsset
|
|||
}
|
||||
}
|
||||
|
||||
SimObjectPtr<Material> MaterialAsset::findMaterialDefinitionByAssetId(StringTableEntry assetId)
|
||||
{
|
||||
SimSet* matSet = MATMGR->getMaterialSet();
|
||||
if (matSet)
|
||||
{
|
||||
SimObjectPtr<Material> matDef = dynamic_cast<Material*>(matSet->findObjectByInternalName(assetId));
|
||||
return matDef;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
DefineEngineStaticMethod(MaterialAsset, getAssetIdByMaterialName, const char*, (const char* materialName), (""),
|
||||
"Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n"
|
||||
|
|
@ -349,9 +430,21 @@ DefineEngineStaticMethod(MaterialAsset, getAssetIdByMaterialName, const char*, (
|
|||
return MaterialAsset::getAssetIdByMaterialName(StringTable->insert(materialName));
|
||||
}
|
||||
|
||||
//MaterialAsset::findMaterialDefinitionByAssetId("Prototyping:Detail")
|
||||
DefineEngineStaticMethod(MaterialAsset, findMaterialDefinitionByAssetId, S32, (const char* assetId), (""),
|
||||
"Queries the MaterialSet to see if any MaterialDefinition exists that is associated to the provided assetId.\n"
|
||||
"@return The MaterialDefinition Id associated to the assetId, if any")
|
||||
{
|
||||
SimObjectPtr<Material> matDef = MaterialAsset::findMaterialDefinitionByAssetId(StringTable->insert(assetId));
|
||||
if (matDef.isNull())
|
||||
return SimObjectId(0);
|
||||
else
|
||||
return matDef->getId();
|
||||
}
|
||||
|
||||
|
||||
DefineEngineMethod(MaterialAsset, getScriptPath, const char*, (), ,
|
||||
"Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n"
|
||||
"@return The AssetId of the associated asset, if any.")
|
||||
"Gets the script file path for the asset.")
|
||||
{
|
||||
return object->getScriptPath();
|
||||
}
|
||||
|
|
@ -385,8 +478,8 @@ GuiControl* GuiInspectorTypeMaterialAssetPtr::constructEditControl()
|
|||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"MaterialAsset\", \"AssetBrowser.changeAsset\", %s, \"\");",
|
||||
getIdString());
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"MaterialAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
|
||||
|
|
|
|||
|
|
@ -48,12 +48,15 @@
|
|||
#include "sim/netConnection.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUI_INSPECTOR_TYPES_H_
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
#endif
|
||||
|
||||
#include "materials/matTextureTarget.h"
|
||||
#include "materials/materialDefinition.h"
|
||||
#include "materials/customMaterialDefinition.h"
|
||||
#include "materials/materialManager.h"
|
||||
#include "assetMacroHelpers.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class MaterialAsset : public AssetBase
|
||||
|
|
@ -70,6 +73,14 @@ class MaterialAsset : public AssetBase
|
|||
public:
|
||||
static StringTableEntry smNoMaterialAssetFallback;
|
||||
|
||||
enum MaterialAssetErrCode
|
||||
{
|
||||
ScriptLoaded = AssetErrCode::Extended,
|
||||
DefinitionAlreadyExists,
|
||||
EmbeddedDefinition,
|
||||
Extended
|
||||
};
|
||||
|
||||
public:
|
||||
MaterialAsset();
|
||||
virtual ~MaterialAsset();
|
||||
|
|
@ -100,6 +111,7 @@ public:
|
|||
/// <returns>AssetId of matching asset.</returns>
|
||||
static StringTableEntry getAssetIdByMaterialName(StringTableEntry matName);
|
||||
static U32 getAssetById(StringTableEntry assetId, AssetPtr<MaterialAsset>* materialAsset);
|
||||
static SimObjectPtr<Material> findMaterialDefinitionByAssetId(StringTableEntry assetId);
|
||||
static U32 getAssetByMaterialName(StringTableEntry matName, AssetPtr<MaterialAsset>* matAsset);
|
||||
|
||||
/// Declare Console Object.
|
||||
|
|
@ -231,7 +243,7 @@ public: \
|
|||
Con::errorf("%s::_set%s() - material asset failure\"%s\" due to [%s]", macroText(className), macroText(name), _in, MaterialAsset::getAssetErrstrn(m##name##Asset->getStatus()).c_str());\
|
||||
return false; \
|
||||
}\
|
||||
else if (m##name)\
|
||||
else if (!m##name)\
|
||||
{\
|
||||
Con::errorf("%s::_set%s() - Couldn't load material \"%s\"", macroText(className), macroText(name), _in);\
|
||||
return false;\
|
||||
|
|
@ -253,47 +265,8 @@ public: \
|
|||
SimObjectPtr<Material> get##name##Resource() \
|
||||
{\
|
||||
return m##name;\
|
||||
}
|
||||
|
||||
#define DECLARE_MATERIALASSET_SETGET(className, name)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DECLARE_MATERIALASSET_NET_SETGET(className, name, bitmask)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
if(ret)\
|
||||
object->setMaskBits(bitmask);\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DEF_MATERIALASSET_BINDS(className,name)\
|
||||
DefineEngineMethod(className, get##name, const char*, (), , "get name")\
|
||||
{\
|
||||
return object->get##name(); \
|
||||
}\
|
||||
DefineEngineMethod(className, get##name##Asset, const char*, (), , assetText(name, asset reference))\
|
||||
{\
|
||||
return object->m##name##AssetId; \
|
||||
}\
|
||||
DefineEngineMethod(className, set##name, bool, (const char* mat), , assetText(name,assignment. first tries asset then material name.))\
|
||||
{\
|
||||
return object->_set##name(StringTable->insert(mat));\
|
||||
}
|
||||
|
||||
#define INIT_MATERIALASSET(name) \
|
||||
m##name##Name = StringTable->EmptyString(); \
|
||||
m##name##AssetId = StringTable->EmptyString(); \
|
||||
m##name##Asset = NULL;\
|
||||
m##name = NULL;
|
||||
}\
|
||||
bool is##name##Valid() {return (get##name() != StringTable->EmptyString() && m##name##Asset->getStatus() == AssetBase::Ok); }
|
||||
|
||||
#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
|
|
@ -309,11 +282,6 @@ DefineEngineMethod(className, set##name, bool, (const char* mat), , assetText(na
|
|||
|
||||
#endif // SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
#define CLONE_MATERIALASSET(name) \
|
||||
m##name##Name = other.m##name##Name;\
|
||||
m##name##AssetId = other.m##name##AssetId;\
|
||||
m##name##Asset = other.m##name##Asset;
|
||||
|
||||
#define LOAD_MATERIALASSET(name)\
|
||||
if (m##name##AssetId != StringTable->EmptyString())\
|
||||
{\
|
||||
|
|
@ -324,42 +292,6 @@ if (m##name##AssetId != StringTable->EmptyString())\
|
|||
}\
|
||||
else Con::warnf("Warning: %s::LOAD_MATERIALASSET(%s)-%s", mClassName, m##name##AssetId, MaterialAsset::getAssetErrstrn(assetState).c_str());\
|
||||
}
|
||||
|
||||
#define PACKDATA_MATERIALASSET(name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset.getAssetId());\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
#define UNPACKDATA_MATERIALASSET(name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = stream->readSTString();\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
|
||||
#define PACK_MATERIALASSET(netconn, name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
NetStringHandle assetIdStr = m##name##Asset.getAssetId();\
|
||||
netconn->packNetStringHandleU(stream, assetIdStr);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
#define UNPACK_MATERIALASSET(netconn, name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = StringTable->insert(netconn->unpackNetStringHandleU(stream).getString());\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ GuiControl* GuiInspectorTypeParticleAssetPtr::constructEditControl()
|
|||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ParticleAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
|
|
|
|||
|
|
@ -206,3 +206,21 @@ void PostEffectAsset::setGLSLShaderFile(const char* pShaderFile)
|
|||
// Refresh the asset.
|
||||
refreshAsset();
|
||||
}
|
||||
|
||||
DefineEngineMethod(PostEffectAsset, getScriptPath, const char*, (), ,
|
||||
"Gets the script file path for the asset.")
|
||||
{
|
||||
return object->getScriptPath();
|
||||
}
|
||||
|
||||
DefineEngineMethod(PostEffectAsset, getHLSLShaderPath, const char*, (), ,
|
||||
"Gets the HLSL Shader file path for the asset.")
|
||||
{
|
||||
return object->getHLSLShaderPath();
|
||||
}
|
||||
|
||||
DefineEngineMethod(PostEffectAsset, getGLSLShaderPath, const char*, (), ,
|
||||
"Gets the GLSL Shader file path for the asset.")
|
||||
{
|
||||
return object->getGLSLShaderPath();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,17 +190,12 @@ bool ScriptAsset::execScript()
|
|||
if (handle)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
{
|
||||
return Con::executeFile(mScriptPath, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::errorf("ScriptAsset:execScript() - Script asset must have a valid file to exec");
|
||||
return false;
|
||||
}
|
||||
Con::errorf("ScriptAsset:execScript() - Script asset must have a valid file to exec");
|
||||
return false;
|
||||
}
|
||||
|
||||
DefineEngineMethod(ScriptAsset, execScript, bool, (), ,
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ void ShapeAnimationAsset::initializeAsset(void)
|
|||
|
||||
mSourceShape = ResourceManager::get().load(mFilePath);
|
||||
|
||||
if (!mSourceShape->addSequence("ambient", "", mAnimationName, mStartFrame, mEndFrame, mPadRotation, mPadTransforms))
|
||||
if (!mSourceShape || !mSourceShape->addSequence("ambient", "", mAnimationName, mStartFrame, mEndFrame, mPadRotation, mPadTransforms))
|
||||
{
|
||||
Con::errorf("ShapeAnimationAsset::initializeAsset - Unable to do initial setup of the animation clip named %s for asset %s", mAnimationName, getAssetName());
|
||||
return;
|
||||
|
|
@ -204,3 +204,9 @@ DefineEngineMethod(ShapeAnimationAsset, getAnimationCount, S32, (), ,
|
|||
{
|
||||
return object->getAnimationCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod(ShapeAnimationAsset, getAnimationPath, const char*, (), ,
|
||||
"Gets the Animation file path associated to this asset.")
|
||||
{
|
||||
return object->getAnimationPath();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@
|
|||
#ifdef TORQUE_TOOLS
|
||||
#include "ts/tsLastDetail.h"
|
||||
#endif
|
||||
#include "util/imposterCapture.h"
|
||||
|
||||
#include "ts/tsShapeInstance.h"
|
||||
#include "gfx/bitmap/imageUtils.h"
|
||||
|
||||
StringTableEntry ShapeAsset::smNoShapeAssetFallback = NULL;
|
||||
|
||||
|
|
@ -128,6 +132,13 @@ ShapeAsset::ShapeAsset()
|
|||
mConstructorFileName = StringTable->EmptyString();
|
||||
mFilePath = StringTable->EmptyString();
|
||||
mConstructorFilePath = StringTable->EmptyString();
|
||||
|
||||
mDiffuseImposterFileName = StringTable->EmptyString();
|
||||
mDiffuseImposterPath = StringTable->EmptyString();
|
||||
mNormalImposterFileName = StringTable->EmptyString();
|
||||
mNormalImposterPath = StringTable->EmptyString();
|
||||
|
||||
|
||||
mLoadedState = AssetErrCode::NotLoaded;
|
||||
}
|
||||
|
||||
|
|
@ -161,6 +172,12 @@ void ShapeAsset::initPersistFields()
|
|||
&setShapeFile, &getShapeFile, "Path to the shape file we want to render");
|
||||
addProtectedField("constuctorFileName", TypeAssetLooseFilePath, Offset(mConstructorFileName, ShapeAsset),
|
||||
&setShapeConstructorFile, &getShapeConstructorFile, "Path to the shape file we want to render");
|
||||
|
||||
addProtectedField("diffuseImposterFileName", TypeAssetLooseFilePath, Offset(mDiffuseImposterFileName, ShapeAsset),
|
||||
&setDiffuseImposterFile, &getDiffuseImposterFile, "Path to the diffuse imposter file we want to render");
|
||||
addProtectedField("normalImposterFileName", TypeAssetLooseFilePath, Offset(mNormalImposterFileName, ShapeAsset),
|
||||
&setNormalImposterFile, &getNormalImposterFile, "Path to the normal imposter file we want to render");
|
||||
|
||||
}
|
||||
|
||||
void ShapeAsset::setDataField(StringTableEntry slotName, StringTableEntry array, StringTableEntry value)
|
||||
|
|
@ -192,6 +209,20 @@ void ShapeAsset::initializeAsset()
|
|||
|
||||
mConstructorFilePath = getOwned() ? expandAssetFilePath(mConstructorFilePath) : mConstructorFilePath;
|
||||
|
||||
mDiffuseImposterPath = getOwned() ? expandAssetFilePath(mDiffuseImposterFileName) : mDiffuseImposterFileName;
|
||||
if (mDiffuseImposterPath == StringTable->EmptyString())
|
||||
{
|
||||
String diffusePath = String(mFilePath) + "_imposter.dds";
|
||||
mDiffuseImposterPath = StringTable->insert(diffusePath.c_str());
|
||||
}
|
||||
|
||||
mNormalImposterPath = getOwned() ? expandAssetFilePath(mNormalImposterFileName) : mNormalImposterFileName;
|
||||
if (mNormalImposterPath == StringTable->EmptyString())
|
||||
{
|
||||
String normalPath = String(mFilePath) + "_imposter_normals.dds";
|
||||
mNormalImposterPath = StringTable->insert(normalPath.c_str());
|
||||
}
|
||||
|
||||
loadShape();
|
||||
}
|
||||
|
||||
|
|
@ -231,6 +262,42 @@ void ShapeAsset::setShapeConstructorFile(const char* pShapeConstructorFile)
|
|||
refreshAsset();
|
||||
}
|
||||
|
||||
void ShapeAsset::setDiffuseImposterFile(const char* pImageFile)
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal(pImageFile != NULL, "Cannot use a NULL image file.");
|
||||
|
||||
// Fetch image file.
|
||||
pImageFile = StringTable->insert(pImageFile, true);
|
||||
|
||||
// Ignore no change,
|
||||
if (pImageFile == mDiffuseImposterFileName)
|
||||
return;
|
||||
|
||||
mDiffuseImposterFileName = getOwned() ? expandAssetFilePath(pImageFile) : pImageFile;
|
||||
|
||||
// Refresh the asset.
|
||||
refreshAsset();
|
||||
}
|
||||
|
||||
void ShapeAsset::setNormalImposterFile(const char* pImageFile)
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal(pImageFile != NULL, "Cannot use a NULL image file.");
|
||||
|
||||
// Fetch image file.
|
||||
pImageFile = StringTable->insert(pImageFile, true);
|
||||
|
||||
// Ignore no change,
|
||||
if (pImageFile == mNormalImposterFileName)
|
||||
return;
|
||||
|
||||
mNormalImposterFileName = getOwned() ? expandAssetFilePath(pImageFile) : pImageFile;
|
||||
|
||||
// Refresh the asset.
|
||||
refreshAsset();
|
||||
}
|
||||
|
||||
void ShapeAsset::_onResourceChanged(const Torque::Path &path)
|
||||
{
|
||||
if (path != Torque::Path(mFilePath) )
|
||||
|
|
@ -291,6 +358,10 @@ bool ShapeAsset::loadShape()
|
|||
return false; //if it failed to load, bail out
|
||||
}
|
||||
|
||||
mShape->setupBillboardDetails(mFilePath, mDiffuseImposterPath, mNormalImposterPath);
|
||||
|
||||
//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
|
||||
|
|
@ -402,6 +473,10 @@ StringTableEntry ShapeAsset::getAssetIdByFilename(StringTableEntry fileName)
|
|||
//acquire and bind the asset, and return it out
|
||||
shapeAssetId = query.mAssetList[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetPtr<ShapeAsset> shapeAsset = shapeAssetId; //ensures the fallback is loaded
|
||||
}
|
||||
|
||||
return shapeAssetId;
|
||||
}
|
||||
|
|
@ -492,25 +567,97 @@ ShapeAnimationAsset* ShapeAsset::getAnimation(S32 index)
|
|||
}
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
const char* ShapeAsset::generateCachedPreviewImage(S32 resolution)
|
||||
const char* ShapeAsset::generateCachedPreviewImage(S32 resolution, String overrideMaterial)
|
||||
{
|
||||
if (!mShape)
|
||||
return "";
|
||||
|
||||
TSLastDetail* dt = new TSLastDetail(mShape,
|
||||
mFilePath,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
resolution);
|
||||
// We're gonna render... make sure we can.
|
||||
bool sceneBegun = GFX->canCurrentlyRender();
|
||||
if (!sceneBegun)
|
||||
GFX->beginScene();
|
||||
|
||||
dt->update();
|
||||
// We need to create our own instance to render with.
|
||||
TSShapeInstance* shape = new TSShapeInstance(mShape, true);
|
||||
|
||||
delete dt;
|
||||
if (overrideMaterial.isNotEmpty())
|
||||
{
|
||||
Material *tMat = dynamic_cast<Material*>(Sim::findObject(overrideMaterial));
|
||||
if (tMat)
|
||||
shape->reSkin(tMat->mMapTo, mShape->materialList->getMaterialName(0));
|
||||
}
|
||||
// Animate the shape once.
|
||||
shape->animate(0);
|
||||
|
||||
return mFilePath;
|
||||
// So we don't have to change it everywhere.
|
||||
const GFXFormat format = GFXFormatR8G8B8A8;
|
||||
|
||||
GBitmap* imposter = NULL;
|
||||
GBitmap* imposterNrml = NULL;
|
||||
|
||||
ImposterCapture* imposterCap = new ImposterCapture();
|
||||
|
||||
static const MatrixF topXfm(EulerF(-M_PI_F / 2.0f, 0, 0));
|
||||
static const MatrixF bottomXfm(EulerF(M_PI_F / 2.0f, 0, 0));
|
||||
|
||||
MatrixF angMat;
|
||||
|
||||
S32 mip = 0;
|
||||
|
||||
PROFILE_START(ShapeAsset_generateCachedPreviewImage);
|
||||
|
||||
//dMemset(destBmp.getWritableBits(mip), 0, destBmp.getWidth(mip) * destBmp.getHeight(mip) * GFXFormat_getByteSize(format));
|
||||
|
||||
F32 rotX = -(mDegToRad(60.0) - 0.5f * M_PI_F);
|
||||
F32 rotZ = -(mDegToRad(45.0) - 0.5f * M_PI_F);
|
||||
|
||||
// We capture the images in a particular order which must
|
||||
// match the order expected by the imposter renderer.
|
||||
|
||||
imposterCap->begin(shape, 0, resolution, mShape->mRadius, mShape->center);
|
||||
|
||||
angMat.mul(MatrixF(EulerF(rotX, 0, 0)),
|
||||
MatrixF(EulerF(0, 0, rotZ)));
|
||||
|
||||
imposterCap->capture(angMat, &imposter, &imposterNrml);
|
||||
|
||||
imposterCap->end();
|
||||
|
||||
PROFILE_END(); // ShapeAsset_generateCachedPreviewImage
|
||||
|
||||
delete imposterCap;
|
||||
delete shape;
|
||||
|
||||
String dumpPath = String(mFilePath) + "_Preview.dds";
|
||||
|
||||
char* returnBuffer = Con::getReturnBuffer(128);
|
||||
dSprintf(returnBuffer, 128, "%s", dumpPath.c_str());
|
||||
|
||||
/*FileStream stream;
|
||||
if (stream.open(dumpPath, Torque::FS::File::Write))
|
||||
destBmp.writeBitmap("png", stream);
|
||||
stream.close();*/
|
||||
|
||||
DDSFile* ddsDest = DDSFile::createDDSFileFromGBitmap(imposter);
|
||||
ImageUtil::ddsCompress(ddsDest, GFXFormatBC2);
|
||||
|
||||
// Finally save the imposters to disk.
|
||||
FileStream fs;
|
||||
if (fs.open(returnBuffer, Torque::FS::File::Write))
|
||||
{
|
||||
ddsDest->write(fs);
|
||||
fs.close();
|
||||
}
|
||||
|
||||
delete ddsDest;
|
||||
delete imposter;
|
||||
delete imposterNrml;
|
||||
|
||||
// If we did a begin then end it now.
|
||||
if (!sceneBegun)
|
||||
GFX->endScene();
|
||||
|
||||
return returnBuffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -536,7 +683,7 @@ DefineEngineMethod(ShapeAsset, getAnimation, ShapeAnimationAsset*, (S32 index),
|
|||
return object->getAnimation(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod(ShapeAsset, getShapeFile, const char*, (), ,
|
||||
DefineEngineMethod(ShapeAsset, getShapePath, const char*, (), ,
|
||||
"Gets the shape's file path\n"
|
||||
"@return The filename of the shape file")
|
||||
{
|
||||
|
|
@ -557,9 +704,12 @@ DefineEngineMethod(ShapeAsset, getStatusString, String, (), , "get status string
|
|||
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
DefineEngineMethod(ShapeAsset, generateCachedPreviewImage, const char*, (S32 resolution), (256), "")
|
||||
DefineEngineMethod(ShapeAsset, generateCachedPreviewImage, const char*, (S32 resolution, const char* overrideMaterialName), (256, ""),
|
||||
"Generates a baked preview image of the given shapeAsset. Only really used for generating Asset Browser icons.\n"
|
||||
"@param resolution Optional field for what resolution to bake the preview image at. Must be pow2\n"
|
||||
"@param overrideMaterialName Optional field for overriding the material used when rendering the shape for the bake.")
|
||||
{
|
||||
return object->generateCachedPreviewImage(resolution);
|
||||
return object->generateCachedPreviewImage(resolution, overrideMaterialName);
|
||||
}
|
||||
|
||||
DefineEngineStaticMethod(ShapeAsset, getAssetIdByFilename, const char*, (const char* filePath), (""),
|
||||
|
|
@ -599,12 +749,10 @@ GuiControl* GuiInspectorTypeShapeAssetPtr::constructEditControl()
|
|||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ShapeAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
|
||||
mInspector->getInspectObject()->getIdString(), mCaption);
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ShapeAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
const char* id = mInspector->getInspectObject()->getIdString();
|
||||
|
||||
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
#ifndef _BITSTREAM_H_
|
||||
#include "core/stream/bitStream.h"
|
||||
#endif
|
||||
#include "assetMacroHelpers.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
class ShapeAsset : public AssetBase
|
||||
{
|
||||
|
|
@ -72,6 +73,12 @@ protected:
|
|||
StringTableEntry mConstructorFilePath;
|
||||
Resource<TSShape> mShape;
|
||||
|
||||
StringTableEntry mDiffuseImposterFileName;
|
||||
StringTableEntry mDiffuseImposterPath;
|
||||
|
||||
StringTableEntry mNormalImposterFileName;
|
||||
StringTableEntry mNormalImposterPath;
|
||||
|
||||
//Material assets we're dependent on and use
|
||||
Vector<StringTableEntry> mMaterialAssetIds;
|
||||
Vector<AssetPtr<MaterialAsset>> mMaterialAssets;
|
||||
|
|
@ -169,13 +176,22 @@ public:
|
|||
inline StringTableEntry getShapeFilePath(void) const { return mFilePath; };
|
||||
inline StringTableEntry getShapeConstructorFilePath(void) const { return mConstructorFilePath; };
|
||||
|
||||
//Imposter images
|
||||
void setDiffuseImposterFile(const char* pImageFile);
|
||||
inline StringTableEntry getDiffuseImposterFile(void) const { return mDiffuseImposterFileName; };
|
||||
inline StringTableEntry getDiffuseImposterFilePath(void) const { return mDiffuseImposterPath; };
|
||||
|
||||
void setNormalImposterFile(const char* pImageFile);
|
||||
inline StringTableEntry getNormalImposterFile(void) const { return mNormalImposterFileName; };
|
||||
inline StringTableEntry getNormalImposterFilePath(void) const { return mNormalImposterPath; };
|
||||
|
||||
static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAsset>* shapeAsset);
|
||||
|
||||
static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
|
||||
static U32 getAssetById(StringTableEntry assetId, AssetPtr<ShapeAsset>* shapeAsset);
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
const char* generateCachedPreviewImage(S32 resolution);
|
||||
const char* generateCachedPreviewImage(S32 resolution, String overrideMaterial = "");
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
|
@ -187,6 +203,10 @@ protected:
|
|||
static bool setShapeConstructorFile(void* obj, const char* index, const char* data) { static_cast<ShapeAsset*>(obj)->setShapeConstructorFile(data); return false; }
|
||||
static const char* getShapeConstructorFile(void* obj, const char* data) { return static_cast<ShapeAsset*>(obj)->getShapeConstructorFile(); }
|
||||
|
||||
static bool setDiffuseImposterFile(void* obj, StringTableEntry index, StringTableEntry data) { static_cast<ShapeAsset*>(obj)->setDiffuseImposterFile(data); return false; }
|
||||
static const char* getDiffuseImposterFile(void* obj, const char* data) { return static_cast<ShapeAsset*>(obj)->getDiffuseImposterFile(); }
|
||||
static bool setNormalImposterFile(void* obj, StringTableEntry index, StringTableEntry data) { static_cast<ShapeAsset*>(obj)->setNormalImposterFile(data); return false; }
|
||||
static const char* getNormalImposterFile(void* obj, const char* data) { return static_cast<ShapeAsset*>(obj)->getNormalImposterFile(); }
|
||||
};
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
|
|
@ -299,7 +319,7 @@ public: \
|
|||
Con::errorf("%s(%s)::_set%s() - shape asset failure \"%s\" due to [%s]", macroText(className), getName(), macroText(name), _in, ShapeAsset::getAssetErrstrn(m##name##Asset->getStatus()).c_str());\
|
||||
return false; \
|
||||
}\
|
||||
else if (m##name)\
|
||||
else if (!m##name)\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s() - Couldn't load shape \"%s\"", macroText(className), getName(), macroText(name), _in);\
|
||||
return false;\
|
||||
|
|
@ -321,47 +341,8 @@ public: \
|
|||
Resource<TSShape> get##name##Resource() \
|
||||
{\
|
||||
return m##name;\
|
||||
}
|
||||
|
||||
#define DECLARE_SHAPEASSET_SETGET(className, name)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DECLARE_SHAPEASSET_NET_SETGET(className, name, bitmask)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
if(ret)\
|
||||
object->setMaskBits(bitmask);\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DEF_SHAPEASSET_BINDS(className,name)\
|
||||
DefineEngineMethod(className, get##name, String, (), , "get name")\
|
||||
{\
|
||||
return object->get##name(); \
|
||||
}\
|
||||
DefineEngineMethod(className, get##name##Asset, String, (), , assetText(name, asset reference))\
|
||||
{\
|
||||
return object->m##name##AssetId; \
|
||||
}\
|
||||
DefineEngineMethod(className, set##name, bool, (const char* shape), , assetText(name,assignment. first tries asset then flat file.))\
|
||||
{\
|
||||
return object->_set##name(StringTable->insert(shape));\
|
||||
}
|
||||
|
||||
#define INIT_SHAPEASSET(name) \
|
||||
m##name##Name = StringTable->EmptyString(); \
|
||||
m##name##AssetId = StringTable->EmptyString(); \
|
||||
m##name##Asset = NULL; \
|
||||
m##name = NULL;
|
||||
}\
|
||||
bool is##name##Valid() {return (get##name() != StringTable->EmptyString() && m##name##Asset->getStatus() == AssetBase::Ok); }
|
||||
|
||||
#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
|
|
@ -377,46 +358,6 @@ DefineEngineMethod(className, set##name, bool, (const char* shape), , assetText
|
|||
|
||||
#endif // SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
#define CLONE_SHAPEASSET(name) \
|
||||
m##name##Name = other.m##name##Name;\
|
||||
m##name##AssetId = other.m##name##AssetId;\
|
||||
m##name##Asset = other.m##name##Asset;\
|
||||
|
||||
#define PACKDATA_SHAPEASSET(name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset.getAssetId());\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
#define UNPACKDATA_SHAPEASSET(name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = stream->readSTString();\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
|
||||
#define PACK_SHAPEASSET(netconn, name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
NetStringHandle assetIdStr = m##name##Asset.getAssetId();\
|
||||
netconn->packNetStringHandleU(stream, assetIdStr);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
#define UNPACK_SHAPEASSET(netconn, name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = StringTable->insert(netconn->unpackNetStringHandleU(stream).getString());\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Arrayed Asset Macros
|
||||
|
|
@ -495,7 +436,7 @@ public: \
|
|||
Con::errorf("%s(%s)::_set%s(%i) - shape asset failure \"%s\" due to [%s]", macroText(className), getName(), macroText(name), index, _in, ShapeAsset::getAssetErrstrn(m##name##Asset[index]->getStatus()).c_str());\
|
||||
return false; \
|
||||
}\
|
||||
else if (bool(m##name[index]) == NULL)\
|
||||
else if (!m##name[index])\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s(%i) - Couldn't load shape \"%s\"", macroText(className), getName(), macroText(name), index, _in);\
|
||||
return false; \
|
||||
|
|
@ -519,59 +460,8 @@ public: \
|
|||
if(index >= sm##name##Count || index < 0)\
|
||||
return ResourceManager::get().load( "" );\
|
||||
return m##name[index];\
|
||||
}
|
||||
|
||||
#define DECLARE_SHAPEASSET_ARRAY_SETGET(className, name)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
if (!index) return false;\
|
||||
U32 idx = dAtoi(index);\
|
||||
if (idx >= sm##name##Count)\
|
||||
return false;\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data), idx);\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DECLARE_SHAPEASSET_ARRAY_NET_SETGET(className, name, bitmask)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
if (!index) return false;\
|
||||
U32 idx = dAtoi(index);\
|
||||
if (idx >= sm##name##Count)\
|
||||
return false;\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data), idx);\
|
||||
if(ret)\
|
||||
object->setMaskBits(bitmask);\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DEF_SHAPEASSET_ARRAY_BINDS(className,name)\
|
||||
DefineEngineMethod(className, get##name, String, (S32 index), , "get name")\
|
||||
{\
|
||||
return object->get##name(index); \
|
||||
}\
|
||||
DefineEngineMethod(className, get##name##Asset, String, (S32 index), , assetText(name, asset reference))\
|
||||
{\
|
||||
if(index >= className::sm##name##Count || index < 0)\
|
||||
return "";\
|
||||
return object->m##name##AssetId[index]; \
|
||||
}\
|
||||
DefineEngineMethod(className, set##name, bool, (const char* shape, S32 index), , assetText(name,assignment. first tries asset then flat file.))\
|
||||
{\
|
||||
return object->_set##name(StringTable->insert(shape), index);\
|
||||
}
|
||||
|
||||
#define INIT_SHAPEASSET_ARRAY(name, index) \
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString(); \
|
||||
m##name##AssetId[index] = StringTable->EmptyString(); \
|
||||
m##name##Asset[index] = NULL; \
|
||||
m##name[index] = NULL;\
|
||||
}
|
||||
}\
|
||||
bool is##name##Valid(const U32& id) {return (get##name(id) != StringTable->EmptyString() && m##name##Asset[id]->getStatus() == AssetBase::Ok); }
|
||||
|
||||
#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
|
|
@ -587,48 +477,6 @@ DefineEngineMethod(className, set##name, bool, (const char* shape, S32 index),
|
|||
|
||||
#endif // SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
#define CLONE_SHAPEASSET_ARRAY(name, index) \
|
||||
{\
|
||||
m##name##Name[index] = other.m##name##Name[index];\
|
||||
m##name##AssetId[index] = other.m##name##AssetId[index];\
|
||||
m##name##Asset[index] = other.m##name##Asset[index];\
|
||||
}
|
||||
|
||||
#define PACKDATA_SHAPEASSET_ARRAY(name, index)\
|
||||
if (stream->writeFlag(m##name##Asset[index].notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset[index].getAssetId());\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name[index]);
|
||||
|
||||
#define UNPACKDATA_SHAPEASSET_ARRAY(name, index)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId[index] = stream->readSTString();\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name[index] = stream->readSTString();
|
||||
|
||||
#define PACK_SHAPEASSET_ARRAY(netconn, name, index)\
|
||||
if (stream->writeFlag(m##name##Asset[index].notNull()))\
|
||||
{\
|
||||
NetStringHandle assetIdStr = m##name##Asset[index].getAssetId();\
|
||||
netconn->packNetStringHandleU(stream, assetIdStr);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name[index]);
|
||||
|
||||
#define UNPACK_SHAPEASSET_ARRAY(netconn, name, index)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId[index] = StringTable->insert(netconn->unpackNetStringHandleU(stream).getString());\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name[index] = stream->readSTString();
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@
|
|||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
#ifndef _SFXSOURCE_H_
|
||||
#include "sfx/sfxSource.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
#include "sfx/sfxTypes.h"
|
||||
|
|
@ -103,6 +107,7 @@ ConsoleSetType(TypeSoundAssetId)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
SoundAsset::SoundAsset()
|
||||
: AssetBase()
|
||||
{
|
||||
mSoundFile = StringTable->EmptyString();
|
||||
mSoundPath = StringTable->EmptyString();
|
||||
|
|
@ -159,7 +164,7 @@ void SoundAsset::initPersistFields()
|
|||
addField("maxDistance", TypeF32, Offset(mProfileDesc.mMaxDistance, SoundAsset), "Max distance for sound.");
|
||||
addField("coneInsideAngle", TypeS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset), "Cone inside angle.");
|
||||
addField("coneOutsideAngle", TypeS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset), "Cone outside angle.");
|
||||
addField("coneOutsideVolume", TypeS32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), "Cone outside volume.");
|
||||
addField("coneOutsideVolume", TypeF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), "Cone outside volume.");
|
||||
addField("rolloffFactor", TypeF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset), "Rolloff factor.");
|
||||
addField("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset), "Randomization to the spacial position of the sound.");
|
||||
addField("sourceGroup", TypeSFXSourceName, Offset(mProfileDesc.mSourceGroup, SoundAsset), "Group that sources playing with this description should be put into.");
|
||||
|
|
@ -181,13 +186,7 @@ void SoundAsset::initializeAsset(void)
|
|||
if (mSoundFile == StringTable->EmptyString())
|
||||
return;
|
||||
|
||||
//ResourceManager::get().getChangedSignal.notify(this, &SoundAsset::_onResourceChanged);
|
||||
|
||||
//Ensure our path is expando'd if it isn't already
|
||||
mSoundPath = getOwned() ? expandAssetFilePath(mSoundFile) : mSoundPath;
|
||||
|
||||
mSoundPath = expandAssetFilePath(mSoundPath);
|
||||
|
||||
loadSound();
|
||||
}
|
||||
|
||||
|
|
@ -208,7 +207,6 @@ void SoundAsset::onAssetRefresh(void)
|
|||
|
||||
//Update
|
||||
mSoundPath = getOwned() ? expandAssetFilePath(mSoundFile) : mSoundPath;
|
||||
|
||||
loadSound();
|
||||
}
|
||||
|
||||
|
|
@ -220,12 +218,15 @@ bool SoundAsset::loadSound()
|
|||
{
|
||||
Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile);
|
||||
mLoadedState = BadFileReference;
|
||||
mSFXProfile.setDescription(NULL);
|
||||
mSFXProfile.setSoundFileName(StringTable->insert(StringTable->EmptyString()));
|
||||
mSFXProfile.setPreload(false);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{// = new SFXProfile(mProfileDesc, mSoundFile, mPreload);
|
||||
mSFXProfile.setDescription(&mProfileDesc);
|
||||
mSFXProfile.setSoundFileName(mSoundFile);
|
||||
mSFXProfile.setSoundFileName(mSoundPath);
|
||||
mSFXProfile.setPreload(mPreload);
|
||||
}
|
||||
|
||||
|
|
@ -254,11 +255,106 @@ void SoundAsset::setSoundFile(const char* pSoundFile)
|
|||
refreshAsset();
|
||||
}
|
||||
|
||||
StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName)
|
||||
{
|
||||
if (fileName == StringTable->EmptyString())
|
||||
return StringTable->EmptyString();
|
||||
|
||||
StringTableEntry soundAssetId = StringTable->EmptyString();
|
||||
|
||||
AssetQuery query;
|
||||
U32 foundCount = AssetDatabase.findAssetType(&query, "SoundAsset");
|
||||
if (foundCount != 0)
|
||||
{
|
||||
for (U32 i = 0; i < foundCount; i++)
|
||||
{
|
||||
SoundAsset* soundAsset = AssetDatabase.acquireAsset<SoundAsset>(query.mAssetList[i]);
|
||||
if (soundAsset && soundAsset->getSoundPath() == fileName)
|
||||
{
|
||||
soundAssetId = soundAsset->getAssetId();
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]);
|
||||
break;
|
||||
}
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return soundAssetId;
|
||||
}
|
||||
|
||||
U32 SoundAsset::getAssetById(StringTableEntry assetId, AssetPtr<SoundAsset>* soundAsset)
|
||||
{
|
||||
(*soundAsset) = assetId;
|
||||
|
||||
if (soundAsset->notNull())
|
||||
{
|
||||
return (*soundAsset)->mLoadedState;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Well that's bad, loading the fallback failed.
|
||||
Con::warnf("SoundAsset::getAssetById - Finding of asset with id %s failed with no fallback asset", assetId);
|
||||
return AssetErrCode::Failed;
|
||||
}
|
||||
}
|
||||
|
||||
U32 SoundAsset::getAssetByFileName(StringTableEntry fileName, AssetPtr<SoundAsset>* soundAsset)
|
||||
{
|
||||
AssetQuery query;
|
||||
U32 foundAssetcount = AssetDatabase.findAssetType(&query, "SoundAsset");
|
||||
if (foundAssetcount == 0)
|
||||
{
|
||||
//Well that's bad, loading the fallback failed.
|
||||
Con::warnf("MaterialAsset::getAssetByMaterialName - Finding of asset associated with filename %s failed with no fallback asset", fileName);
|
||||
return AssetErrCode::Failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 i = 0; i < foundAssetcount; i++)
|
||||
{
|
||||
SoundAsset* tSoundAsset = AssetDatabase.acquireAsset<SoundAsset>(query.mAssetList[i]);
|
||||
if (tSoundAsset && tSoundAsset->getSoundPath() == fileName)
|
||||
{
|
||||
soundAsset->setAssetId(query.mAssetList[i]);
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]);
|
||||
return (*soundAsset)->mLoadedState;
|
||||
}
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]); //cleanup if that's not the one we needed
|
||||
}
|
||||
}
|
||||
|
||||
//No good match
|
||||
return AssetErrCode::Failed;
|
||||
}
|
||||
|
||||
DefineEngineMethod(SoundAsset, getSoundPath, const char*, (), , "")
|
||||
{
|
||||
return object->getSoundPath();
|
||||
}
|
||||
|
||||
DefineEngineMethod(SoundAsset, playSound, S32, (Point3F position), (Point3F::Zero),
|
||||
"Plays the sound for this asset.\n"
|
||||
"@return (sound plays).\n")
|
||||
{
|
||||
if (object->getSfxProfile())
|
||||
{
|
||||
MatrixF transform;
|
||||
transform.setPosition(position);
|
||||
SFXSource* source = SFX->playOnce(object->getSfxProfile(), &transform, NULL, -1);
|
||||
return source->getId();
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
DefineEngineStaticMethod(SoundAsset, getAssetIdByFilename, const char*, (const char* filePath), (""),
|
||||
"Queries the Asset Database to see if any asset exists that is associated with the provided file path.\n"
|
||||
"@return The AssetId of the associated asset, if any.")
|
||||
{
|
||||
return SoundAsset::getAssetIdByFileName(StringTable->insert(filePath));
|
||||
}
|
||||
#endif
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeSoundAssetPtr);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeSoundAssetPtr,
|
||||
|
|
@ -276,12 +372,63 @@ void GuiInspectorTypeSoundAssetPtr::consoleInit()
|
|||
|
||||
GuiControl * GuiInspectorTypeSoundAssetPtr::constructEditControl()
|
||||
{
|
||||
return nullptr;
|
||||
// Create base filename edit controls
|
||||
GuiControl* retCtrl = Parent::constructEditControl();
|
||||
if (retCtrl == NULL)
|
||||
return retCtrl;
|
||||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"SoundAsset\", \"AssetBrowser.changeAsset\", %s, \"\");",
|
||||
getIdString());
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
|
||||
|
||||
// Create "Open in Editor" button
|
||||
mEditButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.editAsset(%d.getText());", retCtrl->getId());
|
||||
mEditButton->setField("Command", szBuffer);
|
||||
|
||||
char bitmapName[512] = "ToolsModule:SFXEmitter_image";
|
||||
mEditButton->setBitmap(StringTable->insert(bitmapName));
|
||||
|
||||
mEditButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mEditButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mEditButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
mEditButton->setDataField(StringTable->insert("tooltip"), NULL, "Test play this sound");
|
||||
|
||||
mEditButton->registerObject();
|
||||
addObject(mEditButton);
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeSoundAssetPtr::updateRects()
|
||||
{
|
||||
return false;
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider(dividerPos, dividerMargin);
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
|
||||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
|
||||
|
||||
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
if (mBrowseButton != NULL)
|
||||
{
|
||||
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
|
||||
}
|
||||
|
||||
if (mEditButton != NULL)
|
||||
{
|
||||
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mEditButton->resize(shapeEdRect.point, shapeEdRect.extent);
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeSoundAssetId);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
#include "sfx/sfxProfile.h"
|
||||
#endif // !_SFXPROFILE_H_
|
||||
|
||||
#include "assetMacroHelpers.h"
|
||||
class SFXResource;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -122,6 +123,9 @@ public:
|
|||
bool isLoop() { return mProfileDesc.mIsLooping; }
|
||||
bool is3D() { return mProfileDesc.mIs3D; }
|
||||
|
||||
static StringTableEntry getAssetIdByFileName(StringTableEntry fileName);
|
||||
static U32 getAssetById(StringTableEntry assetId, AssetPtr<SoundAsset>* materialAsset);
|
||||
static U32 getAssetByFileName(StringTableEntry fileName, AssetPtr<SoundAsset>* matAsset);
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void);
|
||||
|
|
@ -143,7 +147,7 @@ class GuiInspectorTypeSoundAssetPtr : public GuiInspectorTypeFileName
|
|||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl* mSoundButton;
|
||||
GuiBitmapButtonCtrl* mEditButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeSoundAssetPtr);
|
||||
static void consoleInit();
|
||||
|
|
@ -168,14 +172,14 @@ public:
|
|||
/// Declares a sound asset
|
||||
/// This establishes the assetId, asset and legacy filepath fields, along with supplemental getter and setter functions
|
||||
/// </Summary>
|
||||
#define DECLARE_SOUNDASSET(className, name, profile) public: \
|
||||
#define DECLARE_SOUNDASSET(className, name) public: \
|
||||
Resource<SFXResource> m##name;\
|
||||
StringTableEntry m##name##Name; \
|
||||
StringTableEntry m##name##AssetId;\
|
||||
AssetPtr<SoundAsset> m##name##Asset = NULL;\
|
||||
SFXProfile* m##name##Profile = &profile;\
|
||||
SFXProfile* m##name##Profile = NULL;\
|
||||
public: \
|
||||
const StringTableEntry get##name##File() const { return m##name##Name); }\
|
||||
const StringTableEntry get##name##File() const { return m##name##Name; }\
|
||||
void set##name##File(const FileName &_in) { m##name##Name = StringTable->insert(_in.c_str());}\
|
||||
const AssetPtr<SoundAsset> & get##name##Asset() const { return m##name##Asset; }\
|
||||
void set##name##Asset(const AssetPtr<SoundAsset> &_in) { m##name##Asset = _in;}\
|
||||
|
|
@ -206,7 +210,7 @@ public: \
|
|||
}\
|
||||
else\
|
||||
{\
|
||||
StringTableEntry assetId = SoundAsset::getAssetIdByFilename(_in);\
|
||||
StringTableEntry assetId = SoundAsset::getAssetIdByFileName(_in);\
|
||||
if (assetId != StringTable->EmptyString())\
|
||||
{\
|
||||
m##name##AssetId = assetId;\
|
||||
|
|
@ -231,13 +235,17 @@ public: \
|
|||
{\
|
||||
m##name = NULL;\
|
||||
}\
|
||||
if(get##name() == StringTable->EmptyString())\
|
||||
return true;\
|
||||
\
|
||||
if (m##name##Asset.notNull() && m##name##Asset->getStatus() != ShapeAsset::Ok)\
|
||||
if(get##name() == StringTable->EmptyString())\
|
||||
return true;\
|
||||
if (m##name##Asset.notNull() && m##name##Asset->getStatus() != SoundAsset::Ok)\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s() - sound asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name), _in, ShapeAsset::getAssetErrstrn(m##name##Asset->getStatus()).c_str());\
|
||||
Con::errorf("%s(%s)::_set%s() - sound asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name), _in, SoundAsset::getAssetErrstrn(m##name##Asset->getStatus()).c_str());\
|
||||
return false; \
|
||||
}\
|
||||
else if (m##name)\
|
||||
else if (!m##name)\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s() - Couldn't load sound \"%s\"", macroText(className), getName(), macroText(name), _in);\
|
||||
return false;\
|
||||
|
|
@ -259,47 +267,14 @@ public: \
|
|||
Resource<SFXResource> get##name##Resource() \
|
||||
{\
|
||||
return m##name;\
|
||||
}
|
||||
|
||||
#define DECLARE_SOUNDASSET_SETGET(className, name)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
}\
|
||||
SFXProfile* get##name##Profile()\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DECLARE_SOUNDASSET_NET_SETGET(className, name, bitmask)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
if(ret)\
|
||||
object->setMaskBits(bitmask);\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
#define DEF_SOUNDASSET_BINDS(className,name)\
|
||||
DefineEngineMethod(className, get##name, String, (), , "get name")\
|
||||
{\
|
||||
return object->get##name(); \
|
||||
}\
|
||||
DefineEngineMethod(className, get##name##Asset, String, (), , assetText(name, asset reference))\
|
||||
{\
|
||||
return object->m##name##AssetId; \
|
||||
}\
|
||||
DefineEngineMethod(className, set##name, bool, (const char* shape), , assetText(name,assignment. first tries asset then flat file.))\
|
||||
{\
|
||||
return object->_set##name(StringTable->insert(shape));\
|
||||
}
|
||||
|
||||
#define INIT_SOUNDASSET(name) \
|
||||
m##name##Name = StringTable->EmptyString(); \
|
||||
m##name##AssetId = StringTable->EmptyString(); \
|
||||
m##name##Asset = NULL; \
|
||||
m##name = NULL;\
|
||||
if (get##name() != StringTable->EmptyString() && m##name##Asset.notNull())\
|
||||
return m##name##Asset->getSfxProfile();\
|
||||
return NULL;\
|
||||
}\
|
||||
bool is##name##Valid() { return (get##name() != StringTable->EmptyString() && m##name##Asset->getStatus() == AssetBase::Ok); }
|
||||
|
||||
#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
|
|
@ -315,46 +290,164 @@ DefineEngineMethod(className, set##name, bool, (const char* shape), , assetText
|
|||
|
||||
#endif // TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
#define CLONE_SOUNDASSET(name) \
|
||||
m##name##Name = other.m##name##Name;\
|
||||
m##name##AssetId = other.m##name##AssetId;\
|
||||
m##name##Asset = other.m##name##Asset;\
|
||||
#pragma endregion
|
||||
|
||||
#define PACKDATA_SOUNDASSET(name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
#pragma region Arrayed Asset Macros
|
||||
|
||||
#define DECLARE_SOUNDASSET_ARRAY(className,name,max) public: \
|
||||
static const U32 sm##name##Count = max;\
|
||||
Resource<SFXResource> m##name[max];\
|
||||
StringTableEntry m##name##Name[max]; \
|
||||
StringTableEntry m##name##AssetId[max];\
|
||||
AssetPtr<SoundAsset> m##name##Asset[max];\
|
||||
SFXProfile* m##name##Profile[max];\
|
||||
public: \
|
||||
const StringTableEntry get##name##File(const U32& index) const { return m##name##Name[index]; }\
|
||||
void set##name##File(const FileName &_in, const U32& index) { m##name##Name[index] = StringTable->insert(_in.c_str());}\
|
||||
const AssetPtr<SoundAsset> & get##name##Asset(const U32& index) const { return m##name##Asset[index]; }\
|
||||
void set##name##Asset(const AssetPtr<SoundAsset> &_in, const U32& index) { m##name##Asset[index] = _in;}\
|
||||
\
|
||||
bool _set##name(StringTableEntry _in, const U32& index)\
|
||||
{\
|
||||
stream->writeString(m##name##Asset.getAssetId());\
|
||||
if(m##name##AssetId[index] != _in || m##name##Name[index] != _in)\
|
||||
{\
|
||||
if(index >= sm##name##Count || index < 0) \
|
||||
return false;\
|
||||
if (_in == NULL || _in == StringTable->EmptyString())\
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString();\
|
||||
m##name##AssetId[index] = StringTable->EmptyString();\
|
||||
m##name##Asset[index] = NULL;\
|
||||
m##name[index] = NULL;\
|
||||
return true;\
|
||||
}\
|
||||
else if(_in[0] == '$' || _in[0] == '#')\
|
||||
{\
|
||||
m##name##Name[index] = _in;\
|
||||
m##name##AssetId[index] = StringTable->EmptyString();\
|
||||
m##name##Asset[index] = NULL;\
|
||||
m##name[index] = NULL;\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
if (AssetDatabase.isDeclaredAsset(_in))\
|
||||
{\
|
||||
m##name##AssetId[index] = _in;\
|
||||
\
|
||||
U32 assetState = SoundAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]);\
|
||||
\
|
||||
if (SoundAsset::Ok == assetState)\
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString();\
|
||||
}\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
StringTableEntry assetId = SoundAsset::getAssetIdByFileName(_in);\
|
||||
if (assetId != StringTable->EmptyString())\
|
||||
{\
|
||||
m##name##AssetId[index] = assetId;\
|
||||
if(SoundAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]) == SoundAsset::Ok)\
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString();\
|
||||
}\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
m##name##Name[index] = _in;\
|
||||
m##name##AssetId[index] = StringTable->EmptyString();\
|
||||
m##name##Asset[index] = NULL;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
if (get##name(index) != StringTable->EmptyString() && m##name##Asset[index].notNull())\
|
||||
{\
|
||||
m##name[index] = m##name##Asset[index]->getSoundResource();\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
m##name[index] = NULL;\
|
||||
}\
|
||||
if(get##name(index) == StringTable->EmptyString())\
|
||||
return true;\
|
||||
\
|
||||
if (m##name##Asset[index].notNull() && m##name##Asset[index]->getStatus() != SoundAsset::Ok)\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s(%i) - sound asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name),index, _in, SoundAsset::getAssetErrstrn(m##name##Asset[index]->getStatus()).c_str());\
|
||||
return false; \
|
||||
}\
|
||||
else if (!m##name[index])\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s(%i) - Couldn't load sound \"%s\"", macroText(className), getName(), macroText(name),index, _in);\
|
||||
return false;\
|
||||
}\
|
||||
return true;\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
#define UNPACKDATA_SOUNDASSET(name)\
|
||||
if (stream->readFlag())\
|
||||
\
|
||||
const StringTableEntry get##name(const U32& index) const\
|
||||
{\
|
||||
m##name##AssetId = stream->readSTString();\
|
||||
_set##name(m##name##AssetId);\
|
||||
if (m##name##Asset[index] && (m##name##Asset[index]->getSoundPath() != StringTable->EmptyString()))\
|
||||
return m##name##Asset[index]->getSoundPath();\
|
||||
else if (m##name##AssetId[index] != StringTable->EmptyString())\
|
||||
return m##name##AssetId[index];\
|
||||
else if (m##name##Name[index] != StringTable->EmptyString())\
|
||||
return StringTable->insert(m##name##Name[index]);\
|
||||
else\
|
||||
return StringTable->EmptyString();\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
|
||||
#define PACK_SOUNDASSET(netconn, name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
Resource<SFXResource> get##name##Resource(const U32& id) \
|
||||
{\
|
||||
NetStringHandle assetIdStr = m##name##Asset.getAssetId();\
|
||||
netconn->packNetStringHandleU(stream, assetIdStr);\
|
||||
if(id >= sm##name##Count || id < 0)\
|
||||
return ResourceManager::get().load( "" );\
|
||||
return m##name[id];\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
#define UNPACK_SOUNDASSET(netconn, name)\
|
||||
if (stream->readFlag())\
|
||||
SFXProfile* get##name##Profile(const U32& id)\
|
||||
{\
|
||||
m##name##AssetId = StringTable->insert(netconn->unpackNetStringHandleU(stream).getString());\
|
||||
_set##name(m##name##AssetId);\
|
||||
if (get##name(id) != StringTable->EmptyString() && m##name##Asset[id].notNull())\
|
||||
return m##name##Asset[id]->getSfxProfile();\
|
||||
return NULL;\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
bool is##name##Valid(const U32& id) {return (get##name(id) != StringTable->EmptyString() && m##name##Asset[id]->getStatus() == AssetBase::Ok); }
|
||||
|
||||
|
||||
#ifdef TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
#define INITPERSISTFIELD_IMAGEASSET_ARRAY(name, arraySize, consoleClass, docs) \
|
||||
addProtectedField(#name, TypeSoundFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, docs)); \
|
||||
addProtectedField(assetText(name, Asset), TypeImageAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));
|
||||
|
||||
#else
|
||||
|
||||
#define INITPERSISTFIELD_SOUNDASSET_ARRAY(name, arraySize, consoleClass, docs) \
|
||||
addProtectedField(#name, TypeSoundFilename, Offset(m##name##Name, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, docs), AbstractClassRep::FIELD_HideInInspectors); \
|
||||
addProtectedField(assetText(name, Asset), TypeSoundAssetId, Offset(m##name##AssetId, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));
|
||||
|
||||
#endif
|
||||
|
||||
#define LOAD_SOUNDASSET_ARRAY(name, index)\
|
||||
if (m##name##AssetId[index] != StringTable->EmptyString())\
|
||||
{\
|
||||
S32 assetState = SoundAsset::getAssetById(m##name##AssetId[index], &m##name##Asset[index]);\
|
||||
if (assetState == SoundAsset::Ok )\
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString();\
|
||||
}\
|
||||
else Con::warnf("Warning: %s::LOAD_SOUNDASSET_ARRAY(%s[%i])-%s", mClassName, m##name##AssetId[index], index, ImageAsset::getAssetErrstrn(assetState).c_str());\
|
||||
}
|
||||
|
||||
#define assetEnumNameConcat(x,suff)(new std::string( x + std::string(#suff)))->c_str()
|
||||
|
||||
#define INITPERSISTFIELD_SOUNDASSET_ENUMED(name, enumType, maxValue, consoleClass, docs) \
|
||||
for (U32 i = 0; i < maxValue; i++)\
|
||||
{\
|
||||
const enumType itter = static_cast<enumType>(i);\
|
||||
const char* enumString = castConsoleTypeToString(static_cast<enumType>(itter));\
|
||||
if (enumString && enumString[0])\
|
||||
{\
|
||||
addField(assetEnumNameConcat(enumString, File), TypeSoundFilename, Offset(m##name##Name[0], consoleClass) + sizeof(m##name##Name[0])*i, assetText(name, docs), AbstractClassRep::FIELD_HideInInspectors); \
|
||||
addField(assetEnumNameConcat(enumString, Asset), TypeSoundAssetId, Offset(m##name##AssetId[0], consoleClass) + sizeof(m##name##AssetId[0])*i, assetText(name, asset reference.));\
|
||||
}\
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ bool TerrainAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr<Terrai
|
|||
{
|
||||
//Didn't find any assets
|
||||
//If possible, see if we can run an in-place import and the get the asset from that
|
||||
#if TORQUE_DEBUG
|
||||
#ifdef TORQUE_DEBUG
|
||||
Con::warnf("TerrainAsset::getAssetByFilename - Attempted to in-place import a terrainFile(%s) that had no associated asset", fileName);
|
||||
#endif
|
||||
|
||||
|
|
@ -465,11 +465,9 @@ GuiControl* GuiInspectorTypeTerrainAssetPtr::constructEditControl()
|
|||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
|
||||
mInspector->getInspectObject()->getIdString(), mCaption);
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
const char* id = mInspector->getInspectObject()->getIdString();
|
||||
|
||||
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@
|
|||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/assets/assetImporter.h"
|
||||
|
||||
StringTableEntry TerrainMaterialAsset::smNoTerrainMaterialAssetFallback = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(TerrainMaterialAsset);
|
||||
|
|
@ -85,6 +89,35 @@ ConsoleSetType(TypeTerrainMaterialAssetPtr)
|
|||
Con::warnf("(TypeTerrainMaterialAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
|
||||
ConsoleType(assetIdString, TypeTerrainMaterialAssetId, const char*, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
ConsoleGetType(TypeTerrainMaterialAssetId)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return *((const char**)(dptr));
|
||||
}
|
||||
|
||||
ConsoleSetType(TypeTerrainMaterialAssetId)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset Id.
|
||||
StringTableEntry* assetId = (StringTableEntry*)(dptr);
|
||||
|
||||
// Update asset value.
|
||||
*assetId = StringTable->insert(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeTerrainMaterialAssetId) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TerrainMaterialAsset::TerrainMaterialAsset()
|
||||
|
|
@ -92,24 +125,41 @@ TerrainMaterialAsset::TerrainMaterialAsset()
|
|||
mScriptFile = StringTable->EmptyString();
|
||||
mScriptPath = StringTable->EmptyString();
|
||||
mMatDefinitionName = StringTable->EmptyString();
|
||||
mMaterialDefinition = nullptr;
|
||||
mFXMaterialDefinition = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TerrainMaterialAsset::~TerrainMaterialAsset()
|
||||
{
|
||||
if (mMaterialDefinition)
|
||||
mMaterialDefinition->safeDeleteObject();
|
||||
if (mFXMaterialDefinition)
|
||||
mFXMaterialDefinition->safeDeleteObject();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void TerrainMaterialAsset::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
Con::addVariable("$Core::NoTerrainMaterialAssetFallback", TypeString, &smNoTerrainMaterialAssetFallback,
|
||||
"The assetId of the material to display when the requested material asset is missing.\n"
|
||||
"@ingroup GFX\n");
|
||||
|
||||
smNoTerrainMaterialAssetFallback = StringTable->insert(Con::getVariable("$Core::NoTerrainMaterialAssetFallback"));
|
||||
}
|
||||
|
||||
void TerrainMaterialAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
//addField("shaderGraph", TypeRealString, Offset(mShaderGraphFile, TerrainMaterialAsset), "");
|
||||
addProtectedField("scriptFile", TypeAssetLooseFilePath, Offset(mScriptFile, TerrainMaterialAsset),
|
||||
&setScriptFile, &getScriptFile, "Path to the file containing the material definition.");
|
||||
//addProtectedField("scriptFile", TypeAssetLooseFilePath, Offset(mScriptFile, TerrainMaterialAsset),
|
||||
// &setScriptFile, &getScriptFile, "Path to the file containing the material definition.");
|
||||
addField("scriptFile", TypeAssetLooseFilePath, Offset(mScriptFile, TerrainMaterialAsset), "");
|
||||
|
||||
addField("materialDefinitionName", TypeString, Offset(mMatDefinitionName, TerrainMaterialAsset), "Name of the material definition this asset is for.");
|
||||
}
|
||||
|
|
@ -121,28 +171,66 @@ void TerrainMaterialAsset::initializeAsset()
|
|||
|
||||
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
Con::executeFile(mScriptPath, false, false);
|
||||
if (mMatDefinitionName == StringTable->EmptyString())
|
||||
{
|
||||
mLoadedState = Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (size() != 0 && mScriptPath == StringTable->EmptyString())
|
||||
{
|
||||
mLoadedState = EmbeddedDefinition;
|
||||
}
|
||||
else if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
{
|
||||
if (!Sim::findObject(mMatDefinitionName))
|
||||
{
|
||||
if (Con::executeFile(mScriptPath, false, false))
|
||||
{
|
||||
mLoadedState = ScriptLoaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLoadedState = Failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLoadedState = DefinitionAlreadyExists;
|
||||
}
|
||||
}
|
||||
|
||||
loadMaterial();
|
||||
}
|
||||
|
||||
void TerrainMaterialAsset::onAssetRefresh()
|
||||
{
|
||||
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
|
||||
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
Con::executeFile(mScriptPath, false, false);
|
||||
|
||||
if (mMatDefinitionName != StringTable->EmptyString())
|
||||
if (mMatDefinitionName == StringTable->EmptyString())
|
||||
{
|
||||
TerrainMaterial* matDef;
|
||||
if (!Sim::findObject(mMatDefinitionName, matDef))
|
||||
{
|
||||
Con::errorf("TerrainMaterialAsset: Unable to find the Material %s", mMatDefinitionName);
|
||||
mLoadedState = Failed;
|
||||
return;
|
||||
}
|
||||
|
||||
//matDef->reload();
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
{
|
||||
//Since we're refreshing, we can assume that the file we're executing WILL have an existing definition.
|
||||
//But that definition, whatever it is, is the 'correct' one, so we enable the Replace Existing behavior
|
||||
//when the engine encounters a named object conflict.
|
||||
String redefineBehaviorPrev = Con::getVariable("$Con::redefineBehavior");
|
||||
Con::setVariable("$Con::redefineBehavior", "replaceExisting");
|
||||
|
||||
if (Con::executeFile(mScriptPath, false, false))
|
||||
mLoadedState = ScriptLoaded;
|
||||
else
|
||||
mLoadedState = Failed;
|
||||
|
||||
//And now that we've executed, switch back to the prior behavior
|
||||
Con::setVariable("$Con::redefineBehavior", redefineBehaviorPrev.c_str());
|
||||
}
|
||||
|
||||
loadMaterial();
|
||||
}
|
||||
|
||||
void TerrainMaterialAsset::setScriptFile(const char* pScriptFile)
|
||||
|
|
@ -152,10 +240,6 @@ void TerrainMaterialAsset::setScriptFile(const char* pScriptFile)
|
|||
|
||||
pScriptFile = StringTable->insert(pScriptFile, true);
|
||||
|
||||
// Ignore no change,
|
||||
if (pScriptFile == mScriptFile)
|
||||
return;
|
||||
|
||||
// Update.
|
||||
mScriptFile = getOwned() ? expandAssetFilePath(pScriptFile) : pScriptFile;
|
||||
|
||||
|
|
@ -165,41 +249,190 @@ void TerrainMaterialAsset::setScriptFile(const char* pScriptFile)
|
|||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void TerrainMaterialAsset::loadMaterial()
|
||||
{
|
||||
if (mMaterialDefinition)
|
||||
mMaterialDefinition->safeDeleteObject();
|
||||
if (mFXMaterialDefinition)
|
||||
mFXMaterialDefinition->safeDeleteObject();
|
||||
|
||||
if (mLoadedState == EmbeddedDefinition)
|
||||
{
|
||||
if (size() != 0)
|
||||
{
|
||||
for (U32 i = 0; i < size(); i++)
|
||||
{
|
||||
TerrainMaterial* terrMat = dynamic_cast<TerrainMaterial*>(getObject(i));
|
||||
if (terrMat)
|
||||
{
|
||||
mMaterialDefinition = terrMat;
|
||||
mLoadedState = Ok;
|
||||
mMaterialDefinition->setInternalName(getAssetId());
|
||||
continue;
|
||||
}
|
||||
|
||||
//Otherwise, check if it's our FX material
|
||||
Material* fxMat = dynamic_cast<Material*>(getObject(i));
|
||||
if (fxMat)
|
||||
{
|
||||
mFXMaterialDefinition = fxMat;
|
||||
//mMaterialDefinition->setInternalName(getAssetId());
|
||||
mFXMaterialDefinition->reload();
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(mLoadedState == Ok)
|
||||
return;
|
||||
}
|
||||
else if ((mLoadedState == ScriptLoaded || mLoadedState == DefinitionAlreadyExists) && mMatDefinitionName != StringTable->EmptyString())
|
||||
{
|
||||
TerrainMaterial* matDef;
|
||||
if (!Sim::findObject(mMatDefinitionName, matDef))
|
||||
{
|
||||
Con::errorf("TerrainMaterialAsset: Unable to find the Material %s", mMatDefinitionName);
|
||||
mLoadedState = BadFileReference;
|
||||
return;
|
||||
}
|
||||
|
||||
mMaterialDefinition = matDef;
|
||||
|
||||
mLoadedState = Ok;
|
||||
mMaterialDefinition->setInternalName(getAssetId());
|
||||
return;
|
||||
}
|
||||
|
||||
mLoadedState = Failed;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void TerrainMaterialAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
StringTableEntry TerrainMaterialAsset::getAssetIdByMaterialName(StringTableEntry matName)
|
||||
//------------------------------------------------------------------------------
|
||||
U32 TerrainMaterialAsset::getAssetByMaterialName(StringTableEntry matName, AssetPtr<TerrainMaterialAsset>* matAsset)
|
||||
{
|
||||
StringTableEntry materialAssetId = StringTable->EmptyString();
|
||||
|
||||
AssetQuery* query = new AssetQuery();
|
||||
U32 foundCount = AssetDatabase.findAssetType(query, "TerrainMaterialAsset");
|
||||
if (foundCount == 0)
|
||||
AssetQuery query;
|
||||
U32 foundAssetcount = AssetDatabase.findAssetType(&query, "TerrainMaterialAsset");
|
||||
if (foundAssetcount == 0)
|
||||
{
|
||||
//Didn't work, so have us fall back to a placeholder asset
|
||||
materialAssetId = StringTable->insert("Core_Rendering:noMaterial");
|
||||
matAsset->setAssetId(TerrainMaterialAsset::smNoTerrainMaterialAssetFallback);
|
||||
|
||||
if (matAsset->isNull())
|
||||
{
|
||||
//Well that's bad, loading the fallback failed.
|
||||
Con::warnf("TerrainMaterialAsset::getAssetByMaterialName - Finding of asset associated with material name %s failed with no fallback asset", matName);
|
||||
return AssetErrCode::Failed;
|
||||
}
|
||||
|
||||
//handle noshape not being loaded itself
|
||||
if ((*matAsset)->mLoadedState == BadFileReference)
|
||||
{
|
||||
Con::warnf("TerrainMaterialAsset::getAssetByMaterialName - Finding of associated with aterial name %s failed, and fallback asset reported error of Bad File Reference.", matName);
|
||||
return AssetErrCode::BadFileReference;
|
||||
}
|
||||
|
||||
Con::warnf("TerrainMaterialAsset::getAssetByMaterialName - Finding of associated with aterial name %s failed, utilizing fallback asset", matName);
|
||||
|
||||
(*matAsset)->mLoadedState = AssetErrCode::UsingFallback;
|
||||
return AssetErrCode::UsingFallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 i = 0; i < foundAssetcount; i++)
|
||||
{
|
||||
TerrainMaterialAsset* tMatAsset = AssetDatabase.acquireAsset<TerrainMaterialAsset>(query.mAssetList[i]);
|
||||
if (tMatAsset && tMatAsset->getMaterialDefinitionName() == matName)
|
||||
{
|
||||
matAsset->setAssetId(query.mAssetList[i]);
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]);
|
||||
return (*matAsset)->mLoadedState;
|
||||
}
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]); //cleanup if that's not the one we needed
|
||||
}
|
||||
}
|
||||
|
||||
//Somehow we failed to bind an asset, so just use the fallback and mark the failure
|
||||
matAsset->setAssetId(TerrainMaterialAsset::smNoTerrainMaterialAssetFallback);
|
||||
(*matAsset)->mLoadedState = AssetErrCode::UsingFallback;
|
||||
return AssetErrCode::UsingFallback;
|
||||
|
||||
}
|
||||
|
||||
StringTableEntry TerrainMaterialAsset::getAssetIdByMaterialName(StringTableEntry matName)
|
||||
{
|
||||
if (matName == StringTable->EmptyString())
|
||||
return StringTable->EmptyString();
|
||||
|
||||
StringTableEntry materialAssetId = TerrainMaterialAsset::smNoTerrainMaterialAssetFallback;
|
||||
|
||||
AssetQuery query;
|
||||
U32 foundCount = AssetDatabase.findAssetType(&query, "TerrainMaterialAsset");
|
||||
if (foundCount != 0)
|
||||
{
|
||||
for (U32 i = 0; i < foundCount; i++)
|
||||
{
|
||||
TerrainMaterialAsset* matAsset = AssetDatabase.acquireAsset<TerrainMaterialAsset>(query->mAssetList[i]);
|
||||
TerrainMaterialAsset* matAsset = AssetDatabase.acquireAsset<TerrainMaterialAsset>(query.mAssetList[i]);
|
||||
if (matAsset && matAsset->getMaterialDefinitionName() == matName)
|
||||
{
|
||||
materialAssetId = matAsset->getAssetId();
|
||||
AssetDatabase.releaseAsset(query->mAssetList[i]);
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]);
|
||||
break;
|
||||
}
|
||||
AssetDatabase.releaseAsset(query->mAssetList[i]);
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return materialAssetId;
|
||||
}
|
||||
|
||||
U32 TerrainMaterialAsset::getAssetById(StringTableEntry assetId, AssetPtr<TerrainMaterialAsset>* materialAsset)
|
||||
{
|
||||
(*materialAsset) = assetId;
|
||||
if (materialAsset->notNull())
|
||||
{
|
||||
return (*materialAsset)->mLoadedState;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Didn't work, so have us fall back to a placeholder asset
|
||||
materialAsset->setAssetId(TerrainMaterialAsset::smNoTerrainMaterialAssetFallback);
|
||||
if (materialAsset->isNull())
|
||||
{
|
||||
//Well that's bad, loading the fallback failed.
|
||||
Con::warnf("TerrainMaterialAsset::getAssetById - Finding of asset with id %s failed with no fallback asset", assetId);
|
||||
return AssetErrCode::Failed;
|
||||
}
|
||||
//handle noshape not being loaded itself
|
||||
if ((*materialAsset)->mLoadedState == BadFileReference)
|
||||
{
|
||||
Con::warnf("TerrainMaterialAsset::getAssetById - Finding of asset with id %s failed, and fallback asset reported error of Bad File Reference.", assetId);
|
||||
return AssetErrCode::BadFileReference;
|
||||
}
|
||||
Con::warnf("TerrainMaterialAsset::getAssetById - Finding of asset with id %s failed, utilizing fallback asset", assetId);
|
||||
(*materialAsset)->mLoadedState = AssetErrCode::UsingFallback;
|
||||
return AssetErrCode::UsingFallback;
|
||||
}
|
||||
}
|
||||
SimObjectPtr<TerrainMaterial> TerrainMaterialAsset::findMaterialDefinitionByAssetId(StringTableEntry assetId)
|
||||
{
|
||||
SimSet* terrainMatSet;
|
||||
if (!Sim::findObject("TerrainMaterialSet", terrainMatSet))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SimObjectPtr<TerrainMaterial> matDef = dynamic_cast<TerrainMaterial*>(terrainMatSet->findObjectByInternalName(assetId));
|
||||
return matDef;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
DefineEngineStaticMethod(TerrainMaterialAsset, getAssetIdByMaterialName, const char*, (const char* materialName), (""),
|
||||
"Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n"
|
||||
|
|
@ -207,6 +440,48 @@ DefineEngineStaticMethod(TerrainMaterialAsset, getAssetIdByMaterialName, const c
|
|||
{
|
||||
return TerrainMaterialAsset::getAssetIdByMaterialName(StringTable->insert(materialName));
|
||||
}
|
||||
|
||||
//MaterialAsset::findMaterialDefinitionByAssetId("Prototyping:Detail")
|
||||
DefineEngineStaticMethod(TerrainMaterialAsset, findMaterialDefinitionByAssetId, S32, (const char* assetId), (""),
|
||||
"Queries the MaterialSet to see if any MaterialDefinition exists that is associated to the provided assetId.\n"
|
||||
"@return The MaterialDefinition Id associated to the assetId, if any")
|
||||
{
|
||||
SimObjectPtr<TerrainMaterial> matDef = TerrainMaterialAsset::findMaterialDefinitionByAssetId(StringTable->insert(assetId));
|
||||
if (matDef.isNull())
|
||||
return SimObjectId(0);
|
||||
else
|
||||
return matDef->getId();
|
||||
}
|
||||
|
||||
|
||||
DefineEngineMethod(TerrainMaterialAsset, getScriptPath, const char*, (), ,
|
||||
"Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n"
|
||||
"@return The AssetId of the associated asset, if any.")
|
||||
{
|
||||
return object->getScriptPath();
|
||||
}
|
||||
|
||||
DefineEngineMethod(TerrainMaterialAsset, getMaterialDefinition, S32, (), ,
|
||||
"Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n"
|
||||
"@return The AssetId of the associated asset, if any.")
|
||||
{
|
||||
SimObjectPtr<TerrainMaterial> mat = object->getMaterialDefinition();
|
||||
if (mat.isValid())
|
||||
return mat->getId();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
DefineEngineMethod(TerrainMaterialAsset, getFXMaterialDefinition, S32, (), ,
|
||||
"Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n"
|
||||
"@return The AssetId of the associated asset, if any.")
|
||||
{
|
||||
SimObjectPtr<Material> mat = object->getFXMaterialDefinition();
|
||||
if (mat.isValid())
|
||||
return mat->getId();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeAssetId
|
||||
|
|
@ -230,68 +505,36 @@ void GuiInspectorTypeTerrainMaterialAssetPtr::consoleInit()
|
|||
GuiControl* GuiInspectorTypeTerrainMaterialAssetPtr::constructEditControl()
|
||||
{
|
||||
// Create base filename edit controls
|
||||
mUseHeightOverride = true;
|
||||
mHeightOverride = 100;
|
||||
|
||||
mMatEdContainer = new GuiControl();
|
||||
mMatEdContainer->registerObject();
|
||||
|
||||
addObject(mMatEdContainer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
mMatPreviewButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
const char* matAssetId = getData();
|
||||
|
||||
TerrainMaterialAsset* matAsset = AssetDatabase.acquireAsset< TerrainMaterialAsset>(matAssetId);
|
||||
|
||||
TerrainMaterial* materialDef = nullptr;
|
||||
|
||||
char bitmapName[512] = "ToolsModule:material_editor_n_image";
|
||||
|
||||
/*if (!Sim::findObject(matAsset->getMaterialDefinitionName(), materialDef))
|
||||
{
|
||||
Con::errorf("GuiInspectorTypeTerrainMaterialAssetPtr::constructEditControl() - unable to find material in asset");
|
||||
}
|
||||
else
|
||||
{
|
||||
mMatPreviewButton->setBitmap(materialDef->mDiffuseMapFilename[0]);
|
||||
}*/
|
||||
|
||||
mMatPreviewButton->setPosition(0, 0);
|
||||
mMatPreviewButton->setExtent(100,100);
|
||||
GuiControl* retCtrl = Parent::constructEditControl();
|
||||
if (retCtrl == NULL)
|
||||
return retCtrl;
|
||||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainMaterialAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mMatPreviewButton->setField("Command", szBuffer);
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainMaterialAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
mMatPreviewButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mMatPreviewButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mMatPreviewButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
|
||||
|
||||
StringBuilder strbld;
|
||||
strbld.append(matAsset->getMaterialDefinitionName());
|
||||
strbld.append("\n");
|
||||
strbld.append("Open this asset in the Material Editor");
|
||||
// Create "Open in Editor" button
|
||||
mEditButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
mMatPreviewButton->setDataField(StringTable->insert("tooltip"), NULL, strbld.data());
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.editAsset(%d.getText());", retCtrl->getId());
|
||||
mEditButton->setField("Command", szBuffer);
|
||||
|
||||
_registerEditControl(mMatPreviewButton);
|
||||
//mMatPreviewButton->registerObject();
|
||||
mMatEdContainer->addObject(mMatPreviewButton);
|
||||
char bitmapName[512] = "ToolsModule:material_editor_n_image";
|
||||
mEditButton->setBitmap(StringTable->insert(bitmapName));
|
||||
|
||||
mMatAssetIdTxt = new GuiTextEditCtrl();
|
||||
mMatAssetIdTxt->registerObject();
|
||||
mMatAssetIdTxt->setActive(false);
|
||||
mEditButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
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 Terrain Material Editor");
|
||||
|
||||
mMatAssetIdTxt->setText(matAssetId);
|
||||
mEditButton->registerObject();
|
||||
addObject(mEditButton);
|
||||
|
||||
mMatAssetIdTxt->setBounds(100, 0, 150, 18);
|
||||
mMatEdContainer->addObject(mMatAssetIdTxt);
|
||||
|
||||
return mMatEdContainer;
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeTerrainMaterialAssetPtr::updateRects()
|
||||
|
|
@ -305,41 +548,32 @@ bool GuiInspectorTypeTerrainMaterialAssetPtr::updateRects()
|
|||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
|
||||
|
||||
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
|
||||
if (mMatEdContainer != nullptr)
|
||||
if (mBrowseButton != NULL)
|
||||
{
|
||||
mMatPreviewButton->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
|
||||
}
|
||||
|
||||
if (mMatPreviewButton != nullptr)
|
||||
if (mEditButton != NULL)
|
||||
{
|
||||
mMatPreviewButton->resize(Point2I::Zero, Point2I(100, 100));
|
||||
}
|
||||
|
||||
if (mMatAssetIdTxt != nullptr)
|
||||
{
|
||||
mMatAssetIdTxt->resize(Point2I(100, 0), Point2I(mEditCtrlRect.extent.x - 100, 18));
|
||||
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mEditButton->resize(shapeEdRect.point, shapeEdRect.extent);
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
|
||||
void GuiInspectorTypeTerrainMaterialAssetPtr::setMaterialAsset(String assetId)
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeTerrainMaterialAssetId);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeTerrainMaterialAssetId,
|
||||
"@brief Inspector field type for Terrain Material Assets\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeTerrainMaterialAssetId::consoleInit()
|
||||
{
|
||||
mTargetObject->setDataField(mCaption, "", assetId);
|
||||
Parent::consoleInit();
|
||||
|
||||
//force a refresh
|
||||
SimObject* obj = mInspector->getInspectObject();
|
||||
mInspector->inspectObject(obj);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorTypeTerrainMaterialAssetPtr, setMaterialAsset, void, (String assetId), (""),
|
||||
"Gets a particular shape animation asset for this shape.\n"
|
||||
"@param animation asset index.\n"
|
||||
"@return Shape Animation Asset.\n")
|
||||
{
|
||||
if (assetId == String::EmptyString)
|
||||
return;
|
||||
|
||||
return object->setMaterialAsset(assetId);
|
||||
ConsoleBaseType::getType(TypeTerrainMaterialAssetId)->setInspectorFieldType("GuiInspectorTypeTerrainMaterialAssetId");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,13 @@
|
|||
#include "gui/editor/guiInspectorTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TERRMATERIAL_H_
|
||||
#include "terrain/terrMaterial.h"
|
||||
#endif
|
||||
|
||||
#ifndef _MATERIALDEFINITION_H_
|
||||
#include "materials/materialDefinition.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class TerrainMaterialAsset : public AssetBase
|
||||
|
|
@ -58,23 +64,55 @@ class TerrainMaterialAsset : public AssetBase
|
|||
StringTableEntry mScriptPath;
|
||||
StringTableEntry mMatDefinitionName;
|
||||
|
||||
SimObjectPtr<TerrainMaterial> mMaterialDefinition;
|
||||
|
||||
SimObjectPtr<Material> mFXMaterialDefinition;
|
||||
|
||||
public:
|
||||
static StringTableEntry smNoTerrainMaterialAssetFallback;
|
||||
|
||||
enum TerrainMaterialAssetErrCode
|
||||
{
|
||||
ScriptLoaded = AssetErrCode::Extended,
|
||||
DefinitionAlreadyExists,
|
||||
EmbeddedDefinition,
|
||||
Extended
|
||||
};
|
||||
|
||||
public:
|
||||
TerrainMaterialAsset();
|
||||
virtual ~TerrainMaterialAsset();
|
||||
/// Set up some global script interface stuff.
|
||||
static void consoleInit();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
static StringTableEntry getAssetIdByMaterialName(StringTableEntry matName);
|
||||
void loadMaterial();
|
||||
|
||||
StringTableEntry getMaterialDefinitionName() { return mMatDefinitionName; }
|
||||
SimObjectPtr<TerrainMaterial> getMaterialDefinition() { return mMaterialDefinition; }
|
||||
|
||||
SimObjectPtr<Material> getFXMaterialDefinition() { return mFXMaterialDefinition; }
|
||||
|
||||
void setScriptFile(const char* pScriptFile);
|
||||
inline StringTableEntry getScriptFile(void) const { return mScriptFile; };
|
||||
|
||||
inline StringTableEntry getScriptPath(void) const { return mScriptPath; };
|
||||
|
||||
/// <summary>
|
||||
/// Looks for any assets that uses the provided Material Definition name.
|
||||
/// If none are found, attempts to auto-import the material definition if the
|
||||
/// material definition exists.
|
||||
/// </summary>
|
||||
/// <param name="matName">Material Definition name to look for</param>
|
||||
/// <returns>AssetId of matching asset.</returns>
|
||||
static StringTableEntry getAssetIdByMaterialName(StringTableEntry matName);
|
||||
static U32 getAssetById(StringTableEntry assetId, AssetPtr<TerrainMaterialAsset>* materialAsset);
|
||||
static SimObjectPtr<TerrainMaterial> findMaterialDefinitionByAssetId(StringTableEntry assetId);
|
||||
static U32 getAssetByMaterialName(StringTableEntry matName, AssetPtr<TerrainMaterialAsset>* matAsset);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(TerrainMaterialAsset);
|
||||
|
||||
|
|
@ -82,30 +120,40 @@ protected:
|
|||
virtual void initializeAsset();
|
||||
virtual void onAssetRefresh(void);
|
||||
|
||||
static bool setScriptFile(void *obj, const char *index, const char *data) { static_cast<TerrainMaterialAsset*>(obj)->setScriptFile(data); return false; }
|
||||
static bool setScriptFile(void *obj, const char *index, const char *data)
|
||||
{
|
||||
static_cast<TerrainMaterialAsset*>(obj)->setScriptFile(data);
|
||||
return false;
|
||||
}
|
||||
static const char* getScriptFile(void* obj, const char* data) { return static_cast<TerrainMaterialAsset*>(obj)->getScriptFile(); }
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeTerrainMaterialAssetPtr, TerrainMaterialAsset)
|
||||
DefineConsoleType(TypeTerrainMaterialAssetId, String)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeTerrainMaterialAssetPtr : public GuiInspectorField
|
||||
class GuiInspectorTypeTerrainMaterialAssetPtr : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorField Parent;
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiControl* mMatEdContainer;
|
||||
GuiBitmapButtonCtrl *mMatPreviewButton;
|
||||
GuiTextEditCtrl *mMatAssetIdTxt;
|
||||
GuiBitmapButtonCtrl* mEditButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeTerrainMaterialAssetPtr);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
void setMaterialAsset(String assetId);
|
||||
};
|
||||
class GuiInspectorTypeTerrainMaterialAssetId : public GuiInspectorTypeTerrainMaterialAssetPtr
|
||||
{
|
||||
typedef GuiInspectorTypeTerrainMaterialAssetPtr Parent;
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeTerrainMaterialAssetId);
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -261,6 +261,16 @@ public:
|
|||
/// </summary>
|
||||
F32 animFPS;
|
||||
|
||||
/// <summary>
|
||||
/// When importing a shape animation, this indicates if it should automatically add a standard suffix onto the name
|
||||
/// </summary>
|
||||
bool AlwaysAddShapeAnimationSuffix;
|
||||
|
||||
/// <summary>
|
||||
/// If AlwaysAddShapeAnimationSuffix is on, this is the suffix to be added
|
||||
/// </summary>
|
||||
String AddedShapeAnimationSuffix;
|
||||
|
||||
//
|
||||
//Collision
|
||||
/// <summary>
|
||||
|
|
@ -409,6 +419,15 @@ public:
|
|||
/// </summary>
|
||||
bool SoundsCompressed;
|
||||
|
||||
/// When importing an image, this indicates if it should automatically add a standard suffix onto the name
|
||||
/// </summary>
|
||||
bool AlwaysAddSoundSuffix;
|
||||
|
||||
/// <summary>
|
||||
/// If AlwaysAddSoundSuffix is on, this is the suffix to be added
|
||||
/// </summary>
|
||||
String AddedSoundSuffix;
|
||||
|
||||
public:
|
||||
AssetImportConfig();
|
||||
virtual ~AssetImportConfig();
|
||||
|
|
@ -492,15 +511,20 @@ public:
|
|||
/// </summary>
|
||||
bool dirty;
|
||||
|
||||
enum
|
||||
{
|
||||
NotProcessed=0,
|
||||
Processed,
|
||||
Skipped,
|
||||
UseForDependencies,
|
||||
Error,
|
||||
Imported
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Is this asset item marked to be skipped. If it is, it's usually due to being marked as deleted
|
||||
/// </summary>
|
||||
bool skip;
|
||||
|
||||
/// <summary>
|
||||
/// Has the asset item been processed
|
||||
/// </summary>
|
||||
bool processed;
|
||||
U32 importStatus;
|
||||
|
||||
/// <summary>
|
||||
/// Is this specific asset item generated as part of the import process of another item
|
||||
|
|
@ -564,6 +588,10 @@ public:
|
|||
{
|
||||
return o.getId() == this->getId();
|
||||
}
|
||||
|
||||
bool canImport() {
|
||||
return (importStatus == AssetImportObject::Processed);
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -629,6 +657,8 @@ class AssetImporter : public SimObject
|
|||
/// </summary>
|
||||
String finalImportedAssetPath;
|
||||
|
||||
bool mDumpLogs;
|
||||
|
||||
public:
|
||||
AssetImporter();
|
||||
virtual ~AssetImporter();
|
||||
|
|
@ -780,11 +810,17 @@ public:
|
|||
void processMaterialAsset(AssetImportObject* assetItem);
|
||||
|
||||
/// <summary>
|
||||
/// Process a specific AssetImportObject that is an ShapeAsset type to prepare it for importing
|
||||
/// Process a specific AssetImportObject that is an ShapeAnimationAsset type to prepare it for importing
|
||||
/// <para>@param assetItem, The AssetImportObject to process</para>
|
||||
/// </summary>
|
||||
void processShapeAsset(AssetImportObject* assetItem);
|
||||
|
||||
/// <summary>
|
||||
/// Process a specific AssetImportObject that is an ShapeAsset type to prepare it for importing
|
||||
/// <para>@param assetItem, The AssetImportObject to process</para>
|
||||
/// </summary>
|
||||
void processShapeAnimationAsset(AssetImportObject* assetItem);
|
||||
|
||||
/// <summary>
|
||||
/// Process a specific ShapeAsset AssetImportObject with a material id in order to parse and handle the materials listed in the shape file
|
||||
/// <para>@param assetItem, The AssetImportObject to process</para>
|
||||
|
|
@ -878,6 +914,12 @@ public:
|
|||
/// </summary>
|
||||
Torque::Path importShapeAnimationAsset(AssetImportObject* assetItem);
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over all the items in the current session and acquires them, which jumpstarts the loading/init'ng process on them, making the available for use immediately
|
||||
/// <para>@param assetItem, if null, will loop over and recurse the main import asset items, if a specific AssetImportObject is passed in, it will recurse it's children</para>
|
||||
/// </summary>
|
||||
void acquireAssets(AssetImportObject* assetItem = nullptr);
|
||||
|
||||
//
|
||||
/// <summary>
|
||||
/// Gets the currently active import configuration
|
||||
|
|
@ -885,9 +927,15 @@ public:
|
|||
/// </summary>
|
||||
AssetImportConfig* getImportConfig() { return activeImportConfig; }
|
||||
|
||||
void setImportConfig(AssetImportConfig* importConfig) {
|
||||
if(importConfig != nullptr)
|
||||
void setImportConfig(AssetImportConfig* importConfig)
|
||||
{
|
||||
if (importConfig != nullptr)
|
||||
{
|
||||
dSprintf(importLogBuffer, sizeof(importLogBuffer), "Loading import config: %s!", importConfig->getName());
|
||||
activityLog.push_back(importLogBuffer);
|
||||
|
||||
activeImportConfig = importConfig;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -922,16 +970,30 @@ public:
|
|||
return imagePath;
|
||||
}
|
||||
|
||||
static inline const char* makeFullPath(const String& path)
|
||||
{
|
||||
char qualifiedFilePath[2048];
|
||||
|
||||
Platform::makeFullPathName(path.c_str(), qualifiedFilePath, sizeof(qualifiedFilePath));
|
||||
|
||||
return qualifiedFilePath;
|
||||
}
|
||||
|
||||
//
|
||||
void setTargetModuleId(const String& moduleId) { targetModuleId = moduleId; }
|
||||
const String& getTargetModuleId() { return targetModuleId; }
|
||||
|
||||
String getFolderPrefixedName(AssetImportObject* assetItem)
|
||||
{
|
||||
String renamedAssetName = assetItem->assetName;
|
||||
S32 dirIndex = assetItem->filePath.getDirectoryCount() - 1;
|
||||
while (dirIndex > -1)
|
||||
{
|
||||
renamedAssetName = assetItem->assetName;
|
||||
String owningFolder = assetItem->filePath.getDirectory(dirIndex);
|
||||
|
||||
renamedAssetName = owningFolder + "_" + renamedAssetName;
|
||||
|
||||
if (AssetDatabase.isDeclaredAsset(renamedAssetName))
|
||||
{
|
||||
dirIndex--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return renamedAssetName;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,113 +6,116 @@
|
|||
//Console Functions
|
||||
|
||||
DefineEngineMethod(AssetImportConfig, loadImportConfig, void, (Settings* configSettings, String configName), (nullAsType<Settings*>(), ""),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Loads the provided import config to the importer.\n"
|
||||
"@param configSettings A Settings object containing the import configs.\n"
|
||||
"@param configName The specific name of the config to be used.")
|
||||
{
|
||||
return object->loadImportConfig(configSettings, configName);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, setTargetPath, void, (String path), (""),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Sets the target path the importing assets will be put into.\n"
|
||||
"@param A string of the target path.")
|
||||
{
|
||||
return object->setTargetPath(path);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, resetImportSession, void, (bool forceResetSession), (false),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Resets the importer's import session. All existing import items, logs, etc will be cleared.")
|
||||
{
|
||||
return object->resetImportSession(forceResetSession);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, dumpActivityLog, void, (), ,
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Dumps the import activity log. If the importer is set to, it will save to file, otherwise dump to console.")
|
||||
{
|
||||
return object->dumpActivityLog();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, getActivityLogLineCount, S32, (),,
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Gets the number of lines in the import activity log.\n"
|
||||
"@return The number of lines in the import activity log.")
|
||||
{
|
||||
return object->getActivityLogLineCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, getActivityLogLine, String, (S32 i), (0),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
DefineEngineMethod(AssetImporter, getActivityLogLine, String, (S32 index), (0),
|
||||
"Gets a specific line in the import activity log.\n"
|
||||
"@param index The index of the line to be returned.\n"
|
||||
"@return The string of the requested line of the activity log")
|
||||
{
|
||||
return object->getActivityLogLine(0);
|
||||
return object->getActivityLogLine(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, autoImportFile, String, (String path, String typeHint), ("", ""),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Run the full import process on a specific file.\n"
|
||||
"@return If import is successful, the assetId of the new asset. If it failed, an empty string.")
|
||||
{
|
||||
return object->autoImportFile(path, typeHint);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, addImportingFile, AssetImportObject*, (String path), (""),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Adds a filepath to the current importing session.\n"
|
||||
"@param path The path to the file to be imported.\n"
|
||||
"@return The AssetImportObject from the import session.")
|
||||
{
|
||||
return object->addImportingFile(path);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, addImportingAssetItem, void, (AssetImportObject* assetItem, AssetImportObject* parentItem), (nullAsType< AssetImportObject*>(), nullAsType< AssetImportObject*>()),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Adds an existing AssetImportObject to the current improting session.\n"
|
||||
"@param assetItem The AssetImportObject to be added to the import session.\n"
|
||||
"@param parentItem An AssetImportObject that to act as the parent of the item being added.")
|
||||
{
|
||||
return object->addImportingAssetItem(assetItem, parentItem);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, processImportingAssets, void, (), ,
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Processes the importing assets.")
|
||||
{
|
||||
return object->processImportAssets();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, validateImportingAssets, bool, (), ,
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
DefineEngineMethod(AssetImporter, hasImportIssues, bool, (), ,
|
||||
"Validates the status of the importing items.\n"
|
||||
"@return False if there are no issues, true if there are importing issues")
|
||||
{
|
||||
return object->validateAssets();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, resolveAssetItemIssues, void, (AssetImportObject* assetItem), (nullAsType< AssetImportObject*>()),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Runs the issue resolver to attempt to correct any simple issues, such as utilizing the config's settings to resolve collisions.")
|
||||
{
|
||||
object->resolveAssetItemIssues(assetItem);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, importAssets, void, (),,
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Runs the actual import action on the items.")
|
||||
{
|
||||
return object->importAssets();
|
||||
object->importAssets();
|
||||
|
||||
object->acquireAssets();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, getAssetItemCount, S32, (),,
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Gets the number of importing asset items.\n"
|
||||
"@return The number of importing asset items")
|
||||
{
|
||||
return object->getAssetItemCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, getAssetItem, AssetImportObject*, (S32 index), (0),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Gets a specific import asset item.\n"
|
||||
"@param index The index of the AssetImportObject to be returned.\n"
|
||||
"@return AssetImportObject")
|
||||
{
|
||||
return object->getAssetItem(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, getAssetItemChildCount, S32, (AssetImportObject* assetItem), (nullAsType< AssetImportObject*>()),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Gets number of child items for a given importing asset item.\n"
|
||||
"@param assetItem The AssetImportObject to get the number of children of.\n"
|
||||
"@return The number of child items")
|
||||
{
|
||||
if (assetItem == nullptr)
|
||||
return 0;
|
||||
|
|
@ -121,8 +124,10 @@ DefineEngineMethod(AssetImporter, getAssetItemChildCount, S32, (AssetImportObjec
|
|||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, getAssetItemChild, AssetImportObject*, (AssetImportObject* assetItem, S32 index), (nullAsType< AssetImportObject*>(), 0),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Gets a specific child item of a given importing asset item.\n"
|
||||
"@param assetItem The AssetImportObject to get the child from.\n"
|
||||
"@param index The index of the child to get.\n"
|
||||
"@return The child AssetImportObect")
|
||||
{
|
||||
if (assetItem == nullptr)
|
||||
return nullptr;
|
||||
|
|
@ -131,31 +136,15 @@ DefineEngineMethod(AssetImporter, getAssetItemChild, AssetImportObject*, (AssetI
|
|||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, deleteImportingAsset, void, (AssetImportObject* assetItem), (nullAsType< AssetImportObject*>()),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Deletes an importing AssetImportObject from the import session.\n"
|
||||
"@param assetItem The AssetImportObject to delete.")
|
||||
{
|
||||
return object->deleteImportingAsset(assetItem);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, setImportConfig, void, (AssetImportConfig* importConfig), (nullAsType< AssetImportConfig*>()),
|
||||
"Creates a new script asset using the targetFilePath.\n"
|
||||
"@return The bool result of calling exec")
|
||||
"Sets the import config to be used via a AssetImportConfig object.\n"
|
||||
"@param importConfig The AssetImportConfig object to use.")
|
||||
{
|
||||
return object->setImportConfig(importConfig);
|
||||
}
|
||||
|
||||
|
||||
/*DefineEngineFunction(enumColladaForImport, bool, (const char* shapePath, const char* ctrl, bool loadCachedDts), ("", "", true),
|
||||
"(string shapePath, GuiTreeViewCtrl ctrl) Collect scene information from "
|
||||
"a COLLADA file and store it in a GuiTreeView control. This function is "
|
||||
"used by the COLLADA import gui to show a preview of the scene contents "
|
||||
"prior to import, and is probably not much use for anything else.\n"
|
||||
"@param shapePath COLLADA filename\n"
|
||||
"@param ctrl GuiTreeView control to add elements to\n"
|
||||
"@param loadCachedDts dictates if it should try and load the cached dts file if it exists"
|
||||
"@return true if successful, false otherwise\n"
|
||||
"@ingroup Editors\n"
|
||||
"@internal")
|
||||
{
|
||||
return enumColladaForImport(shapePath, ctrl, loadCachedDts);
|
||||
}*/
|
||||
|
|
|
|||
298
Engine/source/T3D/assets/assetMacroHelpers.h
Normal file
298
Engine/source/T3D/assets/assetMacroHelpers.h
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
//general class-injection hooks for asset support. not all cases are needed for every class/usage.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// INDIVIDUALIZED CLASS ENTRIES
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//iniitalization
|
||||
#define INIT_ASSET(name) \
|
||||
m##name##Name = StringTable->EmptyString(); \
|
||||
m##name##AssetId = StringTable->EmptyString(); \
|
||||
m##name##Asset = NULL;\
|
||||
m##name = NULL;
|
||||
|
||||
//load asset into memory by looking up the ID, spew a warning if anything goes wrong
|
||||
#define LOAD_ASSET(name, assetClass)\
|
||||
if (m##name##AssetId != StringTable->EmptyString())\
|
||||
{\
|
||||
S32 assetState = assetClass::getAssetById(m##name##AssetId, &m##name##Asset);\
|
||||
if (assetState == assetClass::Ok )\
|
||||
{\
|
||||
m##name##Name = StringTable->EmptyString();\
|
||||
}\
|
||||
else Con::warnf("Warning: %s::LOAD_ASSET(%s)-%s", mClassName, m##name##AssetId, assetClass::getAssetErrstrn(assetState).c_str());\
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
#define CLONE_ASSET(name) \
|
||||
m##name##Name = other.m##name##Name;\
|
||||
m##name##AssetId = other.m##name##AssetId;\
|
||||
m##name##Asset = other.m##name##Asset;\
|
||||
m##name = other.m##name
|
||||
|
||||
// addProtectedField acessors
|
||||
#define DECLARE_ASSET_SETGET(className, name)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
// addProtectedField acessors for networked objects (sets a flag)
|
||||
#define DECLARE_ASSET_NET_SETGET(className, name, bitmask)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data));\
|
||||
if(ret)\
|
||||
object->setMaskBits(bitmask);\
|
||||
return ret;\
|
||||
}
|
||||
|
||||
//network send - datablock
|
||||
#define PACKDATA_ASSET(name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset.getAssetId());\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
//network recieve - datablock
|
||||
#define UNPACKDATA_ASSET(name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = stream->readSTString();\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
m##name##Name = stream->readSTString();\
|
||||
_set##name(m##name##Name);\
|
||||
}
|
||||
|
||||
//network send - object-instance
|
||||
#define PACK_ASSET(netconn, name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
NetStringHandle assetIdStr = m##name##Asset.getAssetId();\
|
||||
netconn->packNetStringHandleU(stream, assetIdStr);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name);
|
||||
|
||||
//network recieve - object-instance
|
||||
#define UNPACK_ASSET(netconn, name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = StringTable->insert(netconn->unpackNetStringHandleU(stream).getString());\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
m##name##Name = stream->readSTString();
|
||||
|
||||
//script methods for class.asset acces
|
||||
//declare general get<entry>, get<entry>Asset and set<entry> methods
|
||||
#define DEF_ASSET_BINDS(className,name)\
|
||||
DefineEngineMethod(className, get##name, String, (), , "get name")\
|
||||
{\
|
||||
return object->get##name(); \
|
||||
}\
|
||||
DefineEngineMethod(className, get##name##Asset, String, (), , assetText(name, asset reference))\
|
||||
{\
|
||||
return object->m##name##AssetId; \
|
||||
}\
|
||||
DefineEngineMethod(className, set##name, bool, (const char* assetName), , assetText(name,assignment. first tries asset then flat file.))\
|
||||
{\
|
||||
return object->_set##name(StringTable->insert(assetName));\
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// ARRAY CLASS ENTRIES
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//iniitalization
|
||||
#define INIT_ASSET_ARRAY(name, index) \
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString(); \
|
||||
m##name##AssetId[index] = StringTable->EmptyString(); \
|
||||
m##name##Asset[index] = NULL;\
|
||||
m##name[index] = NULL;\
|
||||
}
|
||||
|
||||
//load asset into memory by looking up the ID, spew a warning if anything goes wrong
|
||||
#define LOAD_ASSET_ARRAY(name, index, assetClass)\
|
||||
if (m##name##AssetId[index] != StringTable->EmptyString())\
|
||||
{\
|
||||
S32 assetState = assetClass::getAssetById(m##name##AssetId[index], &m##name##Asset[index]);\
|
||||
if (assetState == assetClass::Ok )\
|
||||
{\
|
||||
m##name##Name[index] = StringTable->EmptyString();\
|
||||
}\
|
||||
else Con::warnf("Warning: %s::LOAD_ASSET(%s[%d])-%s", mClassName, m##name##AssetId[index],index, assetClass::getAssetErrstrn(assetState).c_str());\
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
#define CLONE_ASSET_ARRAY(name, index) \
|
||||
{\
|
||||
m##name##Name[index] = other.m##name##Name[index];\
|
||||
m##name##AssetId[index] = other.m##name##AssetId[index];\
|
||||
m##name##Asset[index] = other.m##name##Asset[index];\
|
||||
m##name[index] = other.m##name[index];\
|
||||
}
|
||||
// addProtectedField acessors
|
||||
#define DECLARE_ASSET_ARRAY_SETGET(className, name)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
if(!index) return false;\
|
||||
U32 idx = dAtoi(index);\
|
||||
if (idx >= sm##name##Count)\
|
||||
return false;\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data), idx);\
|
||||
return ret;\
|
||||
}
|
||||
// addProtectedField acessors for networked objects (sets a flag)
|
||||
#define DECLARE_ASSET_ARRAY_NET_SETGET(className, name, bitmask)\
|
||||
static bool _set##name##Data(void* obj, const char* index, const char* data)\
|
||||
{\
|
||||
if (!index) return false;\
|
||||
U32 idx = dAtoi(index);\
|
||||
if (idx >= sm##name##Count)\
|
||||
return false;\
|
||||
bool ret = false;\
|
||||
className* object = static_cast<className*>(obj);\
|
||||
ret = object->_set##name(StringTable->insert(data), idx);\
|
||||
if(ret)\
|
||||
object->setMaskBits(bitmask);\
|
||||
return ret;\
|
||||
}
|
||||
//network send - datablock
|
||||
#define PACKDATA_ASSET_ARRAY(name, index)\
|
||||
if (stream->writeFlag(m##name##Asset[index].notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset[index].getAssetId());\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name[index]);
|
||||
|
||||
//network recieve - datablock
|
||||
#define UNPACKDATA_ASSET_ARRAY(name, index)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId[index] = stream->readSTString();\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
m##name##Name[index] = stream->readSTString();\
|
||||
_set##name(m##name##Name[index], index);\
|
||||
}
|
||||
|
||||
//network send - object-instance
|
||||
#define PACK_ASSET_ARRAY(netconn, name, index)\
|
||||
if (stream->writeFlag(m##name##Asset[index].notNull()))\
|
||||
{\
|
||||
NetStringHandle assetIdStr = m##name##Asset[index].getAssetId();\
|
||||
netconn->packNetStringHandleU(stream, assetIdStr);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name[index]);
|
||||
|
||||
//network recieve - object-instance
|
||||
#define UNPACK_ASSET_ARRAY(netconn, name, index)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId[index] = StringTable->insert(netconn->unpackNetStringHandleU(stream).getString());\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
m##name##Name[index] = stream->readSTString();\
|
||||
_set##name(m##name##Name[index], index);\
|
||||
}
|
||||
|
||||
//script methods for class.asset acces
|
||||
//declare general get<entry>, get<entry>Asset and set<entry> methods
|
||||
//signatures are:
|
||||
//using DiffuseMap as an example
|
||||
//material.getDiffuseMap(%layer); //returns the raw file referenced
|
||||
//material.getDiffuseMapAsset(%layer); //returns the asset id
|
||||
//material.setDiffuseMap(%texture, %layer); //tries to set the asset and failing that attempts a flat file reference
|
||||
#define DEF_ASSET_ARRAY_BINDS(className,name)\
|
||||
DefineEngineMethod(className, get##name, const char*, (S32 index), , "get name")\
|
||||
{\
|
||||
return object->get##name(index); \
|
||||
}\
|
||||
DefineEngineMethod(className, get##name##Asset, const char*, (S32 index), , assetText(name, asset reference))\
|
||||
{\
|
||||
if(index >= className::sm##name##Count || index < 0)\
|
||||
return "";\
|
||||
return object->m##name##AssetId[index]; \
|
||||
}\
|
||||
DefineEngineMethod(className, set##name, bool, (const char* assetName, S32 index), , assetText(name,assignment. first tries asset then flat file.))\
|
||||
{\
|
||||
return object->_set##name(StringTable->insert(assetName), index);\
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// ARRAYS REFERENCED VIA ENUM CLASS ENTRIES
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// substite these in to see the enum strings and assigned values
|
||||
//network send - object-instance
|
||||
#define PACKDATA_ASSET_ARRAY_ENUMED(name, enumType, index )\
|
||||
{\
|
||||
if (stream->writeFlag(m##name##Asset[index].notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset[index].getAssetId());\
|
||||
const char* enumString = castConsoleTypeToString(static_cast<enumType>(index));\
|
||||
Con::printf("pack: %s = %s",enumString, m##name##AssetId[index]);\
|
||||
}\
|
||||
else\
|
||||
stream->writeString(m##name##Name[index]);\
|
||||
}
|
||||
//network recieve - object-instance
|
||||
#define UNPACKDATA_ASSET_ARRAY_ENUMED(name, enumType, index )\
|
||||
{\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId[index] = stream->readSTString();\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
const char* enumString = castConsoleTypeToString(static_cast<enumType>(index));\
|
||||
Con::printf("unpack: %s = %s",enumString, m##name##AssetId[index]);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
m##name##Name[index] = stream->readSTString();\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
}\
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ GuiControl* GuiInspectorTypeStateMachineAssetPtr::constructEditControl()
|
|||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"StateMachineAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mInspector->getIdString(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
|
|
|
|||
|
|
@ -222,7 +222,6 @@ bool ConvexShape::protectedSetSurface( void *object, const char *index, const ch
|
|||
*/
|
||||
|
||||
String t = data;
|
||||
S32 len = t.length();
|
||||
|
||||
dSscanf( data, "%g %g %g %g %g %g %g %i %g %g %g %g %f", &quat.x, &quat.y, &quat.z, &quat.w, &pos.x, &pos.y, &pos.z,
|
||||
&matID, &offset.x, &offset.y, &scale.x, &scale.y, &rot);
|
||||
|
|
@ -290,7 +289,7 @@ ConvexShape::ConvexShape()
|
|||
mSurfaceUVs.clear();
|
||||
mSurfaceTextures.clear();
|
||||
|
||||
INIT_MATERIALASSET(Material);
|
||||
INIT_ASSET(Material);
|
||||
}
|
||||
|
||||
ConvexShape::~ConvexShape()
|
||||
|
|
@ -318,10 +317,10 @@ void ConvexShape::initPersistFields()
|
|||
|
||||
addGroup( "Internal" );
|
||||
|
||||
addProtectedField( "surface", TypeRealString, NULL, &protectedSetSurface, &defaultProtectedGetFn,
|
||||
addProtectedField( "surface", TypeRealString, 0, &protectedSetSurface, &defaultProtectedGetFn,
|
||||
"Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors );
|
||||
|
||||
addProtectedField( "surfaceTexture", TypeRealString, NULL, &protectedSetSurfaceTexture, &defaultProtectedGetFn,
|
||||
addProtectedField( "surfaceTexture", TypeRealString, 0, &protectedSetSurfaceTexture, &defaultProtectedGetFn,
|
||||
"Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors );
|
||||
|
||||
endGroup( "Internal" );
|
||||
|
|
@ -528,7 +527,7 @@ U32 ConvexShape::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
|
|||
|
||||
if ( stream->writeFlag( mask & UpdateMask ) )
|
||||
{
|
||||
PACK_MATERIALASSET(conn, Material);
|
||||
PACK_ASSET(conn, Material);
|
||||
|
||||
U32 surfCount = mSurfaces.size();
|
||||
stream->writeInt( surfCount, 32 );
|
||||
|
|
@ -584,7 +583,7 @@ void ConvexShape::unpackUpdate( NetConnection *conn, BitStream *stream )
|
|||
|
||||
if ( stream->readFlag() ) // UpdateMask
|
||||
{
|
||||
UNPACK_MATERIALASSET(conn, Material);
|
||||
UNPACK_ASSET(conn, Material);
|
||||
|
||||
mSurfaces.clear();
|
||||
mSurfaceUVs.clear();
|
||||
|
|
@ -961,17 +960,6 @@ bool ConvexShape::castRay( const Point3F &start, const Point3F &end, RayInfo *in
|
|||
VectorF rayDir( end - start );
|
||||
rayDir.normalizeSafe();
|
||||
|
||||
if ( false )
|
||||
{
|
||||
PlaneF plane( Point3F(0,0,0), Point3F(0,0,1) );
|
||||
Point3F sp( 0,0,-1 );
|
||||
Point3F ep( 0,0,1 );
|
||||
|
||||
F32 t = plane.intersect( sp, ep );
|
||||
Point3F hitPnt;
|
||||
hitPnt.interpolate( sp, ep, t );
|
||||
}
|
||||
|
||||
for ( S32 i = 0; i < planeCount; i++ )
|
||||
{
|
||||
// Don't hit the back-side of planes.
|
||||
|
|
@ -1376,8 +1364,6 @@ void ConvexShape::_updateGeometry( bool updateCollision )
|
|||
{
|
||||
U32 count = faceList[i].triangles.size();
|
||||
|
||||
S32 matID = mSurfaceUVs[i].matID;
|
||||
|
||||
mSurfaceBuffers[mSurfaceUVs[i].matID].mPrimCount += count;
|
||||
mSurfaceBuffers[mSurfaceUVs[i].matID].mVertCount += count * 3;
|
||||
}
|
||||
|
|
@ -1429,9 +1415,6 @@ void ConvexShape::_updateGeometry( bool updateCollision )
|
|||
{
|
||||
if (mSurfaceBuffers[i].mVertCount > 0)
|
||||
{
|
||||
U32 primCount = mSurfaceBuffers[i].mPrimCount;
|
||||
U32 vertCount = mSurfaceBuffers[i].mVertCount;
|
||||
|
||||
mSurfaceBuffers[i].mVertexBuffer.set(GFX, mSurfaceBuffers[i].mVertCount, GFXBufferTypeStatic);
|
||||
VertexType *pVert = mSurfaceBuffers[i].mVertexBuffer.lock();
|
||||
|
||||
|
|
@ -2171,4 +2154,4 @@ void ConvexShape::Geometry::generate(const Vector< PlaneF > &planes, const Vecto
|
|||
}
|
||||
}
|
||||
|
||||
DEF_MATERIALASSET_BINDS(ConvexShape, Material);
|
||||
DEF_ASSET_BINDS(ConvexShape, Material);
|
||||
|
|
|
|||
|
|
@ -138,14 +138,14 @@ public:
|
|||
// The name of the Material we will use for rendering
|
||||
DECLARE_MATERIALASSET(surfaceMaterial, Material);
|
||||
|
||||
DECLARE_MATERIALASSET_SETGET(surfaceMaterial, Material);
|
||||
DECLARE_ASSET_SETGET(surfaceMaterial, Material);
|
||||
|
||||
// The actual Material instance
|
||||
BaseMatInstance* materialInst;
|
||||
|
||||
surfaceMaterial()
|
||||
{
|
||||
INIT_MATERIALASSET(Material);
|
||||
INIT_ASSET(Material);
|
||||
|
||||
materialInst = NULL;
|
||||
}
|
||||
|
|
@ -264,7 +264,7 @@ protected:
|
|||
protected:
|
||||
|
||||
DECLARE_MATERIALASSET(ConvexShape, Material);
|
||||
DECLARE_MATERIALASSET_SETGET(ConvexShape, Material);
|
||||
DECLARE_ASSET_SETGET(ConvexShape, Material);
|
||||
|
||||
// The actual Material instance
|
||||
BaseMatInstance* mMaterialInst;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ DebrisData::DebrisData()
|
|||
terminalVelocity = 0.0f;
|
||||
ignoreWater = true;
|
||||
|
||||
INIT_SHAPEASSET(Shape);
|
||||
INIT_ASSET(Shape);
|
||||
}
|
||||
|
||||
//#define TRACK_DEBRIS_DATA_CLONES
|
||||
|
|
@ -152,7 +152,7 @@ DebrisData::DebrisData(const DebrisData& other, bool temp_clone) : GameBaseData(
|
|||
terminalVelocity = other.terminalVelocity;
|
||||
ignoreWater = other.ignoreWater;
|
||||
|
||||
CLONE_SHAPEASSET(Shape);
|
||||
CLONE_ASSET(Shape);
|
||||
|
||||
textureName = other.textureName;
|
||||
explosionId = other.explosionId; // -- for pack/unpack of explosion ptr
|
||||
|
|
@ -382,7 +382,7 @@ void DebrisData::packData(BitStream* stream)
|
|||
|
||||
stream->writeString( textureName );
|
||||
|
||||
PACKDATA_SHAPEASSET(Shape);
|
||||
PACKDATA_ASSET(Shape);
|
||||
|
||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
|
|
@ -426,7 +426,7 @@ void DebrisData::unpackData(BitStream* stream)
|
|||
|
||||
textureName = stream->readSTString();
|
||||
|
||||
UNPACKDATA_SHAPEASSET(Shape);
|
||||
UNPACKDATA_ASSET(Shape);
|
||||
|
||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ struct DebrisData : public GameBaseData
|
|||
bool ignoreWater;
|
||||
|
||||
DECLARE_SHAPEASSET(DebrisData, Shape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(DebrisData, Shape);
|
||||
DECLARE_ASSET_SETGET(DebrisData, Shape);
|
||||
|
||||
StringTableEntry textureName;
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ ConsoleDocClass( DecalData,
|
|||
DecalData::DecalData()
|
||||
{
|
||||
size = 5;
|
||||
INIT_MATERIALASSET(Material);
|
||||
INIT_ASSET(Material);
|
||||
|
||||
lifeSpan = 5000;
|
||||
fadeTime = 1000;
|
||||
|
|
@ -258,7 +258,7 @@ void DecalData::packData( BitStream *stream )
|
|||
stream->write( lookupName );
|
||||
stream->write( size );
|
||||
|
||||
PACKDATA_MATERIALASSET(Material);
|
||||
PACKDATA_ASSET(Material);
|
||||
|
||||
stream->write( lifeSpan );
|
||||
stream->write( fadeTime );
|
||||
|
|
@ -287,7 +287,7 @@ void DecalData::unpackData( BitStream *stream )
|
|||
assignName(lookupName);
|
||||
stream->read( &size );
|
||||
|
||||
UNPACKDATA_MATERIALASSET(Material);
|
||||
UNPACKDATA_ASSET(Material);
|
||||
|
||||
_updateMaterial();
|
||||
stream->read( &lifeSpan );
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class DecalData : public SimDataBlock
|
|||
F32 fadeEndPixelSize;
|
||||
|
||||
DECLARE_MATERIALASSET(DecalData, Material);
|
||||
DECLARE_MATERIALASSET_SETGET(DecalData, Material);
|
||||
DECLARE_ASSET_SETGET(DecalData, Material);
|
||||
|
||||
/// Material instance for decal.
|
||||
BaseMatInstance *matInst;
|
||||
|
|
@ -139,4 +139,4 @@ inline SimSet* DecalData::getSet()
|
|||
return set;
|
||||
}
|
||||
|
||||
#endif // _DECALDATA_H_
|
||||
#endif // _DECALDATA_H_
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ RenderMeshExample::RenderMeshExample()
|
|||
// Set it as a "static" object that casts shadows
|
||||
mTypeMask |= StaticObjectType | StaticShapeObjectType;
|
||||
|
||||
INIT_MATERIALASSET(Material);
|
||||
INIT_ASSET(Material);
|
||||
mMaterialInst = NULL;
|
||||
}
|
||||
|
||||
RenderMeshExample::~RenderMeshExample()
|
||||
|
|
@ -143,7 +144,7 @@ U32 RenderMeshExample::packUpdate( NetConnection *conn, U32 mask, BitStream *str
|
|||
// Write out any of the updated editable properties
|
||||
if (stream->writeFlag(mask & UpdateMask))
|
||||
{
|
||||
PACK_MATERIALASSET(conn, Material);
|
||||
PACK_ASSET(conn, Material);
|
||||
}
|
||||
|
||||
return retMask;
|
||||
|
|
@ -164,7 +165,7 @@ void RenderMeshExample::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
|
||||
if ( stream->readFlag() ) // UpdateMask
|
||||
{
|
||||
UNPACK_MATERIALASSET(conn, Material);
|
||||
UNPACK_ASSET(conn, Material);
|
||||
|
||||
if ( isProperlyAdded() )
|
||||
updateMaterial();
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class RenderMeshExample : public SceneObject
|
|||
BaseMatInstance* mMaterialInst;
|
||||
|
||||
DECLARE_MATERIALASSET(RenderMeshExample, Material);
|
||||
DECLARE_MATERIALASSET_NET_SETGET(RenderMeshExample, Material, UpdateMask);
|
||||
DECLARE_ASSET_NET_SETGET(RenderMeshExample, Material, UpdateMask);
|
||||
|
||||
// The GFX vertex and primitive buffers
|
||||
GFXVertexBufferHandle< VertexType > mVertexBuffer;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ RenderShapeExample::RenderShapeExample()
|
|||
mTypeMask |= StaticObjectType | StaticShapeObjectType;
|
||||
|
||||
// Make sure to initialize our TSShapeInstance to NULL
|
||||
INIT_ASSET(Shape);
|
||||
mShapeInstance = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +146,7 @@ U32 RenderShapeExample::packUpdate( NetConnection *conn, U32 mask, BitStream *st
|
|||
// Write out any of the updated editable properties
|
||||
if ( stream->writeFlag( mask & UpdateMask ) )
|
||||
{
|
||||
PACK_SHAPEASSET(conn, Shape);
|
||||
PACK_ASSET(conn, Shape);
|
||||
|
||||
// Allow the server object a chance to handle a new shape
|
||||
createShape();
|
||||
|
|
@ -169,7 +170,7 @@ void RenderShapeExample::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
|
||||
if ( stream->readFlag() ) // UpdateMask
|
||||
{
|
||||
UNPACK_SHAPEASSET(conn, Shape);
|
||||
UNPACK_ASSET(conn, Shape);
|
||||
|
||||
if ( isProperlyAdded() )
|
||||
createShape();
|
||||
|
|
@ -258,4 +259,4 @@ void RenderShapeExample::prepRenderImage( SceneRenderState *state )
|
|||
|
||||
// Allow the shape to submit the RenderInst(s) for itself
|
||||
mShapeInstance->render( rdata );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class RenderShapeExample : public SceneObject
|
|||
// Rendering variables
|
||||
//--------------------------------------------------------------------------
|
||||
DECLARE_SHAPEASSET(RenderShapeExample, Shape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(RenderShapeExample, Shape);
|
||||
DECLARE_ASSET_SETGET(RenderShapeExample, Shape);
|
||||
|
||||
// The actual shape instance
|
||||
TSShapeInstance* mShapeInstance;
|
||||
|
|
|
|||
|
|
@ -230,14 +230,16 @@ ExplosionData::ExplosionData()
|
|||
|
||||
faceViewer = false;
|
||||
|
||||
soundProfile = NULL;
|
||||
INIT_ASSET(Sound);
|
||||
|
||||
//soundProfile = NULL;
|
||||
particleEmitter = NULL;
|
||||
particleEmitterId = 0;
|
||||
|
||||
explosionScale.set(1.0f, 1.0f, 1.0f);
|
||||
playSpeed = 1.0f;
|
||||
|
||||
INIT_SHAPEASSET(ExplosionShape);
|
||||
INIT_ASSET(ExplosionShape);
|
||||
|
||||
explosionAnimation = -1;
|
||||
|
||||
|
|
@ -308,12 +310,12 @@ ExplosionData::ExplosionData(const ExplosionData& other, bool temp_clone) : Game
|
|||
faceViewer = other.faceViewer;
|
||||
particleDensity = other.particleDensity;
|
||||
particleRadius = other.particleRadius;
|
||||
soundProfile = other.soundProfile;
|
||||
CLONE_ASSET(Sound);
|
||||
particleEmitter = other.particleEmitter;
|
||||
particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr
|
||||
explosionScale = other.explosionScale;
|
||||
playSpeed = other.playSpeed;
|
||||
CLONE_SHAPEASSET(ExplosionShape);
|
||||
CLONE_ASSET(ExplosionShape);
|
||||
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
|
||||
|
|
@ -358,12 +360,6 @@ ExplosionData::~ExplosionData()
|
|||
if (!isTempClone())
|
||||
return;
|
||||
|
||||
if (soundProfile && soundProfile->isTempClone())
|
||||
{
|
||||
delete soundProfile;
|
||||
soundProfile = 0;
|
||||
}
|
||||
|
||||
// particleEmitter, emitterList[*], debrisList[*], explosionList[*] will delete themselves
|
||||
|
||||
#ifdef TRACK_EXPLOSION_DATA_CLONES
|
||||
|
|
@ -399,8 +395,9 @@ void ExplosionData::initPersistFields()
|
|||
"of the explosion." );
|
||||
addField( "playSpeed", TypeF32, Offset(playSpeed, ExplosionData),
|
||||
"Time scale at which to play the explosionShape <i>ambient</i> sequence." );
|
||||
addField( "soundProfile", TYPEID< SFXTrack >(), Offset(soundProfile, ExplosionData),
|
||||
"Non-looping sound effect that will be played at the start of the explosion." );
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET(Sound, ExplosionData, "Sound to play when this explosion explodes.");
|
||||
|
||||
addField( "faceViewer", TypeBool, Offset(faceViewer, ExplosionData),
|
||||
"Controls whether the visual effects of the explosion always face the camera." );
|
||||
|
||||
|
|
@ -523,7 +520,6 @@ void ExplosionData::initPersistFields()
|
|||
onlyKeepClearSubstitutions("debris"); // subs resolving to "~~", or "~0" are OK
|
||||
onlyKeepClearSubstitutions("emitter");
|
||||
onlyKeepClearSubstitutions("particleEmitter");
|
||||
onlyKeepClearSubstitutions("soundProfile");
|
||||
onlyKeepClearSubstitutions("subExplosion");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
|
@ -654,9 +650,10 @@ void ExplosionData::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_SHAPEASSET(ExplosionShape);
|
||||
PACKDATA_ASSET(ExplosionShape);
|
||||
|
||||
PACKDATA_ASSET(Sound);
|
||||
|
||||
sfxWrite( stream, soundProfile );
|
||||
if (stream->writeFlag(particleEmitter))
|
||||
stream->writeRangedU32(particleEmitter->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
|
||||
|
||||
|
|
@ -757,9 +754,9 @@ void ExplosionData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_SHAPEASSET(ExplosionShape);
|
||||
UNPACKDATA_ASSET(ExplosionShape);
|
||||
|
||||
sfxRead( stream, &soundProfile );
|
||||
UNPACKDATA_ASSET(Sound);
|
||||
|
||||
if (stream->readFlag())
|
||||
particleEmitterId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
|
|
@ -861,15 +858,27 @@ bool ExplosionData::preload(bool server, String &errorStr)
|
|||
{
|
||||
if (Parent::preload(server, errorStr) == false)
|
||||
return false;
|
||||
|
||||
|
||||
if( !server )
|
||||
{
|
||||
String sfxErrorStr;
|
||||
if( !sfxResolve( &soundProfile, sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "Error, unable to load sound profile for explosion datablock: %s", sfxErrorStr.c_str());
|
||||
|
||||
if (getSound() != StringTable->EmptyString())
|
||||
{
|
||||
_setSound(getSound());
|
||||
|
||||
if (!getSoundProfile())
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "SplashData::preload: Cant get an sfxProfile for splash.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!particleEmitter && particleEmitterId != 0)
|
||||
if (Sim::findObject(particleEmitterId, particleEmitter) == false)
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "Error, unable to load particle emitter for explosion datablock");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mExplosionShapeAsset.notNull()) {
|
||||
|
|
@ -1384,7 +1393,7 @@ bool Explosion::explode()
|
|||
resetWorldBox();
|
||||
}
|
||||
|
||||
SFXProfile* sound_prof = dynamic_cast<SFXProfile*>(mDataBlock->soundProfile);
|
||||
SFXProfile* sound_prof = mDataBlock->getSoundProfile();
|
||||
if (sound_prof)
|
||||
{
|
||||
soundProfile_clone = sound_prof->cloneAndPerformSubstitutions(ss_object, ss_index);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#endif
|
||||
|
||||
#include "T3D/assets/ShapeAsset.h"
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
class ParticleEmitter;
|
||||
class ParticleEmitterData;
|
||||
|
|
@ -69,7 +70,9 @@ class ExplosionData : public GameBaseData {
|
|||
S32 particleDensity;
|
||||
F32 particleRadius;
|
||||
|
||||
SFXTrack* soundProfile;
|
||||
DECLARE_SOUNDASSET(ExplosionData, Sound);
|
||||
DECLARE_ASSET_SETGET(ExplosionData, Sound);
|
||||
|
||||
ParticleEmitterData* particleEmitter;
|
||||
S32 particleEmitterId;
|
||||
|
||||
|
|
@ -77,7 +80,7 @@ class ExplosionData : public GameBaseData {
|
|||
F32 playSpeed;
|
||||
|
||||
DECLARE_SHAPEASSET(ExplosionData, ExplosionShape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(ExplosionData, ExplosionShape);
|
||||
DECLARE_ASSET_SETGET(ExplosionData, ExplosionShape);
|
||||
|
||||
S32 explosionAnimation;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include "renderInstance/renderDeferredMgr.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "T3D/assets/MaterialAsset.h"
|
||||
#include "T3D/assets/TerrainMaterialAsset.h"
|
||||
|
||||
/// This is used for rendering ground cover billboards.
|
||||
GFXImplementVertexFormat( GCVertex )
|
||||
|
|
@ -459,7 +460,7 @@ GroundCover::GroundCover()
|
|||
|
||||
mRandomSeed = 1;
|
||||
|
||||
INIT_MATERIALASSET(Material);
|
||||
INIT_ASSET(Material);
|
||||
mMaterialInst = NULL;
|
||||
|
||||
mMatParams = NULL;
|
||||
|
|
@ -520,7 +521,7 @@ GroundCover::GroundCover()
|
|||
mBillboardRects[i].point.set( 0.0f, 0.0f );
|
||||
mBillboardRects[i].extent.set( 1.0f, 1.0f );
|
||||
|
||||
INIT_SHAPEASSET_ARRAY(Shape, i);
|
||||
INIT_ASSET_ARRAY(Shape, i);
|
||||
|
||||
mShapeInstances[i] = NULL;
|
||||
|
||||
|
|
@ -564,7 +565,7 @@ void GroundCover::initPersistFields()
|
|||
addField("shapeFilename", TypeFilename, Offset(mShapeName, GroundCover), MAX_COVERTYPES, "The cover shape filename. [Optional]", AbstractClassRep::FIELD_HideInInspectors);
|
||||
INITPERSISTFIELD_SHAPEASSET_ARRAY(Shape, MAX_COVERTYPES, GroundCover, "The cover shape. [Optional]");
|
||||
|
||||
addField( "layer", TypeTerrainMaterialName, Offset( mLayer, GroundCover ), MAX_COVERTYPES, "Terrain material name to limit coverage to, or blank to not limit." );
|
||||
addField( "layer", TypeTerrainMaterialAssetId, Offset( mLayer, GroundCover ), MAX_COVERTYPES, "Terrain material assetId to limit coverage to, or blank to not limit." );
|
||||
|
||||
addField( "invertLayer", TypeBool, Offset( mInvertLayer, GroundCover ), MAX_COVERTYPES, "Indicates that the terrain material index given in 'layer' is an exclusion mask." );
|
||||
|
||||
|
|
@ -713,7 +714,7 @@ U32 GroundCover::packUpdate( NetConnection *connection, U32 mask, BitStream *str
|
|||
// TODO: We could probably optimize a few of these
|
||||
// based on reasonable units at some point.
|
||||
|
||||
PACK_MATERIALASSET(connection, Material);
|
||||
PACK_ASSET(connection, Material);
|
||||
|
||||
stream->write( mRadius );
|
||||
stream->write( mZOffset );
|
||||
|
|
@ -766,7 +767,7 @@ U32 GroundCover::packUpdate( NetConnection *connection, U32 mask, BitStream *str
|
|||
stream->write( mBillboardRects[i].extent.x );
|
||||
stream->write( mBillboardRects[i].extent.y );
|
||||
|
||||
PACK_SHAPEASSET_ARRAY(connection, Shape, i);
|
||||
PACK_ASSET_ARRAY(connection, Shape, i);
|
||||
}
|
||||
|
||||
stream->writeFlag( mDebugRenderCells );
|
||||
|
|
@ -784,7 +785,7 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream )
|
|||
|
||||
if (stream->readFlag())
|
||||
{
|
||||
UNPACK_MATERIALASSET(connection, Material);
|
||||
UNPACK_ASSET(connection, Material);
|
||||
|
||||
stream->read( &mRadius );
|
||||
stream->read( &mZOffset );
|
||||
|
|
@ -837,7 +838,7 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream )
|
|||
stream->read( &mBillboardRects[i].extent.x );
|
||||
stream->read( &mBillboardRects[i].extent.y );
|
||||
|
||||
UNPACK_SHAPEASSET_ARRAY(connection, Shape, i);
|
||||
UNPACK_ASSET_ARRAY(connection, Shape, i);
|
||||
}
|
||||
|
||||
mDebugRenderCells = stream->readFlag();
|
||||
|
|
@ -1178,6 +1179,7 @@ GroundCoverCell* GroundCover::_generateCell( const Point2I& index,
|
|||
const bool typeIsShape = mShapeInstances[ type ] != NULL;
|
||||
const Box3F typeShapeBounds = typeIsShape ? mShapeInstances[ type ]->getShape()->mBounds : Box3F();
|
||||
const F32 typeWindScale = mWindScale[type];
|
||||
|
||||
StringTableEntry typeLayer = mLayer[type];
|
||||
const bool typeInvertLayer = mInvertLayer[type];
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ protected:
|
|||
BaseMatInstance* mMaterialInst;
|
||||
|
||||
DECLARE_MATERIALASSET(GroundCover, Material);
|
||||
DECLARE_MATERIALASSET_NET_SETGET(GroundCover, Material, InitialUpdateMask);
|
||||
DECLARE_ASSET_NET_SETGET(GroundCover, Material, InitialUpdateMask);
|
||||
|
||||
GroundCoverShaderConstData mShaderConstData;
|
||||
|
||||
|
|
@ -312,7 +312,7 @@ protected:
|
|||
/// The maximum world space elevation for placement.
|
||||
F32 mMaxElevation[MAX_COVERTYPES];
|
||||
|
||||
/// Terrain material name to limit coverage to, or
|
||||
/// Terrain material assetId to limit coverage to, or
|
||||
/// left empty to cover entire terrain.
|
||||
StringTableEntry mLayer[MAX_COVERTYPES];
|
||||
|
||||
|
|
@ -341,7 +341,7 @@ protected:
|
|||
|
||||
/// The cover shape filenames.
|
||||
DECLARE_SHAPEASSET_ARRAY(GroundCover, Shape, MAX_COVERTYPES);
|
||||
DECLARE_SHAPEASSET_ARRAY_NET_SETGET(GroundCover, Shape, -1);
|
||||
DECLARE_ASSET_ARRAY_NET_SETGET(GroundCover, Shape, -1);
|
||||
|
||||
/// The cover shape instances.
|
||||
TSShapeInstance* mShapeInstances[MAX_COVERTYPES];
|
||||
|
|
|
|||
|
|
@ -238,10 +238,12 @@ void LightningStrikeEvent::process(NetConnection*)
|
|||
//
|
||||
LightningData::LightningData()
|
||||
{
|
||||
strikeSound = NULL;
|
||||
INIT_ASSET(StrikeSound);
|
||||
|
||||
for (S32 i = 0; i < MaxThunders; i++)
|
||||
thunderSounds[i] = NULL;
|
||||
{
|
||||
INIT_ASSET_ARRAY(ThunderSound, i);
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < MaxTextures; i++)
|
||||
{
|
||||
|
|
@ -260,12 +262,11 @@ LightningData::~LightningData()
|
|||
//--------------------------------------------------------------------------
|
||||
void LightningData::initPersistFields()
|
||||
{
|
||||
addField( "strikeSound", TYPEID< SFXTrack >(), Offset(strikeSound, LightningData),
|
||||
"Sound profile to play when a lightning strike occurs." );
|
||||
addField( "thunderSounds", TYPEID< SFXTrack >(), Offset(thunderSounds, LightningData), MaxThunders,
|
||||
"@brief List of thunder sound effects to play.\n\n"
|
||||
"A random one of these sounds will be played shortly after each strike "
|
||||
"occurs." );
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET(StrikeSound, LightningData, "Sound to play when lightning STRIKES!");
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET_ARRAY(ThunderSound, MaxThunders, LightningData, "Sounds for thunder.");
|
||||
|
||||
addField( "strikeTextures", TypeString, Offset(strikeTextureNames, LightningData), MaxTextures,
|
||||
"List of textures to use to render lightning strikes." );
|
||||
|
||||
|
|
@ -290,27 +291,32 @@ bool LightningData::preload(bool server, String &errorStr)
|
|||
|
||||
//dQsort(thunderSounds, MaxThunders, sizeof(SFXTrack*), cmpSounds);
|
||||
|
||||
for (S32 i = 0; i < MaxThunders; i++) {
|
||||
if (thunderSounds[i]!= NULL) numThunders++;
|
||||
}
|
||||
|
||||
|
||||
if (server == false)
|
||||
{
|
||||
String sfxErrorStr;
|
||||
for (U32 i = 0; i < MaxThunders; i++) {
|
||||
if( !sfxResolve( &thunderSounds[ i ], sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", sfxErrorStr.c_str());
|
||||
for (S32 i = 0; i < MaxThunders; i++)
|
||||
{
|
||||
_setThunderSound(getThunderSound(i), i);
|
||||
if (isThunderSoundValid(i) && !getThunderSoundProfile(i))
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Cant get an sfxProfile for thunder.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !sfxResolve( &strikeSound, sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", sfxErrorStr.c_str());
|
||||
_setStrikeSound(getStrikeSound());
|
||||
if (isStrikeSoundValid() && !getStrikeSoundProfile())
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: can't get sfxProfile from strike sound.");
|
||||
}
|
||||
|
||||
mNumStrikeTextures = 0;
|
||||
for (U32 i = 0; i < MaxTextures; i++)
|
||||
for (U32 k = 0; k < MaxTextures; k++)
|
||||
{
|
||||
if (strikeTextureNames[i][0])
|
||||
if (strikeTextureNames[k][0])
|
||||
{
|
||||
strikeTextures[i] = GFXTexHandle(strikeTextureNames[i], &GFXStaticTextureProfile, avar("%s() - strikeTextures[%d] (line %d)", __FUNCTION__, i, __LINE__));
|
||||
strikeTextures[k] = GFXTexHandle(strikeTextureNames[k], &GFXStaticTextureProfile, avar("%s() - strikeTextures[%d] (line %d)", __FUNCTION__, k, __LINE__));
|
||||
mNumStrikeTextures++;
|
||||
}
|
||||
}
|
||||
|
|
@ -329,8 +335,7 @@ void LightningData::packData(BitStream* stream)
|
|||
U32 i;
|
||||
for (i = 0; i < MaxThunders; i++)
|
||||
{
|
||||
if (stream->writeFlag(thunderSounds[i]))
|
||||
sfxWrite(stream, thunderSounds[i]);
|
||||
PACKDATA_ASSET_ARRAY(ThunderSound, i);
|
||||
}
|
||||
|
||||
stream->writeInt(mNumStrikeTextures, 4);
|
||||
|
|
@ -338,7 +343,7 @@ void LightningData::packData(BitStream* stream)
|
|||
for (i = 0; i < MaxTextures; i++)
|
||||
stream->writeString(strikeTextureNames[i]);
|
||||
|
||||
sfxWrite( stream, strikeSound );
|
||||
PACKDATA_ASSET(StrikeSound);
|
||||
}
|
||||
|
||||
void LightningData::unpackData(BitStream* stream)
|
||||
|
|
@ -348,10 +353,7 @@ void LightningData::unpackData(BitStream* stream)
|
|||
U32 i;
|
||||
for (i = 0; i < MaxThunders; i++)
|
||||
{
|
||||
if (stream->readFlag())
|
||||
sfxRead(stream, &thunderSounds[i]);
|
||||
else
|
||||
thunderSounds[i] = NULL;
|
||||
UNPACKDATA_ASSET_ARRAY(ThunderSound, i);
|
||||
}
|
||||
|
||||
mNumStrikeTextures = stream->readInt(4);
|
||||
|
|
@ -359,7 +361,7 @@ void LightningData::unpackData(BitStream* stream)
|
|||
for (i = 0; i < MaxTextures; i++)
|
||||
strikeTextureNames[i] = stream->readSTString();
|
||||
|
||||
sfxRead( stream, &strikeSound );
|
||||
UNPACKDATA_ASSET(StrikeSound);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -584,7 +586,7 @@ void Lightning::scheduleThunder(Strike* newStrike)
|
|||
if (t <= 0.03f) {
|
||||
// If it's really close, just play it...
|
||||
U32 thunder = sgLightningRand.randI(0, mDataBlock->numThunders - 1);
|
||||
SFX->playOnce(mDataBlock->thunderSounds[thunder]);
|
||||
SFX->playOnce(mDataBlock->getThunderSoundProfile(thunder));
|
||||
} else {
|
||||
Thunder* pThunder = new Thunder;
|
||||
pThunder->tRemaining = t;
|
||||
|
|
@ -651,7 +653,7 @@ void Lightning::advanceTime(F32 dt)
|
|||
|
||||
// Play the sound...
|
||||
U32 thunder = sgLightningRand.randI(0, mDataBlock->numThunders - 1);
|
||||
SFX->playOnce(mDataBlock->thunderSounds[thunder]);
|
||||
SFX->playOnce(mDataBlock->getThunderSoundProfile(thunder));
|
||||
} else {
|
||||
pThunderWalker = &((*pThunderWalker)->next);
|
||||
}
|
||||
|
|
@ -735,9 +737,9 @@ void Lightning::processEvent(LightningStrikeEvent* pEvent)
|
|||
MatrixF trans(true);
|
||||
trans.setPosition( strikePoint );
|
||||
|
||||
if (mDataBlock->strikeSound)
|
||||
if (mDataBlock->getStrikeSoundProfile())
|
||||
{
|
||||
SFX->playOnce(mDataBlock->strikeSound, &trans );
|
||||
SFX->playOnce(mDataBlock->getStrikeSoundProfile(), &trans );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1337,4 +1339,4 @@ void LightningBolt::update( F32 dt )
|
|||
isFading = false;
|
||||
elapsedTime = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@
|
|||
|
||||
#include "gfx/gfxTextureHandle.h"
|
||||
|
||||
|
||||
#include "T3D/assets/ImageAsset.h"
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
class ShapeBase;
|
||||
class LightningStrikeEvent;
|
||||
|
|
@ -62,8 +63,13 @@ class LightningData : public GameBaseData
|
|||
|
||||
//-------------------------------------- Console set variables
|
||||
public:
|
||||
SFXTrack* thunderSounds[MaxThunders];
|
||||
SFXTrack* strikeSound;
|
||||
|
||||
DECLARE_SOUNDASSET_ARRAY(LightningData, ThunderSound, MaxThunders);
|
||||
DECLARE_ASSET_ARRAY_SETGET(LightningData, ThunderSound);
|
||||
|
||||
DECLARE_SOUNDASSET(LightningData, StrikeSound);
|
||||
DECLARE_ASSET_SETGET(LightningData, StrikeSound);
|
||||
|
||||
StringTableEntry strikeTextureNames[MaxTextures];
|
||||
|
||||
//-------------------------------------- load set variables
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ ParticleData::ParticleData()
|
|||
animTexFramesString = NULL; // string of animation frame indices
|
||||
animTexUVs = NULL; // array of tile vertex UVs
|
||||
|
||||
INIT_IMAGEASSET(Texture);
|
||||
INIT_IMAGEASSET(TextureExt);
|
||||
INIT_ASSET(Texture);
|
||||
INIT_ASSET(TextureExt);
|
||||
|
||||
constrain_pos = false;
|
||||
start_angle = 0.0f;
|
||||
|
|
@ -293,7 +293,7 @@ void ParticleData::packData(BitStream* stream)
|
|||
stream->writeFloat( times[i], 8);
|
||||
}
|
||||
|
||||
//PACKDATA_IMAGEASSET(Texture);
|
||||
//PACKDATA_ASSET(Texture);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
mathWrite(*stream, texCoords[i]);
|
||||
|
|
@ -307,7 +307,7 @@ void ParticleData::packData(BitStream* stream)
|
|||
stream->writeInt(framesPerSec, 8);
|
||||
}
|
||||
|
||||
//PACKDATA_IMAGEASSET(TextureExt);
|
||||
//PACKDATA_ASSET(TextureExt);
|
||||
|
||||
stream->writeFlag(constrain_pos);
|
||||
stream->writeFloat(start_angle/360.0f, 11);
|
||||
|
|
@ -378,7 +378,7 @@ void ParticleData::unpackData(BitStream* stream)
|
|||
times[i] = stream->readFloat(8);
|
||||
}
|
||||
|
||||
//UNPACKDATA_IMAGEASSET(Texture);
|
||||
//UNPACKDATA_ASSET(Texture);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
mathRead(*stream, &texCoords[i]);
|
||||
|
|
@ -391,7 +391,7 @@ void ParticleData::unpackData(BitStream* stream)
|
|||
framesPerSec = stream->readInt(8);
|
||||
}
|
||||
|
||||
//UNPACKDATA_IMAGEASSET(Texture);
|
||||
//UNPACKDATA_ASSET(Texture);
|
||||
|
||||
constrain_pos = stream->readFlag();
|
||||
start_angle = 360.0f*stream->readFloat(11);
|
||||
|
|
@ -763,12 +763,12 @@ ParticleData::ParticleData(const ParticleData& other, bool temp_clone) : SimData
|
|||
animTexFramesString = other.animTexFramesString;
|
||||
animTexFrames = other.animTexFrames; // -- parsed from animTexFramesString
|
||||
|
||||
CLONE_IMAGEASSET(Texture);
|
||||
CLONE_ASSET(Texture);
|
||||
|
||||
spinBias = other.spinBias;
|
||||
randomizeSpinDir = other.randomizeSpinDir;
|
||||
|
||||
CLONE_IMAGEASSET(TextureExt);
|
||||
CLONE_ASSET(TextureExt);
|
||||
|
||||
constrain_pos = other.constrain_pos;
|
||||
start_angle = other.start_angle;
|
||||
|
|
@ -804,4 +804,4 @@ void ParticleData::onPerformSubstitutions()
|
|||
reload(errorBuffer);
|
||||
}
|
||||
|
||||
DEF_IMAGEASSET_BINDS(ParticleData, Texture);
|
||||
DEF_ASSET_BINDS(ParticleData, Texture);
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class ParticleData : public SimDataBlock
|
|||
Vector<U8> animTexFrames;
|
||||
|
||||
DECLARE_IMAGEASSET(ParticleData, Texture, onImageChanged, GFXStaticTextureSRGBProfile);
|
||||
DECLARE_IMAGEASSET_SETGET(ParticleData, Texture);
|
||||
DECLARE_ASSET_SETGET(ParticleData, Texture);
|
||||
|
||||
static bool protectedSetSizes(void* object, const char* index, const char* data);
|
||||
static bool protectedSetTimes(void* object, const char* index, const char* data);
|
||||
|
|
@ -118,7 +118,7 @@ public:
|
|||
bool randomizeSpinDir;
|
||||
public:
|
||||
DECLARE_IMAGEASSET(ParticleData, TextureExt, onImageChanged, GFXStaticTextureSRGBProfile);
|
||||
DECLARE_IMAGEASSET_SETGET(ParticleData, TextureExt);
|
||||
DECLARE_ASSET_SETGET(ParticleData, TextureExt);
|
||||
|
||||
bool constrain_pos;
|
||||
F32 start_angle;
|
||||
|
|
|
|||
|
|
@ -1551,13 +1551,10 @@ void ParticleEmitter::updateBBox()
|
|||
|
||||
for (Particle* part = part_list_head.next; part != NULL; part = part->next)
|
||||
{
|
||||
for (Particle* part = part_list_head.next; part != NULL; part = part->next)
|
||||
{
|
||||
Point3F particleSize(part->size * 0.5f);
|
||||
F32 motion = getMax((part->vel.len() * part->totalLifetime / 1000.0f), 1.0f);
|
||||
minPt.setMin(part->pos - particleSize - Point3F(motion));
|
||||
maxPt.setMax(part->pos + particleSize + Point3F(motion));
|
||||
}
|
||||
Point3F particleSize(part->size * 0.5f);
|
||||
F32 motion = getMax((part->vel.len() * part->totalLifetime / 1000.0f), 1.0f);
|
||||
minPt.setMin(part->pos - particleSize - Point3F(motion));
|
||||
maxPt.setMax(part->pos + particleSize + Point3F(motion));
|
||||
}
|
||||
|
||||
mObjBox = Box3F(minPt, maxPt);
|
||||
|
|
@ -1675,8 +1672,8 @@ void ParticleEmitter::addParticle(const Point3F& pos, const Point3F& axis, const
|
|||
}
|
||||
else
|
||||
{
|
||||
U32 dBlockIndex = gRandGen.randI() % mDataBlock->particleDataBlocks.size();
|
||||
mDataBlock->particleDataBlocks[dBlockIndex]->initializeParticle(pNew, vel);
|
||||
dBlockIndex = gRandGen.randI() % mDataBlock->particleDataBlocks.size();
|
||||
mDataBlock->particleDataBlocks[dBlockIndex]->initializeParticle(pNew, vel);
|
||||
}
|
||||
updateKeyData( pNew );
|
||||
|
||||
|
|
@ -1911,42 +1908,21 @@ void ParticleEmitter::copyToVB( const Point3F &camPos, const LinearColorF &ambie
|
|||
|
||||
if (mDataBlock->reverseOrder)
|
||||
{
|
||||
buffPtr += 4 * (n_parts - 1);
|
||||
// do sorted-oriented particles
|
||||
if (mDataBlock->sortParticles)
|
||||
{
|
||||
SortParticle* partPtr = orderedVector.address();
|
||||
for (U32 i = 0; i < n_parts - 1; i++, partPtr++, buffPtr -= 4)
|
||||
setupRibbon(partPtr->p, partPtr++->p, partPtr--->p, camPos, ambientColor, buffPtr);
|
||||
}
|
||||
// do unsorted-oriented particles
|
||||
else
|
||||
{
|
||||
Particle* oldPtr = NULL;
|
||||
for (Particle* partPtr = part_list_head.next; partPtr != NULL; partPtr = partPtr->next, buffPtr -= 4) {
|
||||
for (Particle* partPtr = part_list_head.next; partPtr != NULL; partPtr = partPtr->next, buffPtr -= 4)
|
||||
{
|
||||
setupRibbon(partPtr, partPtr->next, oldPtr, camPos, ambientColor, buffPtr);
|
||||
oldPtr = partPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// do sorted-oriented particles
|
||||
if (mDataBlock->sortParticles)
|
||||
{
|
||||
SortParticle* partPtr = orderedVector.address();
|
||||
for (U32 i = 0; i < n_parts - 1; i++, partPtr++, buffPtr += 4)
|
||||
setupRibbon(partPtr->p, partPtr++->p, partPtr--->p, camPos, ambientColor, buffPtr);
|
||||
}
|
||||
// do unsorted-oriented particles
|
||||
else
|
||||
{
|
||||
Particle* oldPtr = NULL;
|
||||
for (Particle* partPtr = part_list_head.next; partPtr != NULL; partPtr = partPtr->next, buffPtr += 4) {
|
||||
for (Particle* partPtr = part_list_head.next; partPtr != NULL; partPtr = partPtr->next, buffPtr += 4)
|
||||
{
|
||||
setupRibbon(partPtr, partPtr->next, oldPtr, camPos, ambientColor, buffPtr);
|
||||
oldPtr = partPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
PROFILE_END();
|
||||
}
|
||||
|
|
@ -2220,7 +2196,7 @@ void ParticleEmitter::setupOriented( Particle *part,
|
|||
LinearColorF partCol = mLerp( part->color, ( part->color * ambientColor ), ambientLerp );
|
||||
const ColorI color = partCol.toColorI();
|
||||
// Here we deal with UVs for animated particle (oriented)
|
||||
if (part->dataBlock->animateTexture)
|
||||
if (part->dataBlock->animateTexture && !part->dataBlock->animTexFrames.empty())
|
||||
{
|
||||
// Let particle compute the UV indices for current frame
|
||||
S32 fm = (S32)(part->currentAge*(1.0f/1000.0f)*part->dataBlock->framesPerSec);
|
||||
|
|
@ -2331,7 +2307,7 @@ void ParticleEmitter::setupAligned( const Particle *part,
|
|||
LinearColorF partCol = mLerp( part->color, ( part->color * ambientColor ), ambientLerp );
|
||||
const ColorI color = partCol.toColorI();
|
||||
// Here we deal with UVs for animated particle
|
||||
if (part->dataBlock->animateTexture)
|
||||
if (part->dataBlock->animateTexture && !part->dataBlock->animTexFrames.empty())
|
||||
{
|
||||
// Let particle compute the UV indices for current frame
|
||||
S32 fm = (S32)(part->currentAge*(1.0f/1000.0f)*part->dataBlock->framesPerSec);
|
||||
|
|
@ -2520,7 +2496,7 @@ void ParticleEmitter::setupRibbon(Particle *part,
|
|||
ColorI pCol = partCol.toColorI();
|
||||
|
||||
// Here we deal with UVs for animated particle (oriented)
|
||||
if (part->dataBlock->animateTexture)
|
||||
if (part->dataBlock->animateTexture && !part->dataBlock->animTexFrames.empty())
|
||||
{
|
||||
// Let particle compute the UV indices for current frame
|
||||
S32 fm = (S32)(part->currentAge*(1.0f / 1000.0f)*part->dataBlock->framesPerSec);
|
||||
|
|
|
|||
|
|
@ -127,13 +127,13 @@ ConsoleDocClass( PrecipitationData,
|
|||
//----------------------------------------------------------
|
||||
PrecipitationData::PrecipitationData()
|
||||
{
|
||||
soundProfile = NULL;
|
||||
INIT_ASSET(Sound);
|
||||
|
||||
INIT_IMAGEASSET(Drop);
|
||||
INIT_ASSET(Drop);
|
||||
|
||||
mDropShaderName = StringTable->EmptyString();
|
||||
|
||||
INIT_IMAGEASSET(Splash);
|
||||
INIT_ASSET(Splash);
|
||||
|
||||
mSplashShaderName = StringTable->EmptyString();
|
||||
|
||||
|
|
@ -143,8 +143,7 @@ PrecipitationData::PrecipitationData()
|
|||
|
||||
void PrecipitationData::initPersistFields()
|
||||
{
|
||||
addField( "soundProfile", TYPEID< SFXTrack >(), Offset(soundProfile, PrecipitationData),
|
||||
"Looping SFXProfile effect to play while Precipitation is active." );
|
||||
INITPERSISTFIELD_SOUNDASSET(Sound, PrecipitationData, "Looping SFXProfile effect to play while Precipitation is active.");
|
||||
|
||||
addProtectedField( "dropTexture", TypeFilename, Offset(mDropName, PrecipitationData), &_setDropData, &defaultProtectedGetFn,
|
||||
"@brief Texture filename for drop particles.\n\n"
|
||||
|
|
@ -189,9 +188,16 @@ bool PrecipitationData::preload( bool server, String &errorStr )
|
|||
{
|
||||
if( Parent::preload( server, errorStr) == false)
|
||||
return false;
|
||||
if (!server)
|
||||
{
|
||||
if (getSound() != StringTable->EmptyString())
|
||||
{
|
||||
_setSound(getSound());
|
||||
|
||||
if( !server && !sfxResolve( &soundProfile, errorStr ) )
|
||||
return false;
|
||||
if (!getSoundProfile())
|
||||
Con::errorf(ConsoleLogEntry::General, "SplashData::preload: Cant get an sfxProfile for splash.");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -200,13 +206,13 @@ void PrecipitationData::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
sfxWrite( stream, soundProfile );
|
||||
PACKDATA_ASSET(Sound);
|
||||
|
||||
PACKDATA_IMAGEASSET(Drop);
|
||||
PACKDATA_ASSET(Drop);
|
||||
|
||||
stream->writeString(mDropShaderName);
|
||||
|
||||
PACKDATA_IMAGEASSET(Splash);
|
||||
PACKDATA_ASSET(Splash);
|
||||
|
||||
stream->writeString(mSplashShaderName);
|
||||
stream->write(mDropsPerSide);
|
||||
|
|
@ -217,13 +223,13 @@ void PrecipitationData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
sfxRead( stream, &soundProfile );
|
||||
UNPACKDATA_ASSET(Sound);
|
||||
|
||||
UNPACKDATA_IMAGEASSET(Drop);
|
||||
UNPACKDATA_ASSET(Drop);
|
||||
|
||||
mDropShaderName = stream->readSTString();
|
||||
|
||||
UNPACKDATA_IMAGEASSET(Splash);
|
||||
UNPACKDATA_ASSET(Splash);
|
||||
|
||||
mSplashShaderName = stream->readSTString();
|
||||
stream->read(&mDropsPerSide);
|
||||
|
|
@ -598,9 +604,9 @@ bool Precipitation::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
{
|
||||
SFX_DELETE( mAmbientSound );
|
||||
|
||||
if ( mDataBlock->soundProfile )
|
||||
if ( mDataBlock->getSoundProfile())
|
||||
{
|
||||
mAmbientSound = SFX->createSource( mDataBlock->soundProfile, &getTransform() );
|
||||
mAmbientSound = SFX->createSource(mDataBlock->getSoundProfile(), &getTransform() );
|
||||
if ( mAmbientSound )
|
||||
mAmbientSound->play();
|
||||
}
|
||||
|
|
@ -997,7 +1003,7 @@ void Precipitation::initRenderObjects()
|
|||
// entire or a partially filled vb.
|
||||
mRainIB.set(GFX, mMaxVBDrops * 6, 0, GFXBufferTypeStatic);
|
||||
U16 *idxBuff;
|
||||
mRainIB.lock(&idxBuff, NULL, NULL, NULL);
|
||||
mRainIB.lock(&idxBuff, NULL, 0, 0);
|
||||
for( U32 i=0; i < mMaxVBDrops; i++ )
|
||||
{
|
||||
//
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@
|
|||
#endif
|
||||
|
||||
#include "T3D/assets/ImageAsset.h"
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
class SFXTrack;
|
||||
//class SFXTrack;
|
||||
class SFXSource;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
@ -45,30 +46,31 @@ class PrecipitationData : public GameBaseData
|
|||
typedef GameBaseData Parent;
|
||||
|
||||
public:
|
||||
SFXTrack* soundProfile;
|
||||
DECLARE_SOUNDASSET(PrecipitationData, Sound);
|
||||
DECLARE_ASSET_SETGET(PrecipitationData, Sound);
|
||||
|
||||
DECLARE_IMAGEASSET(PrecipitationData, Drop, onDropChanged, GFXStaticTextureSRGBProfile); ///< Texture for drop particles
|
||||
DECLARE_IMAGEASSET_SETGET(PrecipitationData, Drop);
|
||||
DECLARE_IMAGEASSET(PrecipitationData, Drop, onDropChanged, GFXStaticTextureSRGBProfile); ///< Texture for drop particles
|
||||
DECLARE_ASSET_SETGET(PrecipitationData, Drop);
|
||||
|
||||
StringTableEntry mDropShaderName; ///< The name of the shader used for raindrops
|
||||
StringTableEntry mDropShaderName; ///< The name of the shader used for raindrops
|
||||
|
||||
DECLARE_IMAGEASSET(PrecipitationData, Splash, onSplashChanged, GFXStaticTextureSRGBProfile); ///< Texture for splash particles
|
||||
DECLARE_IMAGEASSET_SETGET(PrecipitationData, Splash);
|
||||
DECLARE_IMAGEASSET(PrecipitationData, Splash, onSplashChanged, GFXStaticTextureSRGBProfile); ///< Texture for splash particles
|
||||
DECLARE_ASSET_SETGET(PrecipitationData, Splash);
|
||||
|
||||
StringTableEntry mSplashShaderName; ///< The name of the shader used for raindrops
|
||||
StringTableEntry mSplashShaderName; ///< The name of the shader used for raindrops
|
||||
|
||||
S32 mDropsPerSide; ///< How many drops are on a side of the raindrop texture.
|
||||
S32 mSplashesPerSide; ///< How many splash are on a side of the splash texture.
|
||||
S32 mDropsPerSide; ///< How many drops are on a side of the raindrop texture.
|
||||
S32 mSplashesPerSide; ///< How many splash are on a side of the splash texture.
|
||||
|
||||
PrecipitationData();
|
||||
DECLARE_CONOBJECT(PrecipitationData);
|
||||
bool preload( bool server, String& errorStr );
|
||||
static void initPersistFields();
|
||||
virtual void packData(BitStream* stream);
|
||||
virtual void unpackData(BitStream* stream);
|
||||
PrecipitationData();
|
||||
DECLARE_CONOBJECT(PrecipitationData);
|
||||
bool preload( bool server, String& errorStr );
|
||||
static void initPersistFields();
|
||||
virtual void packData(BitStream* stream);
|
||||
virtual void unpackData(BitStream* stream);
|
||||
|
||||
void onDropChanged() {}
|
||||
void onSplashChanged() {}
|
||||
void onDropChanged() {}
|
||||
void onSplashChanged() {}
|
||||
};
|
||||
|
||||
struct Raindrop
|
||||
|
|
|
|||
|
|
@ -67,8 +67,10 @@ ConsoleDocClass( Splash,
|
|||
//--------------------------------------------------------------------------
|
||||
SplashData::SplashData()
|
||||
{
|
||||
soundProfile = NULL;
|
||||
soundProfileId = 0;
|
||||
//soundProfile = NULL;
|
||||
//soundProfileId = 0;
|
||||
|
||||
INIT_ASSET(Sound);
|
||||
|
||||
scale.set(1, 1, 1);
|
||||
|
||||
|
|
@ -95,7 +97,9 @@ SplashData::SplashData()
|
|||
|
||||
U32 i;
|
||||
for (i = 0; i < NUM_TEX; i++)
|
||||
INIT_IMAGEASSET_ARRAY(Texture, i);
|
||||
{
|
||||
INIT_IMAGEASSET_ARRAY(Texture, GFXStaticTextureSRGBProfile, i);
|
||||
}
|
||||
|
||||
for( i=0; i<NUM_TIME_KEYS; i++ )
|
||||
times[i] = 1.0;
|
||||
|
|
@ -112,7 +116,8 @@ SplashData::SplashData()
|
|||
//--------------------------------------------------------------------------
|
||||
void SplashData::initPersistFields()
|
||||
{
|
||||
addField("soundProfile", TYPEID< SFXProfile >(), Offset(soundProfile, SplashData), "SFXProfile effect to play.\n");
|
||||
INITPERSISTFIELD_SOUNDASSET(Sound, SplashData, "Sound to play when splash, splashes.");
|
||||
|
||||
addField("scale", TypePoint3F, Offset(scale, SplashData), "The scale of this splashing effect, defined as the F32 points X, Y, Z.\n");
|
||||
addField("emitter", TYPEID< ParticleEmitterData >(), Offset(emitterList, SplashData), NUM_EMITTERS, "List of particle emitters to create at the point of this Splash effect.\n");
|
||||
addField("delayMS", TypeS32, Offset(delayMS, SplashData), "Time to delay, in milliseconds, before actually starting this effect.\n");
|
||||
|
|
@ -158,6 +163,8 @@ void SplashData::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_ASSET(Sound);
|
||||
|
||||
mathWrite(*stream, scale);
|
||||
stream->write(delayMS);
|
||||
stream->write(delayVariance);
|
||||
|
|
@ -201,7 +208,7 @@ void SplashData::packData(BitStream* stream)
|
|||
|
||||
for( i=0; i<NUM_TEX; i++ )
|
||||
{
|
||||
PACKDATA_IMAGEASSET_ARRAY(Texture, i);
|
||||
PACKDATA_ASSET_ARRAY(Texture, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -212,6 +219,8 @@ void SplashData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_ASSET(Sound);
|
||||
|
||||
mathRead(*stream, &scale);
|
||||
stream->read(&delayMS);
|
||||
stream->read(&delayVariance);
|
||||
|
|
@ -255,7 +264,7 @@ void SplashData::unpackData(BitStream* stream)
|
|||
|
||||
for( i=0; i<NUM_TEX; i++ )
|
||||
{
|
||||
UNPACKDATA_IMAGEASSET_ARRAY(Texture, i);
|
||||
UNPACKDATA_ASSET_ARRAY(Texture, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -269,6 +278,15 @@ bool SplashData::preload(bool server, String &errorStr)
|
|||
|
||||
if (!server)
|
||||
{
|
||||
|
||||
if (getSound() != StringTable->EmptyString())
|
||||
{
|
||||
_setSound(getSound());
|
||||
|
||||
if(!getSoundProfile())
|
||||
Con::errorf(ConsoleLogEntry::General, "SplashData::preload: Cant get an sfxProfile for splash.");
|
||||
}
|
||||
|
||||
S32 i;
|
||||
for( i=0; i<NUM_EMITTERS; i++ )
|
||||
{
|
||||
|
|
@ -667,6 +685,14 @@ void Splash::spawnExplosion()
|
|||
{
|
||||
if( !mDataBlock->explosion ) return;
|
||||
|
||||
/// could just play the explosion one, but explosion could be weapon specific,
|
||||
/// splash sound could be liquid specific. food for thought.
|
||||
SFXProfile* sound_prof = mDataBlock->getSoundProfile();
|
||||
if (sound_prof)
|
||||
{
|
||||
SFX->playOnce(sound_prof, &getTransform());
|
||||
}
|
||||
|
||||
Explosion* pExplosion = new Explosion;
|
||||
pExplosion->onNewDataBlock(mDataBlock->explosion, false);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "gfx/gfxTextureHandle.h"
|
||||
|
||||
#include "T3D/assets/ImageAsset.h"
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
class ParticleEmitter;
|
||||
class ParticleEmitterData;
|
||||
|
|
@ -91,8 +92,11 @@ class SplashData : public GameBaseData
|
|||
};
|
||||
|
||||
public:
|
||||
AudioProfile* soundProfile;
|
||||
S32 soundProfileId;
|
||||
//AudioProfile* soundProfile;
|
||||
//S32 soundProfileId;
|
||||
|
||||
DECLARE_SOUNDASSET(SplashData, Sound);
|
||||
DECLARE_ASSET_SETGET(SplashData, Sound);
|
||||
|
||||
ParticleEmitterData* emitterList[NUM_EMITTERS];
|
||||
S32 emitterIDList[NUM_EMITTERS];
|
||||
|
|
@ -118,7 +122,7 @@ public:
|
|||
F32 times[ NUM_TIME_KEYS ];
|
||||
LinearColorF colors[ NUM_TIME_KEYS ];
|
||||
|
||||
DECLARE_IMAGEASSET_ARRAY(SplashData, Texture, GFXStaticTextureSRGBProfile, NUM_TEX);
|
||||
DECLARE_IMAGEASSET_ARRAY(SplashData, Texture, NUM_TEX);
|
||||
DECLARE_IMAGEASSET_ARRAY_SETGET(SplashData, Texture)
|
||||
|
||||
ExplosionData* explosion;
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ DefineEngineStringlyVariadicMethod(GameConnection, setConnectArgs, void, 3, 17,
|
|||
|
||||
"@see GameConnection::onConnect()\n\n")
|
||||
{
|
||||
StringStackWrapper args(argc - 2, argv + 2);
|
||||
ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
|
||||
object->setConnectArgs(args.count(), args);
|
||||
}
|
||||
|
||||
|
|
@ -373,7 +373,7 @@ void GameConnection::onConnectionEstablished(bool isInitiator)
|
|||
mMoveList->init();
|
||||
const char *argv[MaxConnectArgs + 2];
|
||||
argv[0] = "onConnect";
|
||||
argv[1] = NULL; // Filled in later
|
||||
argv[1] = getIdString();
|
||||
for(U32 i = 0; i < mConnectArgc; i++)
|
||||
argv[i + 2] = mConnectArgv[i];
|
||||
// NOTE: Need to fallback to Con::execute() as IMPLEMENT_CALLBACK does not
|
||||
|
|
@ -493,33 +493,32 @@ bool GameConnection::readConnectRequest(BitStream *stream, const char **errorStr
|
|||
*errorString = "CR_INVALID_ARGS";
|
||||
return false;
|
||||
}
|
||||
ConsoleValueRef connectArgv[MaxConnectArgs + 3];
|
||||
ConsoleValue connectArgvValue[MaxConnectArgs + 3];
|
||||
|
||||
for(U32 i = 0; i < mConnectArgc+3; i++)
|
||||
{
|
||||
connectArgv[i].value = &connectArgvValue[i];
|
||||
connectArgvValue[i].init();
|
||||
}
|
||||
char buffer[256];
|
||||
Net::addressToString(getNetAddress(), buffer);
|
||||
|
||||
ConsoleValue connectArgv[MaxConnectArgs + 3];
|
||||
|
||||
for(U32 i = 0; i < mConnectArgc; i++)
|
||||
{
|
||||
char argString[256];
|
||||
stream->readString(argString);
|
||||
mConnectArgv[i] = dStrdup(argString);
|
||||
connectArgv[i + 3] = mConnectArgv[i];
|
||||
connectArgv[i + 3].setString(argString);
|
||||
}
|
||||
connectArgvValue[0].setStackStringValue("onConnectRequest");
|
||||
connectArgvValue[1].setIntValue(0);
|
||||
char buffer[256];
|
||||
Net::addressToString(getNetAddress(), buffer);
|
||||
connectArgvValue[2].setStackStringValue(buffer);
|
||||
|
||||
connectArgv[0].setStringTableEntry("onConnectRequest");
|
||||
connectArgv[1].setInt(0);
|
||||
connectArgv[2].setString(buffer);
|
||||
|
||||
// NOTE: Cannot convert over to IMPLEMENT_CALLBACK as it has variable args.
|
||||
const char *ret = Con::execute(this, mConnectArgc + 3, connectArgv);
|
||||
if(ret[0])
|
||||
ConsoleValue returnValue = Con::execute(this, mConnectArgc + 3, connectArgv);
|
||||
|
||||
StringTableEntry returnStr = StringTable->insert(returnValue.getString());
|
||||
|
||||
if(returnStr[0])
|
||||
{
|
||||
*errorString = ret;
|
||||
*errorString = returnStr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -808,7 +807,7 @@ bool GameConnection::isValidControlCameraFov(F32 fov)
|
|||
return cObj->isValidCameraFov(fov);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameConnection::setControlCameraFov(F32 fov)
|
||||
|
|
@ -1088,7 +1087,7 @@ bool GameConnection::readDemoStartBlock(BitStream *stream)
|
|||
void GameConnection::demoPlaybackComplete()
|
||||
{
|
||||
static const char* demoPlaybackArgv[1] = { "demoPlaybackComplete" };
|
||||
static StringStackConsoleWrapper demoPlaybackCmd(1, demoPlaybackArgv);
|
||||
static StringArrayToConsoleValueWrapper demoPlaybackCmd(1, demoPlaybackArgv);
|
||||
|
||||
Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(demoPlaybackCmd.argc, demoPlaybackCmd.argv, false));
|
||||
Parent::demoPlaybackComplete();
|
||||
|
|
@ -1563,33 +1562,50 @@ void GameConnection::packetDropped(PacketNotify *note)
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void GameConnection::play2D(SFXProfile* profile)
|
||||
void GameConnection::play2D(StringTableEntry assetId)
|
||||
{
|
||||
postNetEvent(new Sim2DAudioEvent(profile));
|
||||
if (AssetDatabase.isDeclaredAsset(assetId))
|
||||
{
|
||||
|
||||
AssetPtr<SoundAsset> tempSoundAsset;
|
||||
tempSoundAsset = assetId;
|
||||
|
||||
postNetEvent(new SimSoundAssetEvent(tempSoundAsset));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void GameConnection::play3D(SFXProfile* profile, const MatrixF *transform)
|
||||
void GameConnection::play3D(StringTableEntry assetId, const MatrixF *transform)
|
||||
{
|
||||
if ( !transform )
|
||||
play2D(profile);
|
||||
play2D(assetId);
|
||||
|
||||
else if ( !mControlObject )
|
||||
postNetEvent(new Sim3DAudioEvent(profile,transform));
|
||||
|
||||
else
|
||||
if (AssetDatabase.isDeclaredAsset(assetId))
|
||||
{
|
||||
// TODO: Maybe improve this to account for the duration
|
||||
// of the sound effect and if the control object can get
|
||||
// into hearing range within time?
|
||||
|
||||
// Only post the event if it's within audible range
|
||||
// of the control object.
|
||||
Point3F ear,pos;
|
||||
transform->getColumn(3,&pos);
|
||||
mControlObject->getTransform().getColumn(3,&ear);
|
||||
if ((ear - pos).len() < profile->getDescription()->mMaxDistance)
|
||||
postNetEvent(new Sim3DAudioEvent(profile,transform));
|
||||
}
|
||||
AssetPtr<SoundAsset> tempSoundAsset;
|
||||
tempSoundAsset = assetId;
|
||||
|
||||
if (!mControlObject)
|
||||
postNetEvent(new SimSoundAssetEvent(tempSoundAsset, transform));
|
||||
else
|
||||
{
|
||||
// TODO: Maybe improve this to account for the duration
|
||||
// of the sound effect and if the control object can get
|
||||
// into hearing range within time?
|
||||
|
||||
// Only post the event if it's within audible range
|
||||
// of the control object.
|
||||
tempSoundAsset->getSfxDescription();
|
||||
Point3F ear, pos;
|
||||
transform->getColumn(3, &pos);
|
||||
mControlObject->getTransform().getColumn(3, &ear);
|
||||
if ((ear - pos).len() < tempSoundAsset->getSfxDescription()->mMaxDistance)
|
||||
postNetEvent(new SimSoundAssetEvent(tempSoundAsset, transform));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GameConnection::doneScopingScene()
|
||||
|
|
@ -2011,49 +2027,49 @@ DefineEngineMethod( GameConnection, isControlObjectRotDampedCamera, bool, (),,
|
|||
return object->isControlObjectRotDampedCamera();
|
||||
}
|
||||
|
||||
DefineEngineMethod( GameConnection, play2D, bool, (SFXProfile* profile),,
|
||||
DefineEngineMethod( GameConnection, play2D, bool, (StringTableEntry assetId),,
|
||||
"@brief Used on the server to play a 2D sound that is not attached to any object.\n\n"
|
||||
|
||||
"@param profile The SFXProfile that defines the sound to play.\n\n"
|
||||
"@param assetID The SoundAsset ID that defines the sound to play.\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"function ServerPlay2D(%profile)\n"
|
||||
"function ServerPlay2D(%assetId)\n"
|
||||
"{\n"
|
||||
" // Play the given sound profile on every client.\n"
|
||||
" // Play the given sound asset on every client.\n"
|
||||
" // The sounds will be transmitted as an event, not attached to any object.\n"
|
||||
" for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)\n"
|
||||
" ClientGroup.getObject(%idx).play2D(%profile);\n"
|
||||
" ClientGroup.getObject(%idx).play2D(%assetId);\n"
|
||||
"}\n"
|
||||
"@endtsexample\n\n")
|
||||
{
|
||||
if(!profile)
|
||||
if(assetId == StringTable->EmptyString())
|
||||
return false;
|
||||
|
||||
object->play2D(profile);
|
||||
object->play2D(assetId);
|
||||
return true;
|
||||
}
|
||||
|
||||
DefineEngineMethod( GameConnection, play3D, bool, (SFXProfile* profile, TransformF location),,
|
||||
DefineEngineMethod( GameConnection, play3D, bool, (StringTableEntry assetId, TransformF location),,
|
||||
"@brief Used on the server to play a 3D sound that is not attached to any object.\n\n"
|
||||
|
||||
"@param profile The SFXProfile that defines the sound to play.\n"
|
||||
"@param assetID The SoundAsset ID that defines the sound to play.\n"
|
||||
"@param location The position and orientation of the 3D sound given in the form of \"x y z ax ay az aa\".\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"function ServerPlay3D(%profile,%transform)\n"
|
||||
"function ServerPlay3D(%assetId,%transform)\n"
|
||||
"{\n"
|
||||
" // Play the given sound profile at the given position on every client\n"
|
||||
" // Play the given sound asset at the given position on every client\n"
|
||||
" // The sound will be transmitted as an event, not attached to any object.\n"
|
||||
" for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)\n"
|
||||
" ClientGroup.getObject(%idx).play3D(%profile,%transform);\n"
|
||||
" ClientGroup.getObject(%idx).play3D(%assetID,%transform);\n"
|
||||
"}\n"
|
||||
"@endtsexample\n\n")
|
||||
{
|
||||
if(!profile)
|
||||
if(assetId == StringTable->EmptyString())
|
||||
return false;
|
||||
|
||||
MatrixF mat = location.getMatrix();
|
||||
object->play3D(profile,&mat);
|
||||
object->play3D(assetId,&mat);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -352,8 +352,8 @@ public:
|
|||
/// @name Sound
|
||||
/// @{
|
||||
|
||||
void play2D(SFXProfile *profile);
|
||||
void play3D(SFXProfile *profile, const MatrixF *transform);
|
||||
void play2D(StringTableEntry assetId);
|
||||
void play3D(StringTableEntry assetId, const MatrixF *transform);
|
||||
/// @}
|
||||
|
||||
/// @name Misc.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
|
||||
//--------------------------------------------------------------------------
|
||||
IMPLEMENT_CO_CLIENTEVENT_V1(SimDataBlockEvent);
|
||||
IMPLEMENT_CO_CLIENTEVENT_V1(SimSoundAssetEvent);
|
||||
IMPLEMENT_CO_CLIENTEVENT_V1(Sim2DAudioEvent);
|
||||
IMPLEMENT_CO_CLIENTEVENT_V1(Sim3DAudioEvent);
|
||||
IMPLEMENT_CO_CLIENTEVENT_V1(SetMissionCRCEvent);
|
||||
|
|
@ -293,6 +294,104 @@ void SimDataBlockEvent::process(NetConnection *cptr)
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static F32 SoundPosAccuracy = 0.5;
|
||||
static S32 SoundRotBits = 8;
|
||||
|
||||
SimSoundAssetEvent::SimSoundAssetEvent(AssetPtr<SoundAsset> asset, const MatrixF* mat)
|
||||
{
|
||||
// cant get here unless the asset is declared.
|
||||
mAsset = asset;
|
||||
|
||||
if (mat)
|
||||
mTransform = *mat;
|
||||
}
|
||||
|
||||
void SimSoundAssetEvent::pack(NetConnection* con, BitStream* stream)
|
||||
{
|
||||
NetStringHandle assetIdStr = mAsset->getAssetId();
|
||||
con->packNetStringHandleU(stream, assetIdStr);
|
||||
|
||||
// only stream if this is a 3d sound asset.
|
||||
if (mAsset->is3D())
|
||||
{
|
||||
SFXDescription* ad = mAsset->getSfxDescription();
|
||||
if (stream->writeFlag(ad->mConeInsideAngle || ad->mConeOutsideAngle))
|
||||
{
|
||||
QuatF q(mTransform);
|
||||
q.normalize();
|
||||
|
||||
// LH - we can get a valid quat that's very slightly over 1 in and so
|
||||
// this fails (barely) check against zero. So use some error-
|
||||
AssertFatal((1.0 - ((q.x * q.x) + (q.y * q.y) + (q.z * q.z))) >= (0.0 - 0.001),
|
||||
"QuatF::normalize() is broken in Sim3DAudioEvent");
|
||||
|
||||
stream->writeSignedFloat(q.x, SoundRotBits);
|
||||
stream->writeSignedFloat(q.y, SoundRotBits);
|
||||
stream->writeSignedFloat(q.z, SoundRotBits);
|
||||
stream->writeFlag(q.w < 0.0);
|
||||
}
|
||||
|
||||
Point3F pos;
|
||||
mTransform.getColumn(3, &pos);
|
||||
stream->writeCompressedPoint(pos, SoundPosAccuracy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SimSoundAssetEvent::write(NetConnection* con, BitStream* stream)
|
||||
{
|
||||
// Just do the normal pack...
|
||||
pack(con, stream);
|
||||
}
|
||||
|
||||
void SimSoundAssetEvent::unpack(NetConnection* con, BitStream* stream)
|
||||
{
|
||||
|
||||
StringTableEntry temp = StringTable->insert(con->unpackNetStringHandleU(stream).getString());
|
||||
if (AssetDatabase.isDeclaredAsset(temp))
|
||||
{
|
||||
AssetPtr<SoundAsset> tempSoundAsset;
|
||||
tempSoundAsset = temp;
|
||||
|
||||
mAsset = temp;
|
||||
}
|
||||
|
||||
if (mAsset->is3D())
|
||||
{
|
||||
if (stream->readFlag()) {
|
||||
QuatF q;
|
||||
q.x = stream->readSignedFloat(SoundRotBits);
|
||||
q.y = stream->readSignedFloat(SoundRotBits);
|
||||
q.z = stream->readSignedFloat(SoundRotBits);
|
||||
F32 value = ((q.x * q.x) + (q.y * q.y) + (q.z * q.z));
|
||||
// #ifdef __linux
|
||||
// Hmm, this should never happen, but it does...
|
||||
if (value > 1.f)
|
||||
value = 1.f;
|
||||
// #endif
|
||||
q.w = mSqrt(1.f - value);
|
||||
if (stream->readFlag())
|
||||
q.w = -q.w;
|
||||
q.setMatrix(&mTransform);
|
||||
}
|
||||
else
|
||||
mTransform.identity();
|
||||
|
||||
Point3F pos;
|
||||
stream->readCompressedPoint(&pos, SoundPosAccuracy);
|
||||
mTransform.setColumn(3, pos);
|
||||
}
|
||||
}
|
||||
|
||||
void SimSoundAssetEvent::process(NetConnection* con)
|
||||
{
|
||||
|
||||
if (mAsset->is3D())
|
||||
SFX->playOnce(mAsset->getSfxProfile(), &mTransform);
|
||||
else
|
||||
SFX->playOnce(mAsset->getSfxProfile());
|
||||
|
||||
}
|
||||
|
||||
Sim2DAudioEvent::Sim2DAudioEvent(SFXProfile *profile)
|
||||
{
|
||||
|
|
@ -321,11 +420,6 @@ void Sim2DAudioEvent::process(NetConnection *)
|
|||
SFX->playOnce( mProfile );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static F32 SoundPosAccuracy = 0.5;
|
||||
static S32 SoundRotBits = 8;
|
||||
|
||||
Sim3DAudioEvent::Sim3DAudioEvent(SFXProfile *profile,const MatrixF* mat)
|
||||
{
|
||||
mProfile = profile;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@
|
|||
#include "core/stream/bitStream.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
|
||||
|
||||
class QuitEvent : public SimEvent
|
||||
{
|
||||
|
|
@ -102,6 +105,23 @@ class SimDataBlockEvent : public NetEvent
|
|||
DECLARE_CATEGORY( "Game Networking" );
|
||||
};
|
||||
|
||||
class SimSoundAssetEvent : public NetEvent
|
||||
{
|
||||
private:
|
||||
AssetPtr<SoundAsset> mAsset;
|
||||
MatrixF mTransform;
|
||||
|
||||
public:
|
||||
typedef NetEvent Parent;
|
||||
|
||||
SimSoundAssetEvent(AssetPtr<SoundAsset> asset = NULL, const MatrixF* mat = NULL);
|
||||
void pack(NetConnection*, BitStream* bstream);
|
||||
void write(NetConnection*, BitStream* bstream);
|
||||
void unpack(NetConnection*, BitStream* bstream);
|
||||
void process(NetConnection*);
|
||||
DECLARE_CONOBJECT(SimSoundAssetEvent);
|
||||
};
|
||||
|
||||
class Sim2DAudioEvent: public NetEvent
|
||||
{
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ MODULE_BEGIN( 3D )
|
|||
|
||||
MODULE_SHUTDOWN_BEFORE( Process )
|
||||
MODULE_SHUTDOWN_BEFORE( Sim )
|
||||
MODULE_SHUTDOWN_AFTER( Scene )
|
||||
MODULE_SHUTDOWN_BEFORE( Scene )
|
||||
|
||||
MODULE_INIT
|
||||
{
|
||||
|
|
@ -668,6 +668,7 @@ static void RegisterGameFunctions()
|
|||
// PATHSHAPE
|
||||
Con::setIntVariable("$TypeMasks::PathShapeObjectType", PathShapeObjectType);
|
||||
// PATHSHAPE END
|
||||
Con::setIntVariable("$TypeMasks::TurretObjectType", TurretObjectType);
|
||||
|
||||
Con::addVariable("Ease::InOut", TypeS32, &gEaseInOut,
|
||||
"InOut ease for curve movement.\n"
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ GroundPlane::GroundPlane()
|
|||
mConvexList = new Convex;
|
||||
mTypeMask |= TerrainLikeObjectType;
|
||||
|
||||
INIT_MATERIALASSET(Material);
|
||||
INIT_ASSET(Material);
|
||||
}
|
||||
|
||||
GroundPlane::~GroundPlane()
|
||||
|
|
@ -199,7 +199,7 @@ U32 GroundPlane::packUpdate( NetConnection* connection, U32 mask, BitStream* str
|
|||
stream->write( mScaleU );
|
||||
stream->write( mScaleV );
|
||||
|
||||
PACK_MATERIALASSET(connection, Material);
|
||||
PACK_ASSET(connection, Material);
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
|
@ -212,7 +212,7 @@ void GroundPlane::unpackUpdate( NetConnection* connection, BitStream* stream )
|
|||
stream->read( &mScaleU );
|
||||
stream->read( &mScaleV );
|
||||
|
||||
UNPACK_MATERIALASSET(connection, Material);
|
||||
UNPACK_ASSET(connection, Material);
|
||||
|
||||
// If we're added then something possibly changed in
|
||||
// the editor... do an update of the material and the
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ private:
|
|||
BaseMatInstance* mMaterialInst;
|
||||
|
||||
DECLARE_MATERIALASSET(GroundPlane, Material);
|
||||
DECLARE_MATERIALASSET_NET_SETGET(GroundPlane, Material, -1);
|
||||
DECLARE_ASSET_NET_SETGET(GroundPlane, Material, -1);
|
||||
|
||||
PhysicsBody *mPhysicsRep;
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ extern F32 gDecalBias;
|
|||
extern GFXTexHandle gLevelAccuMap;
|
||||
|
||||
/// Default SFXAmbience used to reset the global soundscape.
|
||||
static SFXAmbience sDefaultAmbience;
|
||||
extern SFXAmbience* sDefaultAmbience;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -99,7 +99,7 @@ LevelInfo::LevelInfo()
|
|||
|
||||
mAdvancedLightmapSupport = true;
|
||||
|
||||
INIT_IMAGEASSET(AccuTexture);
|
||||
INIT_ASSET(AccuTexture);
|
||||
|
||||
// Register with the light manager activation signal, and we need to do it first
|
||||
// so the advanced light bin manager can be instructed about MRT lightmaps
|
||||
|
|
@ -215,7 +215,7 @@ U32 LevelInfo::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
|
|||
sfxWrite( stream, mSoundAmbience );
|
||||
stream->writeInt( mSoundDistanceModel, 1 );
|
||||
|
||||
PACK_IMAGEASSET(conn, AccuTexture);
|
||||
PACK_ASSET(conn, AccuTexture);
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
|
@ -256,13 +256,13 @@ void LevelInfo::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
if( mSoundAmbience )
|
||||
mSoundscape->setAmbience( mSoundAmbience );
|
||||
else
|
||||
mSoundscape->setAmbience( &sDefaultAmbience );
|
||||
mSoundscape->setAmbience( sDefaultAmbience );
|
||||
}
|
||||
|
||||
SFX->setDistanceModel( mSoundDistanceModel );
|
||||
}
|
||||
|
||||
UNPACK_IMAGEASSET(conn, AccuTexture);
|
||||
UNPACK_ASSET(conn, AccuTexture);
|
||||
setLevelAccuTexture(getAccuTexture());
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +302,7 @@ bool LevelInfo::onAdd()
|
|||
void LevelInfo::onRemove()
|
||||
{
|
||||
if( mSoundscape )
|
||||
mSoundscape->setAmbience( &sDefaultAmbience );
|
||||
mSoundscape->setAmbience( sDefaultAmbience );
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ class LevelInfo : public NetObject
|
|||
protected:
|
||||
|
||||
DECLARE_IMAGEASSET(LevelInfo, AccuTexture, onAccuTextureChanged, GFXStaticTextureSRGBProfile);
|
||||
DECLARE_IMAGEASSET_SETGET(LevelInfo, AccuTexture);
|
||||
DECLARE_ASSET_SETGET(LevelInfo, AccuTexture);
|
||||
|
||||
void onAccuTextureChanged() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ LightFlareData::LightFlareData()
|
|||
for ( U32 i = 0; i < MAX_ELEMENTS; i++ )
|
||||
mElementDist[i] = -1.0f;
|
||||
|
||||
INIT_IMAGEASSET(FlareTexture);
|
||||
INIT_ASSET(FlareTexture);
|
||||
}
|
||||
|
||||
LightFlareData::~LightFlareData()
|
||||
|
|
@ -219,7 +219,7 @@ void LightFlareData::packData( BitStream *stream )
|
|||
|
||||
stream->writeFlag( mFlareEnabled );
|
||||
|
||||
PACKDATA_IMAGEASSET(FlareTexture);
|
||||
PACKDATA_ASSET(FlareTexture);
|
||||
|
||||
stream->write( mScale );
|
||||
stream->write( mOcclusionRadius );
|
||||
|
|
@ -244,7 +244,7 @@ void LightFlareData::unpackData( BitStream *stream )
|
|||
|
||||
mFlareEnabled = stream->readFlag();
|
||||
|
||||
UNPACKDATA_IMAGEASSET(FlareTexture);
|
||||
UNPACKDATA_ASSET(FlareTexture);
|
||||
|
||||
stream->read( &mScale );
|
||||
stream->read( &mOcclusionRadius );
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ protected:
|
|||
bool mFlareEnabled;
|
||||
|
||||
DECLARE_IMAGEASSET(LightFlareData, FlareTexture, onImageChanged, GFXStaticTextureSRGBProfile);
|
||||
DECLARE_IMAGEASSET_SETGET(LightFlareData, FlareTexture);
|
||||
DECLARE_ASSET_SETGET(LightFlareData, FlareTexture);
|
||||
|
||||
F32 mOcclusionRadius;
|
||||
bool mRenderReflectPass;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ namespace IBLUtilities
|
|||
}
|
||||
|
||||
GFXShaderConstBufferRef irrConsts = irrShader->allocConstBuffer();
|
||||
GFXShaderConstHandle* irrEnvMapSC = irrShader->getShaderConstHandle("$environmentMap");
|
||||
GFXShaderConstHandle* irrFaceSC = irrShader->getShaderConstHandle("$face");
|
||||
|
||||
GFXStateBlockDesc desc;
|
||||
|
|
@ -132,7 +131,6 @@ namespace IBLUtilities
|
|||
}
|
||||
|
||||
GFXShaderConstBufferRef prefilterConsts = prefilterShader->allocConstBuffer();
|
||||
GFXShaderConstHandle* prefilterEnvMapSC = prefilterShader->getShaderConstHandle("$environmentMap");
|
||||
GFXShaderConstHandle* prefilterFaceSC = prefilterShader->getShaderConstHandle("$face");
|
||||
GFXShaderConstHandle* prefilterRoughnessSC = prefilterShader->getShaderConstHandle("$roughness");
|
||||
GFXShaderConstHandle* prefilterMipSizeSC = prefilterShader->getShaderConstHandle("$mipSize");
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ ConsoleDocClass(BoxEnvironmentProbe,
|
|||
BoxEnvironmentProbe::BoxEnvironmentProbe() : ReflectionProbe()
|
||||
{
|
||||
mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK;
|
||||
mProbeShapeType = ProbeRenderInst::Box;
|
||||
mProbeShapeType = ProbeInfo::Box;
|
||||
mAtten = 0.0;
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ void BoxEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
|
||||
void BoxEnvironmentProbe::updateProbeParams()
|
||||
{
|
||||
mProbeShapeType = ProbeRenderInst::Box;
|
||||
mProbeShapeType = ProbeInfo::Box;
|
||||
mProbeInfo.mAtten = mAtten;
|
||||
|
||||
Parent::updateProbeParams();
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ ConsoleDocClass(ReflectionProbe,
|
|||
ImplementEnumType(ReflectProbeType,
|
||||
"Type of mesh data available in a shape.\n"
|
||||
"@ingroup gameObjects")
|
||||
{ ProbeRenderInst::Sphere, "Sphere", "Sphere shaped" },
|
||||
{ ProbeRenderInst::Box, "Box", "Box shape" }
|
||||
{ ReflectionProbe::ProbeInfo::Sphere, "Sphere", "Sphere shaped" },
|
||||
{ ReflectionProbe::ProbeInfo::Box, "Box", "Box shape" }
|
||||
EndImplementEnumType;
|
||||
|
||||
ImplementEnumType(ReflectionModeEnum,
|
||||
|
|
@ -97,7 +97,7 @@ ReflectionProbe::ReflectionProbe()
|
|||
|
||||
mTypeMask = LightObjectType | MarkerObjectType;
|
||||
|
||||
mProbeShapeType = ProbeRenderInst::Box;
|
||||
mProbeShapeType = ProbeInfo::Box;
|
||||
|
||||
mReflectionModeType = BakedCubemap;
|
||||
|
||||
|
|
@ -121,8 +121,6 @@ ReflectionProbe::ReflectionProbe()
|
|||
mRefreshRateMS = 200;
|
||||
mDynamicLastBakeMS = 0;
|
||||
|
||||
mMaxDrawDistance = 75;
|
||||
|
||||
mResourcesCreated = false;
|
||||
mPrefilterSize = 64;
|
||||
mPrefilterMipLevels = mLog2(F32(mPrefilterSize));
|
||||
|
|
@ -239,7 +237,7 @@ bool ReflectionProbe::_setRadius(void *object, const char *index, const char *da
|
|||
{
|
||||
ReflectionProbe* probe = reinterpret_cast<ReflectionProbe*>(object);
|
||||
|
||||
if (probe->mProbeShapeType != ProbeRenderInst::Sphere)
|
||||
if (probe->mProbeShapeType != ProbeInfo::Sphere)
|
||||
return false;
|
||||
|
||||
probe->mObjScale = Point3F(probe->mRadius, probe->mRadius, probe->mRadius);
|
||||
|
|
@ -291,7 +289,7 @@ bool ReflectionProbe::onAdd()
|
|||
if (!mPersistentId)
|
||||
mPersistentId = getOrCreatePersistentId();
|
||||
|
||||
mProbeUniqueID = String::ToString(mPersistentId->getUUID().getHash());
|
||||
mProbeUniqueID = mPersistentId->getUUID().toString();
|
||||
}
|
||||
|
||||
// Refresh this object's material (if any)
|
||||
|
|
@ -312,7 +310,7 @@ void ReflectionProbe::onRemove()
|
|||
{
|
||||
if (isClientObject())
|
||||
{
|
||||
PROBEMGR->unregisterProbe(mProbeInfo.mProbeIdx);
|
||||
PROBEMGR->unregisterProbe(&mProbeInfo);
|
||||
}
|
||||
|
||||
// Remove this object from the scene
|
||||
|
|
@ -461,10 +459,10 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
|
||||
if (stream->readFlag()) // StaticDataMask
|
||||
{
|
||||
U32 shapeType = ProbeRenderInst::Sphere;
|
||||
U32 shapeType = ProbeInfo::Sphere;
|
||||
stream->read(&shapeType);
|
||||
|
||||
mProbeShapeType = (ProbeRenderInst::ProbeShapeType)shapeType;
|
||||
mProbeShapeType = (ProbeInfo::ProbeShapeType)shapeType;
|
||||
|
||||
stream->read(&mRadius);
|
||||
|
||||
|
|
@ -497,6 +495,8 @@ void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
//-----------------------------------------------------------------------------
|
||||
void ReflectionProbe::updateProbeParams()
|
||||
{
|
||||
mProbeInfo.mObject = this;
|
||||
|
||||
if (!mResourcesCreated)
|
||||
{
|
||||
if (!createClientResources())
|
||||
|
|
@ -507,12 +507,12 @@ void ReflectionProbe::updateProbeParams()
|
|||
|
||||
mProbeInfo.mProbeShapeType = mProbeShapeType;
|
||||
|
||||
if (mProbeShapeType == ProbeRenderInst::Sphere)
|
||||
if (mProbeShapeType == ProbeInfo::Sphere)
|
||||
mObjScale.set(mRadius, mRadius, mRadius);
|
||||
|
||||
Box3F bounds;
|
||||
|
||||
if (mProbeShapeType == ProbeRenderInst::Skylight)
|
||||
if (mProbeShapeType == ProbeInfo::Skylight)
|
||||
{
|
||||
mProbeInfo.mPosition = Point3F::Zero;
|
||||
mProbeInfo.mTransform = MatrixF::Identity;
|
||||
|
|
@ -564,8 +564,6 @@ void ReflectionProbe::updateProbeParams()
|
|||
else
|
||||
processDynamicCubemap();
|
||||
}
|
||||
|
||||
PROBEMGR->updateProbes();
|
||||
}
|
||||
|
||||
void ReflectionProbe::processDynamicCubemap()
|
||||
|
|
@ -575,7 +573,7 @@ void ReflectionProbe::processDynamicCubemap()
|
|||
|
||||
void ReflectionProbe::processBakedCubemap()
|
||||
{
|
||||
mProbeInfo.mIsEnabled = false;
|
||||
//mProbeInfo.mIsEnabled = false;
|
||||
|
||||
if ((mReflectionModeType != BakedCubemap) || mProbeUniqueID.isEmpty())
|
||||
return;
|
||||
|
|
@ -611,7 +609,7 @@ void ReflectionProbe::processBakedCubemap()
|
|||
|
||||
if (mEnabled && mProbeInfo.mPrefilterCubemap->isInitialized() && mProbeInfo.mIrradianceCubemap->isInitialized())
|
||||
{
|
||||
mProbeInfo.mIsEnabled = true;
|
||||
//mProbeInfo.mIsEnabled = true;
|
||||
|
||||
mCubemapDirty = false;
|
||||
|
||||
|
|
@ -622,6 +620,11 @@ void ReflectionProbe::processBakedCubemap()
|
|||
mProbeInfo.mPrefilterCubemap.free();
|
||||
mProbeInfo.mIrradianceCubemap.free();
|
||||
}
|
||||
else
|
||||
{
|
||||
//if we failed, disable
|
||||
mProbeInfo.mIsEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectionProbe::processStaticCubemap()
|
||||
|
|
@ -798,7 +801,7 @@ void ReflectionProbe::createEditorResources()
|
|||
|
||||
mEditorShape = NULL;
|
||||
|
||||
String shapeFile = "tools/resources/ReflectProbeSphere.dae";
|
||||
String shapeFile = "tools/resources/previewSphereShape.dae";
|
||||
|
||||
// Attempt to get the resource from the ResourceManager
|
||||
mEditorShape = ResourceManager::get().load(shapeFile);
|
||||
|
|
@ -811,16 +814,16 @@ void ReflectionProbe::createEditorResources()
|
|||
|
||||
void ReflectionProbe::prepRenderImage(SceneRenderState *state)
|
||||
{
|
||||
if (!mEnabled || !RenderProbeMgr::smRenderReflectionProbes)
|
||||
if (!mEnabled || (!RenderProbeMgr::smRenderReflectionProbes && Con::getVariable("$Probes::Capturing", "0") == "0"))
|
||||
return;
|
||||
|
||||
Point3F distVec = getRenderPosition() - state->getCameraPosition();
|
||||
F32 dist = distVec.len();
|
||||
|
||||
//Culling distance. Can be adjusted for performance options considerations via the scalar
|
||||
if (dist > mMaxDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0))
|
||||
if (dist > RenderProbeMgr::smMaxProbeDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0))
|
||||
{
|
||||
mProbeInfo.mScore = mMaxDrawDistance;
|
||||
mProbeInfo.mScore = RenderProbeMgr::smMaxProbeDrawDistance;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -842,7 +845,7 @@ void ReflectionProbe::prepRenderImage(SceneRenderState *state)
|
|||
|
||||
//mProbeInfo.mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f);
|
||||
|
||||
PROBEMGR->submitProbe(mProbeInfo);
|
||||
PROBEMGR->submitProbe(&mProbeInfo);
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mPrefilterMap != nullptr)
|
||||
|
|
@ -938,7 +941,7 @@ void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
|
|||
ColorI color = ColorI(255, 0, 255, 63);
|
||||
|
||||
const MatrixF worldToObjectXfm = mObjToWorld;
|
||||
if (mProbeShapeType == ProbeRenderInst::Sphere)
|
||||
if (mProbeShapeType == ProbeInfo::Sphere)
|
||||
{
|
||||
draw->drawSphere(desc, mRadius, getPosition(), color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,10 +41,6 @@
|
|||
#include "renderInstance/renderPassManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef RENDER_PROBE_MGR_H
|
||||
#include "renderInstance/renderProbeMgr.h"
|
||||
#endif
|
||||
|
||||
class BaseMatInstance;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -74,6 +70,67 @@ public:
|
|||
DynamicCubemap = 5,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// This contains all the important data the Probe uses for rendering.
|
||||
/// </summary>
|
||||
struct ProbeInfo
|
||||
{
|
||||
bool mIsEnabled;
|
||||
|
||||
MatrixF mTransform;
|
||||
|
||||
ReflectionProbe* mObject;
|
||||
|
||||
F32 mRadius;
|
||||
|
||||
bool mDirty;
|
||||
|
||||
Box3F mBounds;
|
||||
Point3F mExtents;
|
||||
Point3F mPosition;
|
||||
Point3F mProbeRefOffset;
|
||||
Point3F mProbeRefScale;
|
||||
F32 mAtten;
|
||||
|
||||
F32 mScore;
|
||||
|
||||
GFXCubemapHandle mPrefilterCubemap;
|
||||
GFXCubemapHandle mIrradianceCubemap;
|
||||
|
||||
/// The priority of this light used for
|
||||
/// light and shadow scoring.
|
||||
F32 mPriority;
|
||||
|
||||
enum ProbeShapeType
|
||||
{
|
||||
Box = 0,
|
||||
Sphere = 1,
|
||||
Skylight = 2
|
||||
};
|
||||
|
||||
ProbeShapeType mProbeShapeType;
|
||||
|
||||
public:
|
||||
|
||||
ProbeInfo() : mScore(0) {}
|
||||
~ProbeInfo() {}
|
||||
|
||||
// Copies data passed in from light
|
||||
void set(const ProbeInfo* probeInfo);
|
||||
|
||||
// Accessors
|
||||
const MatrixF& getTransform() const { return mTransform; }
|
||||
void setTransform(const MatrixF& xfm) { mTransform = xfm; }
|
||||
|
||||
Point3F getPosition() const { return mPosition; }
|
||||
void setPosition(const Point3F& pos) { mPosition = pos; }
|
||||
|
||||
void setPriority(F32 priority) { mPriority = priority; }
|
||||
F32 getPriority() const { return mPriority; }
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
// Networking masks
|
||||
|
|
@ -124,7 +181,7 @@ protected:
|
|||
/// <summary>
|
||||
/// The shape of the probe
|
||||
/// </summary>
|
||||
ProbeRenderInst::ProbeShapeType mProbeShapeType;
|
||||
ProbeInfo::ProbeShapeType mProbeShapeType;
|
||||
|
||||
/// <summary>
|
||||
/// This is effectively a packed cache of the probe data actually utilized for rendering.
|
||||
|
|
@ -132,7 +189,7 @@ protected:
|
|||
/// When the manager goes to render it has the compacted data to read over more efficiently for setting up what probes should
|
||||
/// Actually render in that frame
|
||||
/// </summary>
|
||||
ProbeRenderInst mProbeInfo;
|
||||
ProbeInfo mProbeInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Used to dictate what sort of cubemap the probes use when using IBL
|
||||
|
|
@ -166,14 +223,13 @@ protected:
|
|||
CubemapData *mStaticCubemap;
|
||||
GFXCubemapHandle mDynamicCubemap;
|
||||
|
||||
String cubeDescName;
|
||||
U32 cubeDescId;
|
||||
ReflectorDesc *reflectorDesc;
|
||||
//String cubeDescName;
|
||||
//U32 cubeDescId;
|
||||
//ReflectorDesc *reflectorDesc;
|
||||
|
||||
//Utilized in dynamic reflections
|
||||
//CubeReflector mCubeReflector;
|
||||
|
||||
///Prevents us from saving out the cubemaps(for now) but allows us the full HDR range on the in-memory cubemap captures
|
||||
bool mUseHDRCaptures;
|
||||
|
||||
//irridiance resources
|
||||
|
|
@ -196,7 +252,6 @@ protected:
|
|||
U32 mDynamicLastBakeMS;
|
||||
U32 mRefreshRateMS;
|
||||
|
||||
F32 mMaxDrawDistance;
|
||||
|
||||
bool mResourcesCreated;
|
||||
U32 mCaptureMask;
|
||||
|
|
@ -313,7 +368,7 @@ public:
|
|||
void bake();
|
||||
};
|
||||
|
||||
typedef ProbeRenderInst::ProbeShapeType ReflectProbeType;
|
||||
typedef ReflectionProbe::ProbeInfo::ProbeShapeType ReflectProbeType;
|
||||
DefineEnumType(ReflectProbeType);
|
||||
|
||||
typedef ReflectionProbe::ReflectionModeType ReflectionModeEnum;
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ void Skylight::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
|
||||
void Skylight::updateProbeParams()
|
||||
{
|
||||
mProbeShapeType = ProbeRenderInst::Skylight;
|
||||
mProbeShapeType = ProbeInfo::Skylight;
|
||||
Parent::updateProbeParams();
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ void Skylight::prepRenderImage(SceneRenderState *state)
|
|||
// Get a handy pointer to our RenderPassmanager
|
||||
//RenderPassManager *renderPass = state->getRenderPass();
|
||||
|
||||
PROBEMGR->submitProbe(mProbeInfo);
|
||||
PROBEMGR->submitProbe(&mProbeInfo);
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
if (Skylight::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ ConsoleDocClass(SphereEnvironmentProbe,
|
|||
SphereEnvironmentProbe::SphereEnvironmentProbe() : ReflectionProbe()
|
||||
{
|
||||
mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK;
|
||||
mProbeShapeType = ProbeRenderInst::Sphere;
|
||||
mProbeShapeType = ProbeInfo::Sphere;
|
||||
}
|
||||
|
||||
SphereEnvironmentProbe::~SphereEnvironmentProbe()
|
||||
|
|
@ -144,83 +144,10 @@ void SphereEnvironmentProbe::unpackUpdate(NetConnection *conn, BitStream *stream
|
|||
|
||||
void SphereEnvironmentProbe::updateProbeParams()
|
||||
{
|
||||
mProbeShapeType = ProbeRenderInst::Sphere;
|
||||
mProbeShapeType = ProbeInfo::Sphere;
|
||||
Parent::updateProbeParams();
|
||||
}
|
||||
|
||||
void SphereEnvironmentProbe::prepRenderImage(SceneRenderState *state)
|
||||
{
|
||||
if (!mEnabled || !ReflectionProbe::smRenderPreviewProbes)
|
||||
return;
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
|
||||
{
|
||||
GFXTransformSaver saver;
|
||||
|
||||
// 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));
|
||||
|
||||
mEditorShapeInst->setDetailFromDistance(state, dist * invScale);
|
||||
|
||||
// Make sure we have a valid level of detail
|
||||
if (mEditorShapeInst->getCurrentDetail() < 0)
|
||||
return;
|
||||
|
||||
BaseMatInstance* probePrevMat = mEditorShapeInst->getMaterialList()->getMaterialInst(0);
|
||||
|
||||
setPreviewMatParameters(state, probePrevMat);
|
||||
|
||||
// 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
|
||||
|
||||
// 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(Point3F(1, 1, 1));
|
||||
GFX->setWorldMatrix(mat);
|
||||
|
||||
// Animate the the shape
|
||||
mEditorShapeInst->animate();
|
||||
|
||||
// Allow the shape to submit the RenderInst(s) for itself
|
||||
mEditorShapeInst->render(rdata);
|
||||
|
||||
saver.restore();
|
||||
}
|
||||
|
||||
// If the light is selected or light visualization
|
||||
// is enabled then register the callback.
|
||||
const bool isSelectedInEditor = (gEditingMission && isSelected());
|
||||
if (isSelectedInEditor)
|
||||
{
|
||||
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
|
||||
ri->renderDelegate.bind(this, &ReflectionProbe::_onRenderViz);
|
||||
ri->type = RenderPassManager::RIT_Editor;
|
||||
state->getRenderPass()->addInst(ri);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SphereEnvironmentProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
|
||||
{
|
||||
Parent::setPreviewMatParameters(renderState, mat);
|
||||
|
|
|
|||
|
|
@ -98,10 +98,6 @@ public:
|
|||
// use the same Materials.
|
||||
//--------------------------------------------------------------------------
|
||||
virtual void updateProbeParams();
|
||||
|
||||
// This is the function that allows this object to submit itself for rendering
|
||||
void prepRenderImage(SceneRenderState *state);
|
||||
|
||||
void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -433,7 +433,23 @@ void SpawnSphere::unpackUpdate(NetConnection * con, BitStream * stream)
|
|||
mSpawnTransform = stream->readFlag();
|
||||
|
||||
stream->read(&mSpawnClass);
|
||||
|
||||
String oldSDB = mSpawnDataBlock;
|
||||
stream->read(&mSpawnDataBlock);
|
||||
if (oldSDB != mSpawnDataBlock)
|
||||
{
|
||||
delete mShapeInstance;
|
||||
ShapeBaseData *spawnedDatablock = dynamic_cast<ShapeBaseData *>(Sim::findObject(mSpawnDataBlock.c_str()));
|
||||
if (spawnedDatablock && spawnedDatablock->mShape)
|
||||
{
|
||||
mShapeInstance = new TSShapeInstance(spawnedDatablock->mShape);
|
||||
}
|
||||
else if (mDataBlock)
|
||||
{
|
||||
if (mDataBlock->mShape)
|
||||
mShapeInstance = new TSShapeInstance(mDataBlock->mShape);
|
||||
}
|
||||
}
|
||||
stream->read(&mSpawnName);
|
||||
stream->read(&mSpawnProperties);
|
||||
stream->read(&mSpawnScript);
|
||||
|
|
|
|||
|
|
@ -167,6 +167,10 @@ enum SceneObjectTypes
|
|||
PathShapeObjectType = BIT( 28 ),
|
||||
// PATHSHAPE END
|
||||
|
||||
/// A turret object.
|
||||
/// @see TurretShape
|
||||
TurretObjectType = BIT(29),
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
|
@ -225,7 +229,7 @@ enum SceneObjectTypeMasks : U32
|
|||
EnvironmentObjectType ),
|
||||
|
||||
SKYLIGHT_CAPTURE_TYPEMASK = (EnvironmentObjectType),
|
||||
REFLECTION_PROBE_CAPTURE_TYPEMASK = (StaticObjectType | StaticShapeObjectType)
|
||||
REFLECTION_PROBE_CAPTURE_TYPEMASK = (StaticObjectType | StaticShapeObjectType | LightObjectType)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -114,6 +114,13 @@ PhysicalZone::PhysicalZone()
|
|||
force_mag = 0.0f;
|
||||
orient_force = false;
|
||||
fade_amt = 1.0f;
|
||||
|
||||
//Default up a basic square
|
||||
Point3F vecs[3] = { Point3F(1.0, 0.0, 0.0),
|
||||
Point3F(0.0, -1.0, 0.0),
|
||||
Point3F(0.0, 0.0, 1.0) };
|
||||
|
||||
mPolyhedron = Polyhedron(Point3F(-0.5, 0.5, 0.0), vecs);
|
||||
}
|
||||
|
||||
PhysicalZone::~PhysicalZone()
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ PhysicsDebrisData::PhysicsDebrisData()
|
|||
lifetime = 5.0f;
|
||||
lifetimeVariance = 0.0f;
|
||||
|
||||
INIT_SHAPEASSET(Shape);
|
||||
INIT_ASSET(Shape);
|
||||
}
|
||||
|
||||
bool PhysicsDebrisData::onAdd()
|
||||
|
|
@ -215,7 +215,7 @@ void PhysicsDebrisData::packData(BitStream* stream)
|
|||
stream->write( waterDampingScale );
|
||||
stream->write( buoyancyDensity );
|
||||
|
||||
PACKDATA_SHAPEASSET(Shape);
|
||||
PACKDATA_ASSET(Shape);
|
||||
}
|
||||
|
||||
void PhysicsDebrisData::unpackData(BitStream* stream)
|
||||
|
|
@ -236,7 +236,7 @@ void PhysicsDebrisData::unpackData(BitStream* stream)
|
|||
stream->read( &waterDampingScale );
|
||||
stream->read( &buoyancyDensity );
|
||||
|
||||
UNPACKDATA_SHAPEASSET(Shape);
|
||||
UNPACKDATA_ASSET(Shape);
|
||||
}
|
||||
|
||||
DefineEngineMethod( PhysicsDebrisData, preload, void, (), ,
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ public:
|
|||
bool castShadows;
|
||||
|
||||
DECLARE_SHAPEASSET(PhysicsDebrisData, Shape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(PhysicsDebrisData, Shape);
|
||||
DECLARE_ASSET_SETGET(PhysicsDebrisData, Shape);
|
||||
|
||||
PhysicsDebrisData();
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ PhysicsShapeData::PhysicsShapeData()
|
|||
buoyancyDensity( 0.0f ),
|
||||
simType( SimType_ClientServer )
|
||||
{
|
||||
INIT_SHAPEASSET(Shape);
|
||||
INIT_ASSET(Shape);
|
||||
}
|
||||
|
||||
PhysicsShapeData::~PhysicsShapeData()
|
||||
|
|
@ -180,7 +180,7 @@ void PhysicsShapeData::packData( BitStream *stream )
|
|||
{
|
||||
Parent::packData( stream );
|
||||
|
||||
PACKDATA_SHAPEASSET(Shape);
|
||||
PACKDATA_ASSET(Shape);
|
||||
|
||||
stream->write( mass );
|
||||
stream->write( dynamicFriction );
|
||||
|
|
@ -204,7 +204,7 @@ void PhysicsShapeData::unpackData( BitStream *stream )
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_SHAPEASSET(Shape);
|
||||
UNPACKDATA_ASSET(Shape);
|
||||
|
||||
stream->read( &mass );
|
||||
stream->read( &dynamicFriction );
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public:
|
|||
public:
|
||||
|
||||
DECLARE_SHAPEASSET(PhysicsShapeData, Shape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(PhysicsShapeData, Shape);
|
||||
DECLARE_ASSET_SETGET(PhysicsShapeData, Shape);
|
||||
|
||||
/// The shared unscaled collision shape.
|
||||
PhysicsCollisionRef colShape;
|
||||
|
|
|
|||
|
|
@ -187,6 +187,32 @@ PlayerData::ActionAnimationDef PlayerData::ActionAnimationList[NumTableActionAni
|
|||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
typedef PlayerData::Sounds playerSoundsEnum;
|
||||
DefineEnumType(playerSoundsEnum);
|
||||
|
||||
ImplementEnumType(playerSoundsEnum, "enum types.\n"
|
||||
"@ingroup PlayerData\n\n")
|
||||
{ playerSoundsEnum::FootSoft, "FootSoft", "..." },
|
||||
{ playerSoundsEnum::FootHard, "FootHard","..." },
|
||||
{ playerSoundsEnum::FootMetal, "FootMetal","..." },
|
||||
{ playerSoundsEnum::FootSnow, "FootSnow","..." },
|
||||
{ playerSoundsEnum::FootShallowSplash, "FootShallowSplash","..." },
|
||||
{ playerSoundsEnum::FootWading, "FootWading","..." },
|
||||
{ playerSoundsEnum::FootUnderWater, "FootUnderWater","..." },
|
||||
{ playerSoundsEnum::FootBubbles, "FootBubbles","..." },
|
||||
{ playerSoundsEnum::MoveBubbles, "MoveBubbles","..." },
|
||||
{ playerSoundsEnum::WaterBreath, "WaterBreath","..." },
|
||||
{ playerSoundsEnum::ImpactSoft, "ImpactSoft","..." },
|
||||
{ playerSoundsEnum::ImpactHard, "ImpactHard","..." },
|
||||
{ playerSoundsEnum::ImpactMetal, "ImpactMetal","..." },
|
||||
{ playerSoundsEnum::ImpactSnow, "ImpactSnow","..." },
|
||||
{ playerSoundsEnum::ImpactWaterEasy, "ImpactWaterEasy","..." },
|
||||
{ playerSoundsEnum::ImpactWaterMedium, "ImpactWaterMedium","..." },
|
||||
{ playerSoundsEnum::ImpactWaterHard, "ImpactWaterHard","..." },
|
||||
{ playerSoundsEnum::ExitWater, "ExitWater","..." },
|
||||
EndImplementEnumType;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -272,7 +298,7 @@ PlayerData::PlayerData()
|
|||
imageAnimPrefixFP = StringTable->EmptyString();
|
||||
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
||||
{
|
||||
INIT_SHAPEASSET_ARRAY(ShapeFP, i);
|
||||
INIT_ASSET_ARRAY(ShapeFP, i);
|
||||
mCRCFP[i] = 0;
|
||||
mValidShapeFP[i] = false;
|
||||
}
|
||||
|
|
@ -397,7 +423,7 @@ PlayerData::PlayerData()
|
|||
boxHeadFrontPercentage = 1;
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
sound[i] = NULL;
|
||||
INIT_ASSET_ARRAY(PlayerSound, i);
|
||||
|
||||
footPuffEmitter = NULL;
|
||||
footPuffID = 0;
|
||||
|
|
@ -444,14 +470,13 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
if(!Parent::preload(server, errorStr))
|
||||
return false;
|
||||
|
||||
// Resolve objects transmitted from server
|
||||
if( !server )
|
||||
for (U32 i = 0; i < MaxSounds; ++i)
|
||||
{
|
||||
for( U32 i = 0; i < MaxSounds; ++ i )
|
||||
_setPlayerSound(getPlayerSound(i), i);
|
||||
if (getPlayerSound(i) != StringTable->EmptyString())
|
||||
{
|
||||
String sfxErrorStr;
|
||||
if( !sfxResolve( &sound[ i ], sfxErrorStr ) )
|
||||
Con::errorf( "PlayerData::preload: %s", sfxErrorStr.c_str() );
|
||||
if (!getPlayerSoundProfile(i))
|
||||
Con::errorf("PlayerData::Preload() - unable to find sfxProfile for asset %d %s", i, mPlayerSoundAssetId[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1021,65 +1046,7 @@ void PlayerData::initPersistFields()
|
|||
endGroup( "Interaction: Footsteps" );
|
||||
|
||||
addGroup( "Interaction: Sounds" );
|
||||
|
||||
addField( "FootSoftSound", TypeSFXTrackName, Offset(sound[FootSoft], PlayerData),
|
||||
"@brief Sound to play when walking on a surface with Material footstepSoundId 0.\n\n" );
|
||||
addField( "FootHardSound", TypeSFXTrackName, Offset(sound[FootHard], PlayerData),
|
||||
"@brief Sound to play when walking on a surface with Material footstepSoundId 1.\n\n" );
|
||||
addField( "FootMetalSound", TypeSFXTrackName, Offset(sound[FootMetal], PlayerData),
|
||||
"@brief Sound to play when walking on a surface with Material footstepSoundId 2.\n\n" );
|
||||
addField( "FootSnowSound", TypeSFXTrackName, Offset(sound[FootSnow], PlayerData),
|
||||
"@brief Sound to play when walking on a surface with Material footstepSoundId 3.\n\n" );
|
||||
|
||||
addField( "FootShallowSound", TypeSFXTrackName, Offset(sound[FootShallowSplash], PlayerData),
|
||||
"@brief Sound to play when walking in water and coverage is less than "
|
||||
"footSplashHeight.\n\n"
|
||||
"@see footSplashHeight\n" );
|
||||
addField( "FootWadingSound", TypeSFXTrackName, Offset(sound[FootWading], PlayerData),
|
||||
"@brief Sound to play when walking in water and coverage is less than 1, "
|
||||
"but > footSplashHeight.\n\n"
|
||||
"@see footSplashHeight\n" );
|
||||
addField( "FootUnderwaterSound", TypeSFXTrackName, Offset(sound[FootUnderWater], PlayerData),
|
||||
"@brief Sound to play when walking in water and coverage equals 1.0 "
|
||||
"(fully underwater).\n\n" );
|
||||
addField( "FootBubblesSound", TypeSFXTrackName, Offset(sound[FootBubbles], PlayerData),
|
||||
"@brief Sound to play when walking in water and coverage equals 1.0 "
|
||||
"(fully underwater).\n\n" );
|
||||
addField( "movingBubblesSound", TypeSFXTrackName, Offset(sound[MoveBubbles], PlayerData),
|
||||
"@brief Sound to play when in water and coverage equals 1.0 (fully underwater).\n\n"
|
||||
"Note that unlike FootUnderwaterSound, this sound plays even if the "
|
||||
"player is not moving around in the water.\n" );
|
||||
addField( "waterBreathSound", TypeSFXTrackName, Offset(sound[WaterBreath], PlayerData),
|
||||
"@brief Sound to play when in water and coverage equals 1.0 (fully underwater).\n\n"
|
||||
"Note that unlike FootUnderwaterSound, this sound plays even if the "
|
||||
"player is not moving around in the water.\n" );
|
||||
|
||||
addField( "impactSoftSound", TypeSFXTrackName, Offset(sound[ImpactSoft], PlayerData),
|
||||
"@brief Sound to play after falling on a surface with Material footstepSoundId 0.\n\n" );
|
||||
addField( "impactHardSound", TypeSFXTrackName, Offset(sound[ImpactHard], PlayerData),
|
||||
"@brief Sound to play after falling on a surface with Material footstepSoundId 1.\n\n" );
|
||||
addField( "impactMetalSound", TypeSFXTrackName, Offset(sound[ImpactMetal], PlayerData),
|
||||
"@brief Sound to play after falling on a surface with Material footstepSoundId 2.\n\n" );
|
||||
addField( "impactSnowSound", TypeSFXTrackName, Offset(sound[ImpactSnow], PlayerData),
|
||||
"@brief Sound to play after falling on a surface with Material footstepSoundId 3.\n\n" );
|
||||
|
||||
addField( "impactWaterEasy", TypeSFXTrackName, Offset(sound[ImpactWaterEasy], PlayerData),
|
||||
"@brief Sound to play when entering the water with velocity < "
|
||||
"mediumSplashSoundVelocity.\n\n"
|
||||
"@see mediumSplashSoundVelocity\n");
|
||||
addField( "impactWaterMedium", TypeSFXTrackName, Offset(sound[ImpactWaterMedium], PlayerData),
|
||||
"@brief Sound to play when entering the water with velocity >= "
|
||||
"mediumSplashSoundVelocity and < hardSplashSoundVelocity.\n\n"
|
||||
"@see mediumSplashSoundVelocity\n"
|
||||
"@see hardSplashSoundVelocity\n");
|
||||
addField( "impactWaterHard", TypeSFXTrackName, Offset(sound[ImpactWaterHard], PlayerData),
|
||||
"@brief Sound to play when entering the water with velocity >= "
|
||||
"hardSplashSoundVelocity.\n\n"
|
||||
"@see hardSplashSoundVelocity\n");
|
||||
addField( "exitingWater", TypeSFXTrackName, Offset(sound[ExitWater], PlayerData),
|
||||
"@brief Sound to play when exiting the water with velocity >= exitSplashSoundVelocity.\n\n"
|
||||
"@see exitSplashSoundVelocity\n");
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET_ENUMED(PlayerSound, playerSoundsEnum, PlayerData::Sounds::MaxSounds, PlayerData, "Sounds related to player interaction.");
|
||||
endGroup( "Interaction: Sounds" );
|
||||
|
||||
addGroup( "Interaction: Splashes" );
|
||||
|
|
@ -1303,8 +1270,8 @@ void PlayerData::packData(BitStream* stream)
|
|||
stream->write(minImpactSpeed);
|
||||
stream->write(minLateralImpactSpeed);
|
||||
|
||||
for( U32 i = 0; i < MaxSounds; i++)
|
||||
sfxWrite( stream, sound[ i ] );
|
||||
for (U32 i = 0; i < MaxSounds; i++)
|
||||
PACKDATA_ASSET_ARRAY(PlayerSound, i);
|
||||
|
||||
mathWrite(*stream, boxSize);
|
||||
mathWrite(*stream, crouchBoxSize);
|
||||
|
|
@ -1372,7 +1339,7 @@ void PlayerData::packData(BitStream* stream)
|
|||
stream->writeString(imageAnimPrefixFP);
|
||||
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
||||
{
|
||||
PACKDATA_SHAPEASSET_ARRAY(ShapeFP, i);
|
||||
PACKDATA_ASSET_ARRAY(ShapeFP, i);
|
||||
|
||||
// computeCRC is handled in ShapeBaseData
|
||||
if (computeCRC)
|
||||
|
|
@ -1484,8 +1451,8 @@ void PlayerData::unpackData(BitStream* stream)
|
|||
stream->read(&minImpactSpeed);
|
||||
stream->read(&minLateralImpactSpeed);
|
||||
|
||||
for( U32 i = 0; i < MaxSounds; i++)
|
||||
sfxRead( stream, &sound[ i ] );
|
||||
for (U32 i = 0; i < MaxSounds; i++)
|
||||
UNPACKDATA_ASSET_ARRAY(PlayerSound, i);
|
||||
|
||||
mathRead(*stream, &boxSize);
|
||||
mathRead(*stream, &crouchBoxSize);
|
||||
|
|
@ -1552,7 +1519,7 @@ void PlayerData::unpackData(BitStream* stream)
|
|||
imageAnimPrefixFP = stream->readSTString();
|
||||
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
||||
{
|
||||
UNPACKDATA_SHAPEASSET_ARRAY(ShapeFP, i);
|
||||
UNPACKDATA_ASSET_ARRAY(ShapeFP, i);
|
||||
|
||||
// computeCRC is handled in ShapeBaseData
|
||||
if (computeCRC)
|
||||
|
|
@ -1932,11 +1899,11 @@ bool Player::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
SFX_DELETE( mMoveBubbleSound );
|
||||
SFX_DELETE( mWaterBreathSound );
|
||||
|
||||
if ( mDataBlock->sound[PlayerData::MoveBubbles] )
|
||||
mMoveBubbleSound = SFX->createSource( mDataBlock->sound[PlayerData::MoveBubbles] );
|
||||
if ( mDataBlock->getPlayerSound(PlayerData::MoveBubbles) )
|
||||
mMoveBubbleSound = SFX->createSource( mDataBlock->getPlayerSoundProfile(PlayerData::MoveBubbles) );
|
||||
|
||||
if ( mDataBlock->sound[PlayerData::WaterBreath] )
|
||||
mWaterBreathSound = SFX->createSource( mDataBlock->sound[PlayerData::WaterBreath] );
|
||||
if ( mDataBlock->getPlayerSound(PlayerData::WaterBreath) )
|
||||
mWaterBreathSound = SFX->createSource( mDataBlock->getPlayerSoundProfile(PlayerData::WaterBreath) );
|
||||
}
|
||||
|
||||
mObjBox.maxExtents.x = mDataBlock->boxSize.x * 0.5f;
|
||||
|
|
@ -3300,7 +3267,7 @@ void Player::updateMove(const Move* move)
|
|||
{
|
||||
// exit-water splash sound happens for client only
|
||||
if ( getSpeed() >= mDataBlock->exitSplashSoundVel && !isMounted() )
|
||||
SFX->playOnce( mDataBlock->sound[PlayerData::ExitWater], &getTransform() );
|
||||
SFX->playOnce( mDataBlock->getPlayerSoundProfile(PlayerData::ExitWater), &getTransform() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7060,39 +7027,39 @@ void Player::playFootstepSound( bool triggeredLeft, Material* contactMaterial, S
|
|||
// Treading water.
|
||||
|
||||
if ( mWaterCoverage < mDataBlock->footSplashHeight )
|
||||
SFX->playOnce( mDataBlock->sound[ PlayerData::FootShallowSplash ], &footMat );
|
||||
SFX->playOnce( mDataBlock->getPlayerSoundProfile( PlayerData::FootShallowSplash ), &footMat );
|
||||
else
|
||||
{
|
||||
if ( mWaterCoverage < 1.0 )
|
||||
SFX->playOnce( mDataBlock->sound[ PlayerData::FootWading ], &footMat );
|
||||
SFX->playOnce( mDataBlock->getPlayerSoundProfile( PlayerData::FootWading ), &footMat );
|
||||
else
|
||||
{
|
||||
if ( triggeredLeft )
|
||||
{
|
||||
SFX->playOnce( mDataBlock->sound[ PlayerData::FootUnderWater ], &footMat );
|
||||
SFX->playOnce( mDataBlock->sound[ PlayerData::FootBubbles ], &footMat );
|
||||
SFX->playOnce( mDataBlock->getPlayerSoundProfile( PlayerData::FootUnderWater ), &footMat );
|
||||
SFX->playOnce( mDataBlock->getPlayerSoundProfile( PlayerData::FootBubbles ), &footMat );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( contactMaterial && contactMaterial->mFootstepSoundCustom )
|
||||
else if( contactMaterial && contactMaterial->getCustomFootstepSoundProfile())
|
||||
{
|
||||
// Footstep sound defined on material.
|
||||
|
||||
SFX->playOnce( contactMaterial->mFootstepSoundCustom, &footMat );
|
||||
SFX->playOnce( contactMaterial->getCustomFootstepSoundProfile(), &footMat );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play default sound.
|
||||
|
||||
S32 sound = -1;
|
||||
if (contactMaterial && (contactMaterial->mFootstepSoundId>-1 && contactMaterial->mFootstepSoundId<PlayerData::MaxSoundOffsets))
|
||||
if (contactMaterial && (contactMaterial->mFootstepSoundId > -1 && contactMaterial->mFootstepSoundId < PlayerData::WaterStart))
|
||||
sound = contactMaterial->mFootstepSoundId;
|
||||
else if( contactObject && contactObject->getTypeMask() & VehicleObjectType )
|
||||
sound = 2;
|
||||
|
||||
if (sound>=0)
|
||||
SFX->playOnce(mDataBlock->sound[sound], &footMat);
|
||||
SFX->playOnce(mDataBlock->getPlayerSoundProfile(sound), &footMat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7112,18 +7079,18 @@ void Player:: playImpactSound()
|
|||
{
|
||||
Material* material = ( rInfo.material ? dynamic_cast< Material* >( rInfo.material->getMaterial() ) : 0 );
|
||||
|
||||
if( material && material->mImpactSoundCustom )
|
||||
SFX->playOnce( material->mImpactSoundCustom, &getTransform() );
|
||||
if( material && material->getCustomImpactSoundProfile() )
|
||||
SFX->playOnce( material->getCustomImpactSoundProfile(), &getTransform() );
|
||||
else
|
||||
{
|
||||
S32 sound = -1;
|
||||
if (material && (material->mImpactSoundId>-1 && material->mImpactSoundId<PlayerData::MaxSoundOffsets))
|
||||
if (material && (material->mImpactSoundId > -1 && material->mImpactSoundId < PlayerData::WaterStart))
|
||||
sound = material->mImpactSoundId;
|
||||
else if( rInfo.object->getTypeMask() & VehicleObjectType )
|
||||
sound = 2; // Play metal;
|
||||
|
||||
if (sound >= 0)
|
||||
SFX->playOnce(mDataBlock->sound[PlayerData::ImpactStart + sound], &getTransform());
|
||||
SFX->playOnce(mDataBlock->getPlayerSoundProfile(PlayerData::ImpactSoft + sound), &getTransform());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7277,11 +7244,11 @@ bool Player::collidingWithWater( Point3F &waterHeight )
|
|||
void Player::createSplash( Point3F &pos, F32 speed )
|
||||
{
|
||||
if ( speed >= mDataBlock->hardSplashSoundVel )
|
||||
SFX->playOnce( mDataBlock->sound[PlayerData::ImpactWaterHard], &getTransform() );
|
||||
SFX->playOnce( mDataBlock->getPlayerSoundProfile(PlayerData::ImpactWaterHard), &getTransform() );
|
||||
else if ( speed >= mDataBlock->medSplashSoundVel )
|
||||
SFX->playOnce( mDataBlock->sound[PlayerData::ImpactWaterMedium], &getTransform() );
|
||||
SFX->playOnce( mDataBlock->getPlayerSoundProfile(PlayerData::ImpactWaterMedium), &getTransform() );
|
||||
else
|
||||
SFX->playOnce( mDataBlock->sound[PlayerData::ImpactWaterEasy], &getTransform() );
|
||||
SFX->playOnce( mDataBlock->getPlayerSoundProfile(PlayerData::ImpactWaterEasy), &getTransform() );
|
||||
|
||||
if( mDataBlock->splash )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "collision/boxConvex.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
#include "T3D/gameBase/gameProcess.h"
|
||||
|
||||
class Material;
|
||||
|
|
@ -76,7 +77,7 @@ struct PlayerData: public ShapeBaseData {
|
|||
/// need to.
|
||||
|
||||
DECLARE_SHAPEASSET_ARRAY(PlayerData, ShapeFP, ShapeBase::MaxMountedImages); ///< Used to render with mounted images in first person [optional]
|
||||
DECLARE_SHAPEASSET_ARRAY_SETGET(PlayerData, ShapeFP);
|
||||
DECLARE_ASSET_ARRAY_SETGET(PlayerData, ShapeFP);
|
||||
|
||||
StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify
|
||||
/// animation sequences played in first person. [optional]
|
||||
|
|
@ -200,7 +201,7 @@ struct PlayerData: public ShapeBaseData {
|
|||
FootHard,
|
||||
FootMetal,
|
||||
FootSnow,
|
||||
MaxSoundOffsets,
|
||||
WaterStart,
|
||||
FootShallowSplash,
|
||||
FootWading,
|
||||
FootUnderWater,
|
||||
|
|
@ -208,7 +209,7 @@ struct PlayerData: public ShapeBaseData {
|
|||
MoveBubbles,
|
||||
WaterBreath,
|
||||
ImpactStart,
|
||||
ImpactSoft = ImpactStart,
|
||||
ImpactSoft,
|
||||
ImpactHard,
|
||||
ImpactMetal,
|
||||
ImpactSnow,
|
||||
|
|
@ -218,7 +219,8 @@ struct PlayerData: public ShapeBaseData {
|
|||
ExitWater,
|
||||
MaxSounds
|
||||
};
|
||||
SFXTrack* sound[MaxSounds];
|
||||
|
||||
DECLARE_SOUNDASSET_ARRAY(PlayerData, PlayerSound, Sounds::MaxSounds);
|
||||
|
||||
Point3F boxSize; ///< Width, depth, height
|
||||
Point3F crouchBoxSize;
|
||||
|
|
@ -877,5 +879,4 @@ public:
|
|||
typedef Player::Pose PlayerPose;
|
||||
|
||||
DefineEnumType( PlayerPose );
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ bool Prefab::protectedSetFile( void *object, const char *index, const char *data
|
|||
return false;
|
||||
}
|
||||
|
||||
void Prefab::setFile( String file )
|
||||
void Prefab::setFile( StringTableEntry file )
|
||||
{
|
||||
AssertFatal( isServerObject(), "Prefab-bad" );
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ void Prefab::setFile( String file )
|
|||
// be called for the client-side prefab but maybe the user did so accidentally.
|
||||
if ( isClientObject() )
|
||||
{
|
||||
Con::errorf( "Prefab::setFile( %s ) - Should not be called on a client-side Prefab.", file.c_str() );
|
||||
Con::errorf( "Prefab::setFile( %s ) - Should not be called on a client-side Prefab.", file );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -616,3 +616,9 @@ void ExplodePrefabUndoAction::redo()
|
|||
name = Sim::getUniqueName( name );
|
||||
mGroup->assignName( name );
|
||||
}
|
||||
|
||||
DefineEngineMethod(Prefab, getChildGroup, S32, (),,
|
||||
"")
|
||||
{
|
||||
return object->getChildGroup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public:
|
|||
void render( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
|
||||
|
||||
///
|
||||
void setFile( String file );
|
||||
void setFile(StringTableEntry file );
|
||||
|
||||
/// Removes all children from this Prefab and puts them into a SimGroup
|
||||
/// which is added to the Scene and returned to the caller.
|
||||
|
|
@ -102,6 +102,13 @@ public:
|
|||
|
||||
virtual void getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList);
|
||||
|
||||
S32 getChildGroup() {
|
||||
if (mChildGroup.isValid())
|
||||
return mChildGroup->getId();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void _closeFile( bool removeFileNotify );
|
||||
|
|
|
|||
|
|
@ -144,9 +144,9 @@ U32 Projectile::smProjectileWarpTicks = 5;
|
|||
//
|
||||
ProjectileData::ProjectileData()
|
||||
{
|
||||
INIT_SHAPEASSET(ProjectileShape);
|
||||
INIT_ASSET(ProjectileShape);
|
||||
|
||||
sound = NULL;
|
||||
INIT_ASSET(ProjectileSound);
|
||||
|
||||
explosion = NULL;
|
||||
explosionId = 0;
|
||||
|
|
@ -217,10 +217,10 @@ ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : G
|
|||
splashId = other.splashId; // -- for pack/unpack of splash ptr
|
||||
decal = other.decal;
|
||||
decalId = other.decalId; // -- for pack/unpack of decal ptr
|
||||
sound = other.sound;
|
||||
CLONE_ASSET(ProjectileSound);
|
||||
lightDesc = other.lightDesc;
|
||||
lightDescId = other.lightDescId; // -- for pack/unpack of lightDesc ptr
|
||||
CLONE_SHAPEASSET(ProjectileShape);// -- TSShape loads using mProjectileShapeName
|
||||
CLONE_ASSET(ProjectileShape);// -- TSShape loads using mProjectileShapeName
|
||||
activateSeq = other.activateSeq; // -- from projectileShape sequence "activate"
|
||||
maintainSeq = other.maintainSeq; // -- from projectileShape sequence "maintain"
|
||||
particleEmitter = other.particleEmitter;
|
||||
|
|
@ -252,8 +252,7 @@ void ProjectileData::initPersistFields()
|
|||
"@brief Scale to apply to the projectile's size.\n\n"
|
||||
"@note This is applied after SceneObject::scale\n");
|
||||
|
||||
addField("sound", TypeSFXTrackName, Offset(sound, ProjectileData),
|
||||
"@brief SFXTrack datablock used to play sounds while in flight.\n\n");
|
||||
INITPERSISTFIELD_SOUNDASSET(ProjectileSound, ProjectileData, "The sound for the projectile.");
|
||||
|
||||
addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, ProjectileData),
|
||||
"@brief Explosion datablock used when the projectile explodes outside of water.\n\n");
|
||||
|
|
@ -368,9 +367,12 @@ bool ProjectileData::preload(bool server, String &errorStr)
|
|||
if (Sim::findObject(decalId, decal) == false)
|
||||
Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(decal): %d", decalId);
|
||||
|
||||
String sfxErrorStr;
|
||||
if( !sfxResolve( &sound, sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet: %s", sfxErrorStr.c_str());
|
||||
_setProjectileSound(getProjectileSound());
|
||||
if (getProjectileSound() != StringTable->EmptyString())
|
||||
{
|
||||
if (!getProjectileSoundProfile())
|
||||
Con::errorf(ConsoleLogEntry::General, "SplashData::preload: Cant get an sfxProfile for splash.");
|
||||
}
|
||||
|
||||
if (!lightDesc && lightDescId != 0)
|
||||
if (Sim::findObject(lightDescId, lightDesc) == false)
|
||||
|
|
@ -403,7 +405,7 @@ void ProjectileData::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_SHAPEASSET(ProjectileShape);
|
||||
PACKDATA_ASSET(ProjectileShape);
|
||||
|
||||
stream->writeFlag(faceViewer);
|
||||
if(stream->writeFlag(scale.x != 1 || scale.y != 1 || scale.z != 1))
|
||||
|
|
@ -436,8 +438,7 @@ void ProjectileData::packData(BitStream* stream)
|
|||
if (stream->writeFlag(decal != NULL))
|
||||
stream->writeRangedU32(decal->getId(), DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast);
|
||||
|
||||
sfxWrite( stream, sound );
|
||||
PACKDATA_ASSET(ProjectileSound);
|
||||
|
||||
if ( stream->writeFlag(lightDesc != NULL))
|
||||
stream->writeRangedU32(lightDesc->getId(), DataBlockObjectIdFirst,
|
||||
|
|
@ -468,7 +469,7 @@ void ProjectileData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_SHAPEASSET(ProjectileShape);
|
||||
UNPACKDATA_ASSET(ProjectileShape);
|
||||
|
||||
faceViewer = stream->readFlag();
|
||||
if(stream->readFlag())
|
||||
|
|
@ -497,8 +498,8 @@ void ProjectileData::unpackData(BitStream* stream)
|
|||
|
||||
if (stream->readFlag())
|
||||
decalId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
|
||||
sfxRead( stream, &sound );
|
||||
|
||||
UNPACKDATA_ASSET(ProjectileSound);
|
||||
|
||||
if (stream->readFlag())
|
||||
lightDescId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
|
|
@ -786,6 +787,8 @@ bool Projectile::onAdd()
|
|||
// If we're on the server, we need to inherit some of our parent's velocity
|
||||
//
|
||||
mCurrTick = 0;
|
||||
|
||||
scriptOnAdd();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -882,8 +885,8 @@ bool Projectile::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
|
||||
SFX_DELETE( mSound );
|
||||
|
||||
if ( mDataBlock->sound )
|
||||
mSound = SFX->createSource( mDataBlock->sound );
|
||||
if ( mDataBlock->getProjectileSound() )
|
||||
mSound = SFX->createSource( mDataBlock->getProjectileSoundProfile() );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1097,7 +1100,7 @@ void Projectile::explode( const Point3F &p, const Point3F &n, const U32 collideT
|
|||
|
||||
void Projectile::updateSound()
|
||||
{
|
||||
if (!mDataBlock->sound)
|
||||
if (!mDataBlock->isProjectileSoundValid())
|
||||
return;
|
||||
|
||||
if ( mSound )
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "lighting/lightInfo.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
#include "T3D/assets/ShapeAsset.h"
|
||||
|
||||
class ExplosionData;
|
||||
|
|
@ -71,7 +72,7 @@ protected:
|
|||
|
||||
public:
|
||||
DECLARE_SHAPEASSET(ProjectileData, ProjectileShape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(ProjectileData, ProjectileShape);
|
||||
DECLARE_ASSET_SETGET(ProjectileData, ProjectileShape);
|
||||
|
||||
/// Set to true if it is a billboard and want it to always face the viewer, false otherwise
|
||||
bool faceViewer;
|
||||
|
|
@ -115,7 +116,8 @@ public:
|
|||
DecalData *decal; // (impact) Decal Datablock
|
||||
S32 decalId; // (impact) Decal ID
|
||||
|
||||
SFXTrack* sound; // Projectile Sound
|
||||
DECLARE_SOUNDASSET(ProjectileData, ProjectileSound);
|
||||
DECLARE_ASSET_SETGET(ProjectileData, ProjectileSound);
|
||||
|
||||
LightDescription *lightDesc;
|
||||
S32 lightDescId;
|
||||
|
|
|
|||
|
|
@ -74,16 +74,16 @@ IMPLEMENT_CALLBACK( ProximityMineData, onExplode, void, ( ProximityMine* obj, Po
|
|||
ProximityMineData::ProximityMineData()
|
||||
: armingDelay( 0 ),
|
||||
armingSequence( -1 ),
|
||||
armingSound( NULL ),
|
||||
triggerRadius( 5.0f ),
|
||||
triggerSpeed( 1.0f ),
|
||||
autoTriggerDelay( 0 ),
|
||||
triggerOnOwner( false ),
|
||||
triggerDelay( 0 ),
|
||||
triggerSequence( -1 ),
|
||||
triggerSound( NULL ),
|
||||
explosionOffset( 0.05f )
|
||||
{
|
||||
INIT_ASSET(ArmSound);
|
||||
INIT_ASSET(TriggerSound);
|
||||
}
|
||||
|
||||
void ProximityMineData::initPersistFields()
|
||||
|
|
@ -91,9 +91,9 @@ void ProximityMineData::initPersistFields()
|
|||
addGroup( "Arming" );
|
||||
addField( "armingDelay", TypeF32, Offset(armingDelay, ProximityMineData),
|
||||
"Delay (in seconds) from when the mine is placed to when it becomes active." );
|
||||
addField( "armingSound", TypeSFXTrackName, Offset(armingSound, ProximityMineData),
|
||||
"Sound to play when the mine is armed (starts at the same time as "
|
||||
"the <i>armed</i> sequence if defined)." );
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET(ArmSound, ProximityMineData, "Arming sound for this proximity mine.");
|
||||
|
||||
endGroup( "Arming" );
|
||||
|
||||
addGroup( "Triggering" );
|
||||
|
|
@ -111,9 +111,9 @@ void ProximityMineData::initPersistFields()
|
|||
"Speed above which moving objects within the trigger radius will trigger the mine" );
|
||||
addField( "triggerDelay", TypeF32, Offset(triggerDelay, ProximityMineData),
|
||||
"Delay (in seconds) from when the mine is triggered until it explodes." );
|
||||
addField( "triggerSound", TypeSFXTrackName, Offset(triggerSound, ProximityMineData),
|
||||
"Sound to play when the mine is triggered (starts at the same time as "
|
||||
"the <i>triggered</i> sequence if defined)." );
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET(TriggerSound, ProximityMineData, "Arming sound for this proximity mine.");
|
||||
|
||||
endGroup( "Triggering" );
|
||||
|
||||
addGroup( "Explosion" );
|
||||
|
|
@ -135,12 +135,10 @@ bool ProximityMineData::preload( bool server, String& errorStr )
|
|||
|
||||
if ( !server )
|
||||
{
|
||||
// Resolve sounds
|
||||
String sfxErrorStr;
|
||||
if( !sfxResolve( &armingSound, sfxErrorStr ) )
|
||||
Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", sfxErrorStr.c_str() );
|
||||
if( !sfxResolve( &triggerSound, sfxErrorStr ) )
|
||||
Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", sfxErrorStr.c_str() );
|
||||
if( !getArmSound() )
|
||||
Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid arming sound." );
|
||||
if( !getTriggerSound() )
|
||||
Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid trigger sound." );
|
||||
}
|
||||
|
||||
if ( mShape )
|
||||
|
|
@ -158,14 +156,14 @@ void ProximityMineData::packData( BitStream* stream )
|
|||
Parent::packData( stream );
|
||||
|
||||
stream->write( armingDelay );
|
||||
sfxWrite( stream, armingSound );
|
||||
PACKDATA_ASSET(ArmSound);
|
||||
|
||||
stream->write( autoTriggerDelay );
|
||||
stream->writeFlag( triggerOnOwner );
|
||||
stream->write( triggerRadius );
|
||||
stream->write( triggerSpeed );
|
||||
stream->write( triggerDelay );
|
||||
sfxWrite( stream, triggerSound );
|
||||
PACKDATA_ASSET(TriggerSound);
|
||||
}
|
||||
|
||||
void ProximityMineData::unpackData( BitStream* stream )
|
||||
|
|
@ -173,14 +171,14 @@ void ProximityMineData::unpackData( BitStream* stream )
|
|||
Parent::unpackData(stream);
|
||||
|
||||
stream->read( &armingDelay );
|
||||
sfxRead( stream, &armingSound );
|
||||
UNPACKDATA_ASSET(ArmSound);
|
||||
|
||||
stream->read( &autoTriggerDelay );
|
||||
triggerOnOwner = stream->readFlag();
|
||||
stream->read( &triggerRadius );
|
||||
stream->read( &triggerSpeed );
|
||||
stream->read( &triggerDelay );
|
||||
sfxRead( stream, &triggerSound );
|
||||
UNPACKDATA_ASSET(TriggerSound);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -428,8 +426,8 @@ void ProximityMine::processTick( const Move* move )
|
|||
mAnimThread = mShapeInstance->addThread();
|
||||
mShapeInstance->setSequence( mAnimThread, mDataBlock->armingSequence, 0.0f );
|
||||
}
|
||||
if ( mDataBlock->armingSound )
|
||||
SFX->playOnce( mDataBlock->armingSound, &getRenderTransform() );
|
||||
if ( mDataBlock->getArmSoundProfile() )
|
||||
SFX->playOnce( mDataBlock->getArmSoundProfile(), &getRenderTransform() );
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -469,8 +467,8 @@ void ProximityMine::processTick( const Move* move )
|
|||
mAnimThread = mShapeInstance->addThread();
|
||||
mShapeInstance->setSequence( mAnimThread, mDataBlock->triggerSequence, 0.0f );
|
||||
}
|
||||
if ( mDataBlock->triggerSound )
|
||||
SFX->playOnce( mDataBlock->triggerSound, &getRenderTransform() );
|
||||
if ( mDataBlock->getTriggerSoundProfile() )
|
||||
SFX->playOnce( mDataBlock->getTriggerSoundProfile(), &getRenderTransform() );
|
||||
|
||||
if ( isServerObject() )
|
||||
mDataBlock->onTriggered_callback( this, sql.mList[0] );
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "T3D/item.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
class ExplosionData;
|
||||
class SFXTrack;
|
||||
class ProximityMine;
|
||||
|
|
@ -43,7 +45,8 @@ struct ProximityMineData: public ItemData
|
|||
public:
|
||||
F32 armingDelay;
|
||||
S32 armingSequence;
|
||||
SFXTrack* armingSound;
|
||||
DECLARE_SOUNDASSET(ProximityMineData, ArmSound);
|
||||
DECLARE_ASSET_SETGET(ProximityMineData, ArmSound);
|
||||
|
||||
F32 autoTriggerDelay;
|
||||
bool triggerOnOwner;
|
||||
|
|
@ -51,7 +54,8 @@ public:
|
|||
F32 triggerSpeed;
|
||||
F32 triggerDelay;
|
||||
S32 triggerSequence;
|
||||
SFXTrack* triggerSound;
|
||||
DECLARE_SOUNDASSET(ProximityMineData, TriggerSound);
|
||||
DECLARE_ASSET_SETGET(ProximityMineData, TriggerSound);
|
||||
|
||||
F32 explosionOffset;
|
||||
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ RigidShapeData::RigidShapeData()
|
|||
density = 4;
|
||||
|
||||
for (S32 i = 0; i < Body::MaxSounds; i++)
|
||||
body.sound[i] = 0;
|
||||
INIT_ASSET_ARRAY(BodySounds, i);
|
||||
|
||||
dustEmitter = NULL;
|
||||
dustID = 0;
|
||||
|
|
@ -256,13 +256,15 @@ RigidShapeData::RigidShapeData()
|
|||
hardSplashSoundVel = 3.0;
|
||||
enablePhysicsRep = true;
|
||||
|
||||
dMemset(waterSound, 0, sizeof(waterSound));
|
||||
for (S32 i = 0; i < Sounds::MaxSounds; i++)
|
||||
INIT_ASSET_ARRAY(WaterSounds, i);
|
||||
|
||||
dragForce = 0;
|
||||
vertFactor = 0.25;
|
||||
|
||||
dustTrailEmitter = NULL;
|
||||
dustTrailID = 0;
|
||||
_setShape(ShapeAsset::smNoShapeAssetFallback);
|
||||
}
|
||||
|
||||
RigidShapeData::~RigidShapeData()
|
||||
|
|
@ -298,7 +300,21 @@ bool RigidShapeData::preload(bool server, String &errorStr)
|
|||
// Resolve objects transmitted from server
|
||||
if (!server) {
|
||||
for (S32 i = 0; i < Body::MaxSounds; i++)
|
||||
sfxResolve( &body.sound[ i ], errorStr );
|
||||
{
|
||||
if (mBodySounds[i])
|
||||
{
|
||||
_setBodySounds(getBodySounds(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < Sounds::MaxSounds; j++)
|
||||
{
|
||||
if (mWaterSounds[j])
|
||||
{
|
||||
_setWaterSounds(getWaterSounds(j), j);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !dustEmitter && dustID != 0 )
|
||||
|
|
@ -353,8 +369,10 @@ void RigidShapeData::packData(BitStream* stream)
|
|||
|
||||
stream->write(body.restitution);
|
||||
stream->write(body.friction);
|
||||
for( U32 i = 0; i < Body::MaxSounds; ++ i )
|
||||
sfxWrite( stream, body.sound[ i ] );
|
||||
for (U32 i = 0; i < Body::MaxSounds; ++i)
|
||||
{
|
||||
PACKDATA_ASSET_ARRAY(BodySounds, i);
|
||||
}
|
||||
|
||||
stream->write(minImpactSpeed);
|
||||
stream->write(softImpactSpeed);
|
||||
|
|
@ -383,8 +401,10 @@ void RigidShapeData::packData(BitStream* stream)
|
|||
stream->write(enablePhysicsRep);
|
||||
|
||||
// write the water sound profiles
|
||||
for( U32 i = 0; i < MaxSounds; ++ i )
|
||||
sfxWrite( stream, waterSound[ i ] );
|
||||
for (U32 i = 0; i < Sounds::MaxSounds; ++i)
|
||||
{
|
||||
PACKDATA_ASSET_ARRAY(WaterSounds, i);
|
||||
}
|
||||
|
||||
if (stream->writeFlag( dustEmitter ))
|
||||
stream->writeRangedU32( dustEmitter->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
|
||||
|
|
@ -412,8 +432,10 @@ void RigidShapeData::unpackData(BitStream* stream)
|
|||
stream->read(&body.restitution);
|
||||
stream->read(&body.friction);
|
||||
|
||||
for( U32 i = 0; i < Body::MaxSounds; i++)
|
||||
sfxRead( stream, &body.sound[ i ] );
|
||||
for (U32 i = 0; i < Body::Sounds::MaxSounds; i++)
|
||||
{
|
||||
UNPACKDATA_ASSET_ARRAY(BodySounds, i);
|
||||
}
|
||||
|
||||
stream->read(&minImpactSpeed);
|
||||
stream->read(&softImpactSpeed);
|
||||
|
|
@ -442,8 +464,10 @@ void RigidShapeData::unpackData(BitStream* stream)
|
|||
stream->read(&enablePhysicsRep);
|
||||
|
||||
// write the water sound profiles
|
||||
for( U32 i = 0; i < MaxSounds; ++ i )
|
||||
sfxRead( stream, &waterSound[ i ] );
|
||||
for (U32 i = 0; i < Sounds::MaxSounds; ++i)
|
||||
{
|
||||
UNPACKDATA_ASSET_ARRAY(WaterSounds, i);
|
||||
}
|
||||
|
||||
if( stream->readFlag() )
|
||||
dustID = (S32) stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
|
|
@ -515,21 +539,15 @@ void RigidShapeData::initPersistFields()
|
|||
|
||||
addGroup( "Sounds" );
|
||||
|
||||
addField("softImpactSound", TypeSFXTrackName, Offset(body.sound[Body::SoftImpactSound], RigidShapeData),
|
||||
"Sound to play when body impacts with at least softImageSpeed but less than hardImpactSpeed." );
|
||||
addField("hardImpactSound", TypeSFXTrackName, Offset(body.sound[Body::HardImpactSound], RigidShapeData),
|
||||
"Sound to play when body impacts with at least hardImpactSpeed." );
|
||||
INITPERSISTFIELD_SOUNDASSET_ARRAY(BodySounds, Body::Sounds::MaxSounds, RigidShapeData, "Sounds for body.");
|
||||
|
||||
addField("exitSplashSoundVelocity", TypeF32, Offset(exitSplashSoundVel, RigidShapeData), "The minimum velocity at which the exit splash sound will be played when emerging from water.\n");
|
||||
addField("softSplashSoundVelocity", TypeF32, Offset(softSplashSoundVel, RigidShapeData),"The minimum velocity at which the soft splash sound will be played when impacting water.\n");
|
||||
addField("mediumSplashSoundVelocity", TypeF32, Offset(medSplashSoundVel, RigidShapeData), "The minimum velocity at which the medium splash sound will be played when impacting water.\n");
|
||||
addField("hardSplashSoundVelocity", TypeF32, Offset(hardSplashSoundVel, RigidShapeData), "The minimum velocity at which the hard splash sound will be played when impacting water.\n");
|
||||
addField("exitingWater", TypeSFXTrackName, Offset(waterSound[ExitWater], RigidShapeData), "The AudioProfile will be used to produce sounds when emerging from water.\n");
|
||||
addField("impactWaterEasy", TypeSFXTrackName, Offset(waterSound[ImpactSoft], RigidShapeData), "The AudioProfile will be used to produce sounds when a soft impact with water occurs.\n");
|
||||
addField("impactWaterMedium", TypeSFXTrackName, Offset(waterSound[ImpactMedium], RigidShapeData), "The AudioProfile will be used to produce sounds when a medium impact with water occurs.\n");
|
||||
addField("impactWaterHard", TypeSFXTrackName, Offset(waterSound[ImpactHard], RigidShapeData), "The AudioProfile will be used to produce sounds when a hard impact with water occurs.\n");
|
||||
addField("waterWakeSound", TypeSFXTrackName, Offset(waterSound[Wake], RigidShapeData), "The AudioProfile will be used to produce sounds when a water wake is displayed.\n");
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET_ARRAY(WaterSounds, Sounds::MaxSounds, RigidShapeData, "Sounds for interacting with water.");
|
||||
|
||||
endGroup( "Sounds" );
|
||||
|
||||
addGroup( "Camera" );
|
||||
|
|
@ -1154,27 +1172,27 @@ void RigidShape::updatePos(F32 dt)
|
|||
if (collSpeed >= mDataBlock->softImpactSpeed)
|
||||
impactSound = RigidShapeData::Body::SoftImpactSound;
|
||||
|
||||
if (impactSound != -1 && mDataBlock->body.sound[impactSound] != NULL)
|
||||
SFX->playOnce(mDataBlock->body.sound[impactSound], &getTransform());
|
||||
if (impactSound != -1 && mDataBlock->getBodySoundsProfile(impactSound))
|
||||
SFX->playOnce(mDataBlock->getBodySoundsProfile(impactSound), &getTransform());
|
||||
}
|
||||
|
||||
// Water volume sounds
|
||||
F32 vSpeed = getVelocity().len();
|
||||
if (!inLiquid && mWaterCoverage >= 0.8f) {
|
||||
if (vSpeed >= mDataBlock->hardSplashSoundVel)
|
||||
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactHard], &getTransform());
|
||||
SFX->playOnce(mDataBlock->getWaterSoundsProfile(RigidShapeData::ImpactHard), &getTransform());
|
||||
else
|
||||
if (vSpeed >= mDataBlock->medSplashSoundVel)
|
||||
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactMedium], &getTransform());
|
||||
SFX->playOnce(mDataBlock->getWaterSoundsProfile(RigidShapeData::ImpactMedium), &getTransform());
|
||||
else
|
||||
if (vSpeed >= mDataBlock->softSplashSoundVel)
|
||||
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactSoft], &getTransform());
|
||||
SFX->playOnce(mDataBlock->getWaterSoundsProfile(RigidShapeData::ImpactSoft), &getTransform());
|
||||
inLiquid = true;
|
||||
}
|
||||
else
|
||||
if (inLiquid && mWaterCoverage < 0.8f) {
|
||||
if (vSpeed >= mDataBlock->exitSplashSoundVel)
|
||||
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ExitWater], &getTransform());
|
||||
SFX->playOnce(mDataBlock->getWaterSoundsProfile(RigidShapeData::ExitWater), &getTransform());
|
||||
inLiquid = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include "T3D/physics/physicsBody.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
class ParticleEmitter;
|
||||
class ParticleEmitterData;
|
||||
class ClippedPolyList;
|
||||
|
|
@ -57,11 +59,13 @@ class RigidShapeData : public ShapeBaseData
|
|||
HardImpactSound,
|
||||
MaxSounds,
|
||||
};
|
||||
SFXTrack* sound[MaxSounds];
|
||||
F32 restitution;
|
||||
F32 friction;
|
||||
} body;
|
||||
|
||||
DECLARE_SOUNDASSET_ARRAY(RigidShapeData, BodySounds, Body::Sounds::MaxSounds)
|
||||
DECLARE_ASSET_ARRAY_SETGET(RigidShapeData, BodySounds);
|
||||
|
||||
enum RigidShapeConsts
|
||||
{
|
||||
VC_NUM_DUST_EMITTERS = 1,
|
||||
|
|
@ -79,7 +83,8 @@ class RigidShapeData : public ShapeBaseData
|
|||
Wake,
|
||||
MaxSounds
|
||||
};
|
||||
SFXTrack* waterSound[MaxSounds];
|
||||
DECLARE_SOUNDASSET_ARRAY(RigidShapeData, WaterSounds, Sounds::MaxSounds)
|
||||
DECLARE_ASSET_ARRAY_SETGET(RigidShapeData, WaterSounds);
|
||||
|
||||
F32 exitSplashSoundVel;
|
||||
F32 softSplashSoundVel;
|
||||
|
|
|
|||
|
|
@ -94,22 +94,23 @@ ColorI SFXEmitter::smRenderColorRangeSphere( 200, 0, 0, 90 );
|
|||
SFXEmitter::SFXEmitter()
|
||||
: SceneObject(),
|
||||
mSource( NULL ),
|
||||
mTrack( NULL ),
|
||||
mUseTrackDescriptionOnly( false ),
|
||||
mLocalProfile( &mDescription ),
|
||||
mPlayOnAdd( true )
|
||||
{
|
||||
mTypeMask |= MarkerObjectType;
|
||||
mNetFlags.set( Ghostable | ScopeAlways );
|
||||
|
||||
|
||||
mDescription.mIs3D = true;
|
||||
mDescription.mIsLooping = true;
|
||||
mDescription.mIsStreaming = false;
|
||||
mDescription.mFadeInTime = -1.f;
|
||||
mDescription.mFadeOutTime = -1.f;
|
||||
|
||||
|
||||
mLocalProfile.mFilename = StringTable->EmptyString();
|
||||
mLocalProfile._registerSignals();
|
||||
|
||||
INIT_ASSET(Sound);
|
||||
|
||||
mObjBox.minExtents.set( -1.f, -1.f, -1.f );
|
||||
mObjBox.maxExtents.set( 1.f, 1.f, 1.f );
|
||||
}
|
||||
|
|
@ -174,15 +175,17 @@ void SFXEmitter::consoleInit()
|
|||
void SFXEmitter::initPersistFields()
|
||||
{
|
||||
addGroup( "Media" );
|
||||
|
||||
addField( "track", TypeSFXTrackName, Offset( mTrack, SFXEmitter),
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET(Sound, SFXEmitter, "");
|
||||
|
||||
/*addField("track", TypeSFXTrackName, Offset(mTrack, SFXEmitter),
|
||||
"The track which the emitter should play.\n"
|
||||
"@note If assigned, this field will take precedence over a #fileName that may also be assigned to the "
|
||||
"emitter." );
|
||||
addField( "fileName", TypeStringFilename, Offset( mLocalProfile.mFilename, SFXEmitter),
|
||||
"The sound file to play.\n"
|
||||
"Use @b either this property @b or #track. If both are assigned, #track takes precendence. The primary purpose of this "
|
||||
"field is to avoid the need for the user to define SFXTrack datablocks for all sounds used in a level." );
|
||||
"field is to avoid the need for the user to define SFXTrack datablocks for all sounds used in a level." );*/
|
||||
|
||||
endGroup( "Media");
|
||||
|
||||
|
|
@ -287,12 +290,13 @@ U32 SFXEmitter::packUpdate( NetConnection *con, U32 mask, BitStream *stream )
|
|||
stream->writeAffineTransform( mObjToWorld );
|
||||
|
||||
// track
|
||||
if( stream->writeFlag( mDirty.test( Track ) ) )
|
||||
sfxWrite( stream, mTrack );
|
||||
PACK_ASSET(con, Sound);
|
||||
//if (stream->writeFlag(mDirty.test(Track)))
|
||||
// sfxWrite( stream, mTrack );
|
||||
|
||||
// filename
|
||||
if( stream->writeFlag( mDirty.test( Filename ) ) )
|
||||
stream->writeString( mLocalProfile.mFilename );
|
||||
//if( stream->writeFlag( mDirty.test( Filename ) ) )
|
||||
// stream->writeString( mLocalProfile.mFilename );
|
||||
|
||||
// volume
|
||||
if( stream->writeFlag( mDirty.test( Volume ) ) )
|
||||
|
|
@ -397,7 +401,8 @@ void SFXEmitter::unpackUpdate( NetConnection *conn, BitStream *stream )
|
|||
}
|
||||
|
||||
// track
|
||||
if ( _readDirtyFlag( stream, Track ) )
|
||||
UNPACK_ASSET(conn, Sound);
|
||||
/*if (_readDirtyFlag(stream, Track))
|
||||
{
|
||||
String errorStr;
|
||||
if( !sfxReadAndResolve( stream, &mTrack, errorStr ) )
|
||||
|
|
@ -406,7 +411,7 @@ void SFXEmitter::unpackUpdate( NetConnection *conn, BitStream *stream )
|
|||
|
||||
// filename
|
||||
if ( _readDirtyFlag( stream, Filename ) )
|
||||
mLocalProfile.mFilename = stream->readSTString();
|
||||
mLocalProfile.mFilename = stream->readSTString();*/
|
||||
|
||||
// volume
|
||||
if ( _readDirtyFlag( stream, Volume ) )
|
||||
|
|
@ -586,8 +591,8 @@ void SFXEmitter::inspectPostApply()
|
|||
// Parent will call setScale so sync up scale with distance.
|
||||
|
||||
F32 maxDistance = mDescription.mMaxDistance;
|
||||
if( mUseTrackDescriptionOnly && mTrack )
|
||||
maxDistance = mTrack->getDescription()->mMaxDistance;
|
||||
if( mUseTrackDescriptionOnly && mSoundAsset )
|
||||
maxDistance = mSoundAsset->getSfxDescription()->mMaxDistance;
|
||||
|
||||
mObjScale.set( maxDistance, maxDistance, maxDistance );
|
||||
|
||||
|
|
@ -608,8 +613,8 @@ bool SFXEmitter::onAdd()
|
|||
mDescription.validate();
|
||||
|
||||
// Read an old 'profile' field for backwards-compatibility.
|
||||
|
||||
if( !mTrack )
|
||||
/*
|
||||
if(mSoundAsset.isNull() || !mSoundAsset->getSfxProfile())
|
||||
{
|
||||
static const char* sProfile = StringTable->insert( "profile" );
|
||||
const char* profileName = getDataField( sProfile, NULL );
|
||||
|
|
@ -643,7 +648,7 @@ bool SFXEmitter::onAdd()
|
|||
// Remove the old 'channel' field.
|
||||
setDataField( sChannel, NULL, "" );
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -683,6 +688,12 @@ void SFXEmitter::_update()
|
|||
// we can restore it.
|
||||
SFXStatus prevState = mSource ? mSource->getStatus() : SFXStatusNull;
|
||||
|
||||
if (mSoundAsset.notNull() )
|
||||
{
|
||||
mLocalProfile = *mSoundAsset->getSfxProfile();
|
||||
mDescription = *mSoundAsset->getSfxDescription();
|
||||
}
|
||||
|
||||
// Make sure all the settings are valid.
|
||||
mDescription.validate();
|
||||
|
||||
|
|
@ -695,12 +706,12 @@ void SFXEmitter::_update()
|
|||
SFX_DELETE( mSource );
|
||||
|
||||
// Do we have a track?
|
||||
if( mTrack )
|
||||
if( mSoundAsset && mSoundAsset->getSfxProfile() )
|
||||
{
|
||||
mSource = SFX->createSource( mTrack, &transform, &velocity );
|
||||
mSource = SFX->createSource(mSoundAsset->getSfxProfile(), &transform, &velocity );
|
||||
if( !mSource )
|
||||
Con::errorf( "SFXEmitter::_update() - failed to create sound for track %i (%s)",
|
||||
mTrack->getId(), mTrack->getName() );
|
||||
mSoundAsset->getSfxProfile()->getId(), mSoundAsset->getSfxProfile()->getName() );
|
||||
|
||||
// If we're supposed to play when the emitter is
|
||||
// added to the scene then also restart playback
|
||||
|
|
@ -739,12 +750,12 @@ void SFXEmitter::_update()
|
|||
// is toggled on a local profile sound. It makes the
|
||||
// editor feel responsive and that things are working.
|
||||
if( gEditingMission &&
|
||||
!mTrack &&
|
||||
(mSoundAsset.isNull() || !mSoundAsset->getSfxProfile()) &&
|
||||
mPlayOnAdd &&
|
||||
mDirty.test( IsLooping ) )
|
||||
prevState = SFXStatusPlaying;
|
||||
|
||||
bool useTrackDescriptionOnly = ( mUseTrackDescriptionOnly && mTrack );
|
||||
bool useTrackDescriptionOnly = ( mUseTrackDescriptionOnly && mSoundAsset.notNull() && mSoundAsset->getSfxProfile());
|
||||
|
||||
// The rest only applies if we have a source.
|
||||
if( mSource )
|
||||
|
|
@ -1087,8 +1098,8 @@ SFXStatus SFXEmitter::_getPlaybackStatus() const
|
|||
|
||||
bool SFXEmitter::is3D() const
|
||||
{
|
||||
if( mTrack != NULL )
|
||||
return mTrack->getDescription()->mIs3D;
|
||||
if( mSoundAsset.notNull() && mSoundAsset->getSfxProfile() != NULL )
|
||||
return mSoundAsset->getSfxProfile()->getDescription()->mIs3D;
|
||||
else
|
||||
return mDescription.mIs3D;
|
||||
}
|
||||
|
|
@ -1124,8 +1135,8 @@ void SFXEmitter::setScale( const VectorF &scale )
|
|||
{
|
||||
F32 maxDistance;
|
||||
|
||||
if( mUseTrackDescriptionOnly && mTrack )
|
||||
maxDistance = mTrack->getDescription()->mMaxDistance;
|
||||
if( mUseTrackDescriptionOnly && mSoundAsset.notNull() && mSoundAsset->getSfxProfile())
|
||||
maxDistance = mSoundAsset->getSfxProfile()->getDescription()->mMaxDistance;
|
||||
else
|
||||
{
|
||||
// Use the average of the three coords.
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "gfx/gfxStateBlock.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
class SFXSource;
|
||||
class SFXTrack;
|
||||
|
|
@ -103,13 +104,11 @@ class SFXEmitter : public SceneObject
|
|||
/// The current dirty flags.
|
||||
BitSet32 mDirty;
|
||||
|
||||
DECLARE_SOUNDASSET(SFXEmitter, Sound);
|
||||
DECLARE_ASSET_NET_SETGET(SFXEmitter, Sound, DirtyUpdateMask);
|
||||
|
||||
/// The sound source for the emitter.
|
||||
SFXSource *mSource;
|
||||
|
||||
/// The selected track or null if the local
|
||||
/// profile should be used.
|
||||
SFXTrack *mTrack;
|
||||
|
||||
/// Whether to leave sound setup exclusively to the assigned mTrack and not
|
||||
/// override part of the track's description with emitter properties.
|
||||
bool mUseTrackDescriptionOnly;
|
||||
|
|
|
|||
|
|
@ -197,8 +197,8 @@ ShapeBaseData::ShapeBaseData()
|
|||
renderWhenDestroyed( true ),
|
||||
inheritEnergyFromMount( false )
|
||||
{
|
||||
INIT_SHAPEASSET(Shape);
|
||||
INIT_SHAPEASSET(DebrisShape);
|
||||
INIT_ASSET(Shape);
|
||||
INIT_ASSET(DebrisShape);
|
||||
|
||||
dMemset( mountPointNode, -1, sizeof( S32 ) * SceneObject::NumMountPoints );
|
||||
remap_txr_tags = NULL;
|
||||
|
|
@ -214,13 +214,13 @@ ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : Game
|
|||
shadowProjectionDistance = other.shadowProjectionDistance;
|
||||
shadowSphereAdjust = other.shadowSphereAdjust;
|
||||
cloakTexName = other.cloakTexName;
|
||||
CLONE_SHAPEASSET(Shape);
|
||||
CLONE_ASSET(Shape);
|
||||
cubeDescName = other.cubeDescName;
|
||||
cubeDescId = other.cubeDescId;
|
||||
reflectorDesc = other.reflectorDesc;
|
||||
debris = other.debris;
|
||||
debrisID = other.debrisID; // -- for pack/unpack of debris ptr
|
||||
CLONE_SHAPEASSET(DebrisShape);
|
||||
CLONE_ASSET(DebrisShape);
|
||||
explosion = other.explosion;
|
||||
explosionID = other.explosionID; // -- for pack/unpack of explosion ptr
|
||||
underwaterExplosion = other.underwaterExplosion;
|
||||
|
|
@ -757,8 +757,8 @@ void ShapeBaseData::packData(BitStream* stream)
|
|||
stream->write(shadowProjectionDistance);
|
||||
stream->write(shadowSphereAdjust);
|
||||
|
||||
PACKDATA_SHAPEASSET(Shape);
|
||||
PACKDATA_SHAPEASSET(DebrisShape);
|
||||
PACKDATA_ASSET(Shape);
|
||||
PACKDATA_ASSET(DebrisShape);
|
||||
|
||||
stream->writeString(cloakTexName);
|
||||
if(stream->writeFlag(mass != gShapeBaseDataProto.mass))
|
||||
|
|
@ -835,8 +835,8 @@ void ShapeBaseData::unpackData(BitStream* stream)
|
|||
stream->read(&shadowProjectionDistance);
|
||||
stream->read(&shadowSphereAdjust);
|
||||
|
||||
UNPACKDATA_SHAPEASSET(Shape);
|
||||
UNPACKDATA_SHAPEASSET(DebrisShape);
|
||||
UNPACKDATA_ASSET(Shape);
|
||||
UNPACKDATA_ASSET(DebrisShape);
|
||||
|
||||
cloakTexName = stream->readSTString();
|
||||
if(stream->readFlag())
|
||||
|
|
@ -1009,7 +1009,7 @@ ShapeBase::ShapeBase()
|
|||
|
||||
for (i = 0; i < MaxSoundThreads; i++) {
|
||||
mSoundThread[i].play = false;
|
||||
mSoundThread[i].profile = 0;
|
||||
mSoundThread[i].asset = 0;
|
||||
mSoundThread[i].sound = 0;
|
||||
}
|
||||
|
||||
|
|
@ -2233,24 +2233,30 @@ void ShapeBase::applyImpulse(const Point3F&,const VectorF&)
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void ShapeBase::playAudio(U32 slot,SFXTrack* profile)
|
||||
void ShapeBase::playAudio(U32 slot, StringTableEntry assetId)
|
||||
{
|
||||
AssertFatal( slot < MaxSoundThreads, "ShapeBase::playAudio() bad slot index" );
|
||||
Sound& st = mSoundThread[slot];
|
||||
if( profile && ( !st.play || st.profile != profile ) )
|
||||
if (AssetDatabase.isDeclaredAsset(assetId))
|
||||
{
|
||||
AssetPtr<SoundAsset> tempSoundAsset;
|
||||
tempSoundAsset = assetId;
|
||||
|
||||
SoundThread& st = mSoundThread[slot];
|
||||
if (tempSoundAsset && (!st.play || st.asset != tempSoundAsset))
|
||||
{
|
||||
setMaskBits(SoundMaskN << slot);
|
||||
st.play = true;
|
||||
st.profile = profile;
|
||||
st.asset = tempSoundAsset;
|
||||
updateAudioState(st);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeBase::stopAudio(U32 slot)
|
||||
{
|
||||
AssertFatal( slot < MaxSoundThreads, "ShapeBase::stopAudio() bad slot index" );
|
||||
|
||||
Sound& st = mSoundThread[slot];
|
||||
SoundThread& st = mSoundThread[slot];
|
||||
if ( st.play )
|
||||
{
|
||||
st.play = false;
|
||||
|
|
@ -2263,7 +2269,7 @@ void ShapeBase::updateServerAudio()
|
|||
{
|
||||
// Timeout non-looping sounds
|
||||
for (S32 i = 0; i < MaxSoundThreads; i++) {
|
||||
Sound& st = mSoundThread[i];
|
||||
SoundThread& st = mSoundThread[i];
|
||||
if (st.play && st.timeout && st.timeout < Sim::getCurrentTime()) {
|
||||
clearMaskBits(SoundMaskN << i);
|
||||
st.play = false;
|
||||
|
|
@ -2271,17 +2277,18 @@ void ShapeBase::updateServerAudio()
|
|||
}
|
||||
}
|
||||
|
||||
void ShapeBase::updateAudioState(Sound& st)
|
||||
void ShapeBase::updateAudioState(SoundThread& st)
|
||||
{
|
||||
SFX_DELETE( st.sound );
|
||||
|
||||
if ( st.play && st.profile )
|
||||
if ( st.play && st.asset )
|
||||
{
|
||||
if ( isGhost() )
|
||||
{
|
||||
if ( Sim::findObject( SimObjectId((uintptr_t)st.profile), st.profile ) )
|
||||
// if asset is valid, play
|
||||
if (st.asset->isAssetValid() )
|
||||
{
|
||||
st.sound = SFX->createSource( st.profile, &getTransform() );
|
||||
st.sound = SFX->createSource( st.asset->getSfxProfile() , &getTransform() );
|
||||
if ( st.sound )
|
||||
st.sound->play();
|
||||
}
|
||||
|
|
@ -2292,12 +2299,17 @@ void ShapeBase::updateAudioState(Sound& st)
|
|||
{
|
||||
// Non-looping sounds timeout on the server
|
||||
st.timeout = 0;
|
||||
if ( !st.profile->getDescription()->mIsLooping )
|
||||
if ( !st.asset->getSfxDescription()->mIsLooping )
|
||||
st.timeout = Sim::getCurrentTime() + sAudioTimeout;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// st.sound was not stopped before. If this causes issues remove.
|
||||
st.play = false;
|
||||
if (st.sound)
|
||||
st.sound->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeBase::updateAudioPos()
|
||||
|
|
@ -3122,13 +3134,15 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
|
||||
if (stream->writeFlag(mask & SoundMask)) {
|
||||
for (S32 i = 0; i < MaxSoundThreads; i++) {
|
||||
Sound& st = mSoundThread[i];
|
||||
SoundThread& st = mSoundThread[i];
|
||||
if (stream->writeFlag(mask & (SoundMaskN << i)))
|
||||
if (stream->writeFlag(st.play))
|
||||
stream->writeRangedU32(st.profile->getId(),DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast);
|
||||
{
|
||||
NetStringHandle assetIdStr = st.asset->getAssetId();
|
||||
con->packNetStringHandleU(stream, assetIdStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stream->writeFlag(mask & ImageMask)) {
|
||||
for (S32 i = 0; i < MaxMountedImages; i++)
|
||||
|
|
@ -3242,12 +3256,18 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
{
|
||||
if ( stream->readFlag() )
|
||||
{
|
||||
Sound& st = mSoundThread[i];
|
||||
SoundThread& st = mSoundThread[i];
|
||||
st.play = stream->readFlag();
|
||||
if ( st.play )
|
||||
{
|
||||
st.profile = (SFXTrack*)(uintptr_t)stream->readRangedU32( DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast );
|
||||
StringTableEntry temp = StringTable->insert(con->unpackNetStringHandleU(stream).getString());
|
||||
if (AssetDatabase.isDeclaredAsset(temp))
|
||||
{
|
||||
AssetPtr<SoundAsset> tempSoundAsset;
|
||||
tempSoundAsset = temp;
|
||||
|
||||
st.asset = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isProperlyAdded() )
|
||||
|
|
@ -3777,7 +3797,7 @@ DefineEngineMethod( ShapeBase, isHidden, bool, (),,
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DefineEngineMethod( ShapeBase, playAudio, bool, ( S32 slot, SFXTrack* track ),,
|
||||
DefineEngineMethod( ShapeBase, playAudio, bool, ( S32 slot, StringTableEntry assetId),,
|
||||
"@brief Attach a sound to this shape and start playing it.\n\n"
|
||||
|
||||
"@param slot Audio slot index for the sound (valid range is 0 - 3)\n" // 3 = ShapeBase::MaxSoundThreads-1
|
||||
|
|
@ -3786,8 +3806,8 @@ DefineEngineMethod( ShapeBase, playAudio, bool, ( S32 slot, SFXTrack* track ),,
|
|||
|
||||
"@see stopAudio()\n")
|
||||
{
|
||||
if (track && slot >= 0 && slot < ShapeBase::MaxSoundThreads) {
|
||||
object->playAudio(slot,track);
|
||||
if (assetId && slot >= 0 && slot < ShapeBase::MaxSoundThreads) {
|
||||
object->playAudio(slot, assetId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
|
||||
// Need full definition visible for SimObjectPtr<ParticleEmitter>
|
||||
#include "T3D/fx/particleEmitter.h"
|
||||
#include "T3D/assets/SoundAsset.h"
|
||||
|
||||
class GFXCubemap;
|
||||
class TSShapeInstance;
|
||||
|
|
@ -116,7 +117,7 @@ class ShapeBaseConvex : public Convex
|
|||
Box3F box;
|
||||
|
||||
public:
|
||||
ShapeBaseConvex() :pShapeBase(NULL), transform(NULL), hullId(NULL), nodeTransform(0) { mType = ShapeBaseConvexType; }
|
||||
ShapeBaseConvex() :pShapeBase(NULL), transform(NULL), hullId(0), nodeTransform(0) { mType = ShapeBaseConvexType; }
|
||||
ShapeBaseConvex(const ShapeBaseConvex& cv) {
|
||||
mObject = cv.mObject;
|
||||
pShapeBase = cv.pShapeBase;
|
||||
|
|
@ -259,11 +260,13 @@ struct ShapeBaseImageData: public GameBaseData {
|
|||
/// the imageSlot.
|
||||
ParticleEmitterData* emitter; ///< A particle emitter; this emitter will emit as long as the gun is in this
|
||||
/// this state.
|
||||
SFXTrack* sound;
|
||||
|
||||
//SFXTrack* sound;
|
||||
F32 emitterTime; ///<
|
||||
S32 emitterNode[MaxShapes]; ///< Node ID on the shape to emit from
|
||||
SoundAsset* sound;
|
||||
SFXTrack* soundTrack; ///<Holdover for special, non-asset cases like SFXPlaylists
|
||||
};
|
||||
|
||||
/// @name State Data
|
||||
/// Individual state data used to initialize struct array
|
||||
/// @{
|
||||
|
|
@ -321,7 +324,10 @@ struct ShapeBaseImageData: public GameBaseData {
|
|||
|
||||
bool stateIgnoreLoadedForReady [MaxStates];
|
||||
|
||||
SFXTrack* stateSound [MaxStates];
|
||||
DECLARE_SOUNDASSET_ARRAY(ShapeBaseImageData, stateSound, MaxStates);
|
||||
DECLARE_ASSET_ARRAY_SETGET(ShapeBaseImageData, stateSound);
|
||||
|
||||
//SFXTrack* stateSound [MaxStates];
|
||||
const char* stateScript [MaxStates];
|
||||
|
||||
ParticleEmitterData* stateEmitter [MaxStates];
|
||||
|
|
@ -374,10 +380,10 @@ struct ShapeBaseImageData: public GameBaseData {
|
|||
///< when the script prefix has changed.
|
||||
|
||||
DECLARE_SHAPEASSET_ARRAY(ShapeBaseImageData, Shape, MaxShapes); ///< Name of shape to render.
|
||||
DECLARE_SHAPEASSET_ARRAY_SETGET(ShapeBaseImageData, Shape);
|
||||
DECLARE_ASSET_ARRAY_SETGET(ShapeBaseImageData, Shape);
|
||||
|
||||
//DECLARE_SHAPEASSET(ShapeBaseImageData, ShapeFP); ///< Name of shape to render in first person (optional).
|
||||
//DECLARE_SHAPEASSET_SETGET(ShapeBaseImageData, ShapeFP);
|
||||
//DECLARE_ASSET_SETGET(ShapeBaseImageData, ShapeFP);
|
||||
|
||||
StringTableEntry imageAnimPrefix; ///< Passed along to the mounting shape to modify
|
||||
/// animation sequences played in 3rd person. [optional]
|
||||
|
|
@ -541,7 +547,7 @@ public:
|
|||
F32 shadowSphereAdjust;
|
||||
|
||||
DECLARE_SHAPEASSET(ShapeBaseData, Shape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(ShapeBaseData, Shape);
|
||||
DECLARE_ASSET_SETGET(ShapeBaseData, Shape);
|
||||
|
||||
StringTableEntry cloakTexName;
|
||||
|
||||
|
|
@ -557,7 +563,7 @@ public:
|
|||
S32 debrisID;
|
||||
|
||||
DECLARE_SHAPEASSET(ShapeBaseData, DebrisShape, onDebrisChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(ShapeBaseData, DebrisShape);
|
||||
DECLARE_ASSET_SETGET(ShapeBaseData, DebrisShape);
|
||||
|
||||
ExplosionData* explosion;
|
||||
S32 explosionID;
|
||||
|
|
@ -662,7 +668,7 @@ public:
|
|||
DECLARE_CALLBACK( void, onCollision, ( ShapeBase* obj, SceneObject* collObj, VectorF vec, F32 len ) );
|
||||
DECLARE_CALLBACK( void, onDamage, ( ShapeBase* obj, F32 delta ) );
|
||||
DECLARE_CALLBACK( void, onTrigger, ( ShapeBase* obj, S32 index, bool state ) );
|
||||
DECLARE_CALLBACK(void, onEndSequence, (ShapeBase* obj, S32 slot, const char* name));
|
||||
DECLARE_CALLBACK( void, onEndSequence, (ShapeBase* obj, S32 slot, const char* name));
|
||||
DECLARE_CALLBACK( void, onForceUncloak, ( ShapeBase* obj, const char* reason ) );
|
||||
/// @}
|
||||
struct TextureTagRemapping
|
||||
|
|
@ -739,13 +745,13 @@ protected:
|
|||
|
||||
/// @name Scripted Sound
|
||||
/// @{
|
||||
struct Sound {
|
||||
struct SoundThread {
|
||||
bool play; ///< Are we playing this sound?
|
||||
SimTime timeout; ///< Time until we stop playing this sound.
|
||||
SFXTrack* profile; ///< Profile on server
|
||||
AssetPtr<SoundAsset> asset; ///< Asset on server
|
||||
SFXSource* sound; ///< Sound on client
|
||||
};
|
||||
Sound mSoundThread[MaxSoundThreads];
|
||||
SoundThread mSoundThread[MaxSoundThreads];
|
||||
/// @}
|
||||
|
||||
/// @name Scripted Animation Threads
|
||||
|
|
@ -1109,7 +1115,7 @@ protected:
|
|||
|
||||
/// Updates the audio state of the supplied sound
|
||||
/// @param st Sound
|
||||
void updateAudioState(Sound& st);
|
||||
void updateAudioState(SoundThread& st);
|
||||
|
||||
/// Recalculates the spacial sound based on the current position of the object
|
||||
/// emitting the sound.
|
||||
|
|
@ -1323,9 +1329,7 @@ public:
|
|||
|
||||
/// Plays an audio sound from a mounted object
|
||||
/// @param slot Mount slot ID
|
||||
/// @param track Audio track to play
|
||||
void playAudio(U32 slot,SFXTrack* track);
|
||||
void playAudio( U32 slot, SFXProfile* profile ) { playAudio( slot, ( SFXTrack* ) profile ); }
|
||||
void playAudio(U32 slot, StringTableEntry assetId);
|
||||
|
||||
/// Stops audio from a mounted object
|
||||
/// @param slot Mount slot ID
|
||||
|
|
|
|||
|
|
@ -132,7 +132,8 @@ ShapeBaseImageData::StateData::StateData()
|
|||
loaded = IgnoreLoaded;
|
||||
spin = IgnoreSpin;
|
||||
recoil = NoRecoil;
|
||||
sound = 0;
|
||||
sound = NULL;
|
||||
soundTrack = NULL;
|
||||
emitter = NULL;
|
||||
shapeSequence = NULL;
|
||||
shapeSequenceScale = true;
|
||||
|
|
@ -156,6 +157,7 @@ ShapeBaseImageData::StateData::StateData()
|
|||
flashSequence[i] = false;
|
||||
emitterNode[i] = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static ShapeBaseImageData::StateData gDefaultStateData;
|
||||
|
|
@ -256,7 +258,7 @@ ShapeBaseImageData::ShapeBaseImageData()
|
|||
stateShapeSequence[i] = 0;
|
||||
stateScaleShapeSequence[i] = false;
|
||||
|
||||
stateSound[i] = 0;
|
||||
INIT_ASSET_ARRAY(stateSound, i);
|
||||
stateScript[i] = 0;
|
||||
stateEmitter[i] = 0;
|
||||
stateEmitterTime[i] = 0;
|
||||
|
|
@ -294,7 +296,7 @@ ShapeBaseImageData::ShapeBaseImageData()
|
|||
hasFlash[i] = false;
|
||||
shapeIsValid[i] = false;
|
||||
|
||||
INIT_SHAPEASSET_ARRAY(Shape, i);
|
||||
INIT_ASSET_ARRAY(Shape, i);
|
||||
}
|
||||
|
||||
shakeCamera = false;
|
||||
|
|
@ -303,6 +305,7 @@ ShapeBaseImageData::ShapeBaseImageData()
|
|||
camShakeDuration = 1.5f;
|
||||
camShakeRadius = 3.0f;
|
||||
camShakeFalloff = 10.0f;
|
||||
|
||||
}
|
||||
|
||||
ShapeBaseImageData::~ShapeBaseImageData()
|
||||
|
|
@ -368,7 +371,21 @@ bool ShapeBaseImageData::onAdd()
|
|||
s.shapeSequence = stateShapeSequence[i];
|
||||
s.shapeSequenceScale = stateScaleShapeSequence[i];
|
||||
|
||||
s.sound = stateSound[i];
|
||||
//_setstateSound(getstateSound(i),i);
|
||||
s.sound = getstateSoundAsset(i);
|
||||
if (s.sound == NULL && mstateSoundName[i] != StringTable->EmptyString())
|
||||
{
|
||||
//ok, so we've got some sort of special-case here like a fallback or SFXPlaylist. So do the hook-up now
|
||||
SFXTrack* sndTrack;
|
||||
if (!Sim::findObject(mstateSoundName[i], sndTrack))
|
||||
{
|
||||
Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %s but failed!", mstateSoundName[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.soundTrack = sndTrack;
|
||||
}
|
||||
}
|
||||
s.script = stateScript[i];
|
||||
s.emitter = stateEmitter[i];
|
||||
s.emitterTime = stateEmitterTime[i];
|
||||
|
|
@ -407,7 +424,6 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
{
|
||||
if (!Parent::preload(server, errorStr))
|
||||
return false;
|
||||
bool shapeError = false;
|
||||
|
||||
// Resolve objects transmitted from server
|
||||
if (!server) {
|
||||
|
|
@ -419,10 +435,14 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
if (state[i].emitter)
|
||||
if (!Sim::findObject(SimObjectId((uintptr_t)state[i].emitter), state[i].emitter))
|
||||
Con::errorf(ConsoleLogEntry::General, "Error, unable to load emitter for image datablock");
|
||||
|
||||
String str;
|
||||
if( !sfxResolve( &state[ i ].sound, str ) )
|
||||
Con::errorf( ConsoleLogEntry::General, str.c_str() );
|
||||
|
||||
if (getstateSound(i) != StringTable->EmptyString())
|
||||
{
|
||||
_setstateSound(getstateSound(i), i);
|
||||
if (!getstateSoundProfile(i))
|
||||
Con::errorf("ShapeBaseImageData::preload() - Could not find profile for asset %s on state %d", getstateSound(i), i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -922,8 +942,8 @@ void ShapeBaseImageData::initPersistFields()
|
|||
addField( "stateScaleShapeSequence", TypeBool, Offset(stateScaleShapeSequence, ShapeBaseImageData), MaxStates,
|
||||
"Indicates if the sequence to be played on the mounting shape should be scaled to the length of the state." );
|
||||
|
||||
addField( "stateSound", TypeSFXTrackName, Offset(stateSound, ShapeBaseImageData), MaxStates,
|
||||
"Sound to play on entry to this state." );
|
||||
INITPERSISTFIELD_SOUNDASSET_ARRAY(stateSound, MaxStates, ShapeBaseImageData, "State sound.");
|
||||
|
||||
addField( "stateScript", TypeCaseString, Offset(stateScript, ShapeBaseImageData), MaxStates,
|
||||
"@brief Method to execute on entering this state.\n\n"
|
||||
"Scoped to this image class name, then ShapeBaseImageData. The script "
|
||||
|
|
@ -976,7 +996,7 @@ void ShapeBaseImageData::packData(BitStream* stream)
|
|||
|
||||
for (U32 j = 0; j < MaxShapes; ++j)
|
||||
{
|
||||
PACKDATA_SHAPEASSET_ARRAY(Shape, j); // shape 0 for normal use, shape 1 for first person use (optional)
|
||||
PACKDATA_ASSET_ARRAY(Shape, j); // shape 0 for normal use, shape 1 for first person use (optional)
|
||||
}
|
||||
|
||||
stream->writeString(imageAnimPrefix);
|
||||
|
|
@ -1140,7 +1160,7 @@ void ShapeBaseImageData::packData(BitStream* stream)
|
|||
}
|
||||
}
|
||||
|
||||
sfxWrite( stream, s.sound );
|
||||
PACKDATA_ASSET_ARRAY(stateSound, i);
|
||||
}
|
||||
stream->write(maxConcurrentSounds);
|
||||
stream->writeFlag(useRemainderDT);
|
||||
|
|
@ -1160,7 +1180,7 @@ void ShapeBaseImageData::unpackData(BitStream* stream)
|
|||
|
||||
for (U32 j = 0; j < MaxShapes; ++j)
|
||||
{
|
||||
UNPACKDATA_SHAPEASSET_ARRAY(Shape, j); // shape 0 for normal use, shape 1 for first person use (optional)
|
||||
UNPACKDATA_ASSET_ARRAY(Shape, j); // shape 0 for normal use, shape 1 for first person use (optional)
|
||||
}
|
||||
|
||||
imageAnimPrefix = stream->readSTString();
|
||||
|
|
@ -1345,7 +1365,7 @@ void ShapeBaseImageData::unpackData(BitStream* stream)
|
|||
else
|
||||
s.emitter = 0;
|
||||
|
||||
sfxRead( stream, &s.sound );
|
||||
UNPACKDATA_ASSET_ARRAY(stateSound, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2574,7 +2594,7 @@ bool ShapeBase::hasImageState(U32 imageSlot, const char* state)
|
|||
return false;
|
||||
}
|
||||
|
||||
void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
||||
void ShapeBase::setImageState(U32 imageSlot, U32 newState, bool force)
|
||||
{
|
||||
if (!mMountedImageList[imageSlot].dataBlock)
|
||||
return;
|
||||
|
|
@ -2605,12 +2625,12 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
// Eject shell casing on every state change (client side only)
|
||||
ShapeBaseImageData::StateData& nextStateData = image.dataBlock->state[newState];
|
||||
if (isGhost() && nextStateData.ejectShell) {
|
||||
ejectShellCasing( imageSlot );
|
||||
ejectShellCasing(imageSlot);
|
||||
}
|
||||
|
||||
// Shake camera on client.
|
||||
if (isGhost() && nextStateData.fire && image.dataBlock->shakeCamera) {
|
||||
shakeCamera( imageSlot );
|
||||
shakeCamera(imageSlot);
|
||||
}
|
||||
|
||||
// Server must animate the shape if it is a firestate...
|
||||
|
|
@ -2626,12 +2646,12 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
if (!force && image.state == &image.dataBlock->state[newState]) {
|
||||
image.delayTime = image.state->timeoutValue;
|
||||
if (image.state->script && !isGhost())
|
||||
scriptCallback(imageSlot,image.state->script);
|
||||
scriptCallback(imageSlot, image.state->script);
|
||||
|
||||
// If this is a flash sequence, we need to select a new position for the
|
||||
// animation if we're returning to that state...
|
||||
F32 randomPos = Platform::getRandom();
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
||||
for (U32 i = 0; i < ShapeBaseImageData::MaxShapes; ++i)
|
||||
{
|
||||
if (!image.dataBlock->shapeIsValid[i] || (i != imageShapeIndex && !image.doAnimateAllShapes))
|
||||
continue;
|
||||
|
|
@ -2659,7 +2679,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
|
||||
// Mount pending images
|
||||
if (image.nextImage != InvalidImagePtr && stateData.allowImageChange) {
|
||||
setImage(imageSlot,image.nextImage,image.nextSkinNameHandle,image.nextLoaded);
|
||||
setImage(imageSlot, image.nextImage, image.nextSkinNameHandle, image.nextLoaded);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2667,16 +2687,16 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
// (the first key frame should be it's off state).
|
||||
// We need to do this across all image shapes to make sure we have no hold overs when switching
|
||||
// rendering shapes while in the middle of a state change.
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
||||
for (U32 i = 0; i < ShapeBaseImageData::MaxShapes; ++i)
|
||||
{
|
||||
// If we are to do a sequence transition then we need to keep the previous animThread active
|
||||
if (image.animThread[i] && image.animThread[i]->getSequence()->isCyclic() && (stateData.sequenceNeverTransition || !(stateData.sequenceTransitionIn || lastState->sequenceTransitionOut))) {
|
||||
image.shapeInstance[i]->setPos(image.animThread[i],0);
|
||||
image.shapeInstance[i]->setTimeScale(image.animThread[i],0);
|
||||
image.shapeInstance[i]->setPos(image.animThread[i], 0);
|
||||
image.shapeInstance[i]->setTimeScale(image.animThread[i], 0);
|
||||
}
|
||||
if (image.flashThread[i]) {
|
||||
image.shapeInstance[i]->setPos(image.flashThread[i],0);
|
||||
image.shapeInstance[i]->setTimeScale(image.flashThread[i],0);
|
||||
image.shapeInstance[i]->setPos(image.flashThread[i], 0);
|
||||
image.shapeInstance[i]->setTimeScale(image.flashThread[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2689,10 +2709,10 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
if (image.delayTime <= 0 || !stateData.waitForTimeout)
|
||||
{
|
||||
if ((ns = stateData.transition.loaded[image.loaded]) != -1) {
|
||||
setImageState(imageSlot,ns);
|
||||
setImageState(imageSlot, ns);
|
||||
return;
|
||||
}
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxGenericTriggers; ++i)
|
||||
for (U32 i = 0; i < ShapeBaseImageData::MaxGenericTriggers; ++i)
|
||||
{
|
||||
if ((ns = stateData.transition.genericTrigger[i][image.genericTrigger[i]]) != -1) {
|
||||
setImageState(imageSlot, ns);
|
||||
|
|
@ -2701,7 +2721,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
}
|
||||
//if (!imageData.usesEnergy)
|
||||
if ((ns = stateData.transition.ammo[image.ammo]) != -1) {
|
||||
setImageState(imageSlot,ns);
|
||||
setImageState(imageSlot, ns);
|
||||
return;
|
||||
}
|
||||
if ((ns = stateData.transition.target[image.target]) != -1) {
|
||||
|
|
@ -2717,11 +2737,11 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
return;
|
||||
}
|
||||
if ((ns = stateData.transition.trigger[image.triggerDown]) != -1) {
|
||||
setImageState(imageSlot,ns);
|
||||
setImageState(imageSlot, ns);
|
||||
return;
|
||||
}
|
||||
if ((ns = stateData.transition.altTrigger[image.altTriggerDown]) != -1) {
|
||||
setImageState(imageSlot,ns);
|
||||
setImageState(imageSlot, ns);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -2746,28 +2766,37 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
|
||||
// Apply recoil
|
||||
if (stateData.recoil != ShapeBaseImageData::StateData::NoRecoil)
|
||||
onImageRecoil(imageSlot,stateData.recoil);
|
||||
onImageRecoil(imageSlot, stateData.recoil);
|
||||
|
||||
// Apply image state animation on mounting shape
|
||||
if (stateData.shapeSequence && stateData.shapeSequence[0])
|
||||
{
|
||||
onImageStateAnimation(imageSlot, stateData.shapeSequence, stateData.direction, stateData.shapeSequenceScale, stateData.timeoutValue);
|
||||
}
|
||||
|
||||
// Delete any loooping sounds that were in the previous state.
|
||||
if (lastState->sound && lastState->sound->getDescription()->mIsLooping)
|
||||
// this is the crazy bit =/ needs to know prev state in order to stop sounds.
|
||||
// lastState does not return an id for the prev state so we keep track of it.
|
||||
if (lastState->sound && lastState->sound->getSfxProfile()->getDescription()->mIsLooping)
|
||||
{
|
||||
for(Vector<SFXSource*>::iterator i = image.mSoundSources.begin(); i != image.mSoundSources.end(); i++)
|
||||
for (Vector<SFXSource*>::iterator i = image.mSoundSources.begin(); i != image.mSoundSources.end(); i++)
|
||||
SFX_DELETE((*i));
|
||||
|
||||
image.mSoundSources.clear();
|
||||
}
|
||||
|
||||
// Play sound
|
||||
if( stateData.sound && isGhost() )
|
||||
if (isGhost())
|
||||
{
|
||||
if (stateData.sound)
|
||||
{
|
||||
const Point3F& velocity = getVelocity();
|
||||
image.addSoundSource(SFX->createSource( stateData.sound, &getRenderTransform(), &velocity ));
|
||||
image.addSoundSource(SFX->createSource(stateData.sound->getSfxProfile(), &getRenderTransform(), &velocity));
|
||||
}
|
||||
if (stateData.soundTrack)
|
||||
{
|
||||
const Point3F& velocity = getVelocity();
|
||||
image.addSoundSource(SFX->createSource(stateData.soundTrack, &getRenderTransform(), &velocity));
|
||||
}
|
||||
}
|
||||
|
||||
// Play animation
|
||||
|
|
|
|||
|
|
@ -173,6 +173,13 @@ Trigger::Trigger()
|
|||
mTripOnce = false;
|
||||
mTrippedBy = 0xFFFFFFFF;
|
||||
mTripCondition = "";
|
||||
|
||||
//Default up a basic square
|
||||
Point3F vecs[3] = { Point3F(1.0, 0.0, 0.0),
|
||||
Point3F(0.0, -1.0, 0.0),
|
||||
Point3F(0.0, 0.0, 1.0) };
|
||||
|
||||
mTriggerPolyhedron = Polyhedron(Point3F(-0.5, 0.5, 0.0), vecs);
|
||||
}
|
||||
|
||||
Trigger::~Trigger()
|
||||
|
|
@ -731,7 +738,8 @@ void Trigger::potentialEnterObject(GameBase* enter)
|
|||
|
||||
if(evalCmD(&mEnterCommand))
|
||||
{
|
||||
String command = String("%obj = ") + enter->getIdString() + ";" + mEnterCommand;
|
||||
String command = String("%obj = ") + enter->getIdString() + ";";
|
||||
command = command + String("%this = ") + getIdString() + ";" + mEnterCommand;
|
||||
Con::evaluate(command.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -779,7 +787,8 @@ void Trigger::processTick(const Move* move)
|
|||
|
||||
if (evalCmD(&mLeaveCommand))
|
||||
{
|
||||
String command = String("%obj = ") + remove->getIdString() + ";" + mLeaveCommand;
|
||||
String command = String("%obj = ") + remove->getIdString() + ";";
|
||||
command = command + String("%this = ") + getIdString() + ";" + mLeaveCommand;
|
||||
Con::evaluate(command.c_str());
|
||||
}
|
||||
if (testTrippable() && testCondition())
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#include "materials/materialFeatureTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "T3D/accumulationVolume.h"
|
||||
#include "math/mTransform.h"
|
||||
|
||||
#include "gui/editor/inspector/group.h"
|
||||
#include "console/typeValidators.h"
|
||||
|
|
@ -149,7 +150,7 @@ TSStatic::TSStatic()
|
|||
mAnimOffset = 0.0f;
|
||||
mAnimSpeed = 1.0f;
|
||||
|
||||
INIT_SHAPEASSET(Shape);
|
||||
INIT_ASSET(Shape);
|
||||
}
|
||||
|
||||
TSStatic::~TSStatic()
|
||||
|
|
@ -418,6 +419,8 @@ bool TSStatic::_createShape()
|
|||
// Reapply the current skin
|
||||
mAppliedSkinName = "";
|
||||
reSkin();
|
||||
|
||||
updateMaterials();
|
||||
}
|
||||
|
||||
prepCollision();
|
||||
|
|
@ -958,7 +961,7 @@ U32 TSStatic::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
|||
|
||||
if (stream->writeFlag(mask & AdvancedStaticOptionsMask))
|
||||
{
|
||||
PACK_SHAPEASSET(con, Shape);
|
||||
PACK_ASSET(con, Shape);
|
||||
|
||||
stream->write((U32)mDecalType);
|
||||
|
||||
|
|
@ -1015,7 +1018,7 @@ U32 TSStatic::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
|||
con->packNetStringHandleU(stream, matNameStr);
|
||||
}
|
||||
|
||||
mChangingMaterials.clear();
|
||||
//mChangingMaterials.clear();
|
||||
}
|
||||
|
||||
return retMask;
|
||||
|
|
@ -1073,7 +1076,7 @@ void TSStatic::unpackUpdate(NetConnection* con, BitStream* stream)
|
|||
|
||||
if (stream->readFlag()) // AdvancedStaticOptionsMask
|
||||
{
|
||||
UNPACK_SHAPEASSET(con, Shape);
|
||||
UNPACK_ASSET(con, Shape);
|
||||
|
||||
stream->read((U32*)&mDecalType);
|
||||
|
||||
|
|
@ -1085,15 +1088,16 @@ void TSStatic::unpackUpdate(NetConnection* con, BitStream* stream)
|
|||
|
||||
stream->read(&mForceDetail);
|
||||
|
||||
if (stream->readFlag())
|
||||
mAnimOffset = stream->readFloat(7);
|
||||
if (stream->readFlag())
|
||||
mAnimOffset = stream->readFloat(7);
|
||||
|
||||
if (stream->readFlag())
|
||||
mAnimSpeed = stream->readSignedFloat(7) * AnimSpeedMax;
|
||||
if (stream->readFlag())
|
||||
mAnimSpeed = stream->readSignedFloat(7) * AnimSpeedMax;
|
||||
|
||||
mPlayAmbient = stream->readFlag();
|
||||
|
||||
|
||||
//update our shape, figuring that it likely changed
|
||||
_createShape();
|
||||
}
|
||||
|
||||
mUseAlphaFade = stream->readFlag();
|
||||
|
|
@ -1585,7 +1589,7 @@ U32 TSStatic::getNumDetails()
|
|||
|
||||
void TSStatic::updateMaterials()
|
||||
{
|
||||
if (mChangingMaterials.empty() || !mShape)
|
||||
if (mChangingMaterials.empty() || !mShapeInstance)
|
||||
return;
|
||||
|
||||
TSMaterialList* pMatList = mShapeInstance->getMaterialList();
|
||||
|
|
@ -1617,8 +1621,6 @@ void TSStatic::updateMaterials()
|
|||
}
|
||||
}
|
||||
|
||||
mChangingMaterials.clear();
|
||||
|
||||
// Initialize the material instances
|
||||
mShapeInstance->initMaterialList();
|
||||
}
|
||||
|
|
@ -1670,53 +1672,45 @@ void TSStatic::onInspect(GuiInspector* inspector)
|
|||
{
|
||||
StringTableEntry materialname = StringTable->insert(mShapeAsset->getShape()->materialList->getMaterialName(i).c_str());
|
||||
|
||||
//Iterate through our assetList to find the compliant entry in our matList
|
||||
for (U32 m = 0; m < mShapeAsset->getMaterialCount(); m++)
|
||||
AssetPtr<MaterialAsset> matAsset;
|
||||
if(MaterialAsset::getAssetByMaterialName(materialname, &matAsset) == MaterialAsset::Ok)
|
||||
{
|
||||
AssetPtr<MaterialAsset> matAsset = mShapeAsset->getMaterialAsset(m);
|
||||
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
|
||||
|
||||
if (matAsset->getMaterialDefinitionName() == materialname)
|
||||
GuiInspectorField* fieldGui = materialGroup->constructField(TypeMaterialAssetPtr);
|
||||
fieldGui->init(inspector, materialGroup);
|
||||
|
||||
fieldGui->setSpecialEditField(true);
|
||||
fieldGui->setTargetObject(this);
|
||||
|
||||
StringTableEntry fldnm = StringTable->insert(matFieldName);
|
||||
|
||||
fieldGui->setSpecialEditVariableName(fldnm);
|
||||
|
||||
fieldGui->setInspectorField(NULL, fldnm);
|
||||
fieldGui->setDocs("");
|
||||
|
||||
if (fieldGui->registerObject())
|
||||
{
|
||||
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
|
||||
StringTableEntry fieldValue = matAsset->getAssetId();
|
||||
|
||||
//addComponentField(matFieldName, "A material used in the shape file", "Material", matAsset->getAssetId(), "");
|
||||
//Con::executef(this, "onConstructComponentField", mTargetComponent, field->mFieldName);
|
||||
Con::printf("Added material field for MaterialSlot %d", i);
|
||||
|
||||
GuiInspectorField* fieldGui = materialGroup->constructField(TypeMaterialAssetPtr);
|
||||
fieldGui->init(inspector, materialGroup);
|
||||
|
||||
fieldGui->setSpecialEditField(true);
|
||||
fieldGui->setTargetObject(this);
|
||||
|
||||
StringTableEntry fldnm = StringTable->insert(matFieldName);
|
||||
|
||||
fieldGui->setSpecialEditVariableName(fldnm);
|
||||
|
||||
fieldGui->setInspectorField(NULL, fldnm);
|
||||
fieldGui->setDocs("");
|
||||
|
||||
if (fieldGui->registerObject())
|
||||
//Check if we'd already actually changed it, and display the modified value
|
||||
for (U32 c = 0; c < mChangingMaterials.size(); c++)
|
||||
{
|
||||
fieldGui->setValue(materialname);
|
||||
|
||||
stack->addObject(fieldGui);
|
||||
}
|
||||
else
|
||||
{
|
||||
SAFE_DELETE(fieldGui);
|
||||
if (mChangingMaterials[c].slot == i)
|
||||
{
|
||||
fieldValue = StringTable->insert(mChangingMaterials[i].assetId.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*if (materialGroup->isMethod("onConstructField"))
|
||||
{
|
||||
//ensure our stack variable is bound if we need it
|
||||
//Con::evaluatef("%d.stack = %d;", materialGroup->getId(), materialGroup->at(0)->getId());
|
||||
fieldGui->setValue(fieldValue);
|
||||
|
||||
Con::executef(materialGroup, "onConstructField", matFieldName,
|
||||
matFieldName, "material", matFieldName,
|
||||
materialname, "", "", this);
|
||||
}*/
|
||||
break;
|
||||
stack->addObject(fieldGui);
|
||||
}
|
||||
else
|
||||
{
|
||||
SAFE_DELETE(fieldGui);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1871,3 +1865,31 @@ void TSStatic::setSelectionFlags(U8 flags)
|
|||
}
|
||||
}
|
||||
|
||||
void TSStatic::getNodeTransform(const char *nodeName, const MatrixF &xfm, MatrixF *outMat)
|
||||
{
|
||||
|
||||
S32 nodeIDx = getShapeResource()->findNode(nodeName);
|
||||
|
||||
MatrixF mountTransform = mShapeInstance->mNodeTransforms[nodeIDx];
|
||||
mountTransform.mul(xfm);
|
||||
const Point3F &scale = getScale();
|
||||
// The position of the mount point needs to be scaled.
|
||||
Point3F position = mountTransform.getPosition();
|
||||
position.convolve(scale);
|
||||
mountTransform.setPosition(position);
|
||||
// Also we would like the object to be scaled to the model.
|
||||
outMat->mul(mObjToWorld, mountTransform);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
DefineEngineMethod(TSStatic, getNodeTransform, TransformF, (const char *nodeName), ,
|
||||
"@brief Get the world transform of the specified mount slot.\n\n"
|
||||
|
||||
"@param slot Image slot to query\n"
|
||||
"@return the mount transform\n\n")
|
||||
{
|
||||
MatrixF xf(true);
|
||||
object->getNodeTransform(nodeName, MatrixF::Identity, &xf);
|
||||
return xf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ protected:
|
|||
Convex* mConvexList;
|
||||
|
||||
DECLARE_SHAPEASSET(TSStatic, Shape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_NET_SETGET(TSStatic, Shape, AdvancedStaticOptionsMask);
|
||||
DECLARE_ASSET_NET_SETGET(TSStatic, Shape, AdvancedStaticOptionsMask);
|
||||
|
||||
U32 mShapeHash;
|
||||
Vector<S32> mCollisionDetails;
|
||||
|
|
@ -276,6 +276,7 @@ public:
|
|||
void updateMaterials();
|
||||
|
||||
bool isAnimated() { return mPlayAmbient; }
|
||||
void getNodeTransform(const char *nodeName, const MatrixF &xfm, MatrixF *outMat);
|
||||
|
||||
virtual void getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList);
|
||||
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ ConsoleDocClass( TurretShape,
|
|||
|
||||
TurretShape::TurretShape()
|
||||
{
|
||||
mTypeMask |= VehicleObjectType | DynamicShapeObjectType;
|
||||
mTypeMask |= VehicleObjectType | DynamicShapeObjectType | TurretObjectType;
|
||||
mDataBlock = 0;
|
||||
|
||||
allowManualRotation = true;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ FlyingVehicleData::FlyingVehicleData()
|
|||
jetEmitter[j] = 0;
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
sound[i] = 0;
|
||||
INIT_ASSET_ARRAY(FlyingSounds, i);
|
||||
|
||||
vertThrustMultiple = 1.0;
|
||||
}
|
||||
|
|
@ -131,9 +131,12 @@ bool FlyingVehicleData::preload(bool server, String &errorStr)
|
|||
// Resolve objects transmitted from server
|
||||
if (!server) {
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
if (sound[i])
|
||||
Sim::findObject(SimObjectId((uintptr_t)sound[i]),sound[i]);
|
||||
|
||||
{
|
||||
if (mFlyingSounds[i])
|
||||
{
|
||||
_setFlyingSounds(getFlyingSounds(i), i);
|
||||
}
|
||||
}
|
||||
for (S32 j = 0; j < MaxJetEmitters; j++)
|
||||
if (jetEmitter[j])
|
||||
Sim::findObject(SimObjectId((uintptr_t)jetEmitter[j]),jetEmitter[j]);
|
||||
|
|
@ -163,10 +166,8 @@ bool FlyingVehicleData::preload(bool server, String &errorStr)
|
|||
|
||||
void FlyingVehicleData::initPersistFields()
|
||||
{
|
||||
addField( "jetSound", TYPEID< SFXProfile >(), Offset(sound[JetSound], FlyingVehicleData),
|
||||
"Looping sound to play while the vehicle is jetting." );
|
||||
addField( "engineSound", TYPEID< SFXProfile >(), Offset(sound[EngineSound], FlyingVehicleData),
|
||||
"Looping engine sound." );
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET_ARRAY(FlyingSounds, Sounds::MaxSounds, FlyingVehicleData, "Sounds for flying vehicle");
|
||||
|
||||
addField( "maneuveringForce", TypeF32, Offset(maneuveringForce, FlyingVehicleData),
|
||||
"@brief Maximum X and Y (horizontal plane) maneuvering force.\n\n"
|
||||
|
|
@ -240,11 +241,7 @@ void FlyingVehicleData::packData(BitStream* stream)
|
|||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
{
|
||||
if (stream->writeFlag(sound[i]))
|
||||
{
|
||||
SimObjectId writtenId = mPacked ? SimObjectId((uintptr_t)sound[i]) : sound[i]->getId();
|
||||
stream->writeRangedU32(writtenId, DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
}
|
||||
PACKDATA_ASSET_ARRAY(FlyingSounds, i);
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < MaxJetEmitters; j++)
|
||||
|
|
@ -277,11 +274,9 @@ void FlyingVehicleData::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++) {
|
||||
sound[i] = NULL;
|
||||
if (stream->readFlag())
|
||||
sound[i] = (SFXProfile*)(uintptr_t)stream->readRangedU32(DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast);
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
{
|
||||
UNPACKDATA_ASSET_ARRAY(FlyingSounds, i);
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < MaxJetEmitters; j++) {
|
||||
|
|
@ -353,9 +348,6 @@ bool FlyingVehicle::onAdd()
|
|||
return false;
|
||||
|
||||
addToScene();
|
||||
|
||||
if (isServerObject())
|
||||
scriptOnAdd();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -374,11 +366,11 @@ bool FlyingVehicle::onNewDataBlock(GameBaseData* dptr, bool reload)
|
|||
SFX_DELETE( mJetSound );
|
||||
SFX_DELETE( mEngineSound );
|
||||
|
||||
if ( mDataBlock->sound[FlyingVehicleData::EngineSound] )
|
||||
mEngineSound = SFX->createSource( mDataBlock->sound[FlyingVehicleData::EngineSound], &getTransform() );
|
||||
if ( mDataBlock->getFlyingSounds(FlyingVehicleData::EngineSound) )
|
||||
mEngineSound = SFX->createSource( mDataBlock->getFlyingSoundsProfile(FlyingVehicleData::EngineSound), &getTransform() );
|
||||
|
||||
if ( mDataBlock->sound[FlyingVehicleData::JetSound] )
|
||||
mJetSound = SFX->createSource( mDataBlock->sound[FlyingVehicleData::JetSound], &getTransform() );
|
||||
if ( mDataBlock->getFlyingSounds(FlyingVehicleData::JetSound))
|
||||
mJetSound = SFX->createSource( mDataBlock->getFlyingSoundsProfile(FlyingVehicleData::JetSound), &getTransform() );
|
||||
}
|
||||
|
||||
// Jet Sequences
|
||||
|
|
@ -405,7 +397,6 @@ void FlyingVehicle::onRemove()
|
|||
SFX_DELETE( mJetSound );
|
||||
SFX_DELETE( mEngineSound );
|
||||
|
||||
scriptOnRemove();
|
||||
removeFromScene();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ struct FlyingVehicleData: public VehicleData {
|
|||
EngineSound,
|
||||
MaxSounds,
|
||||
};
|
||||
SFXProfile* sound[MaxSounds];
|
||||
DECLARE_SOUNDASSET_ARRAY(FlyingVehicleData, FlyingSounds, Sounds::MaxSounds);
|
||||
DECLARE_ASSET_ARRAY_SETGET(FlyingVehicleData, FlyingSounds);
|
||||
|
||||
enum Jets {
|
||||
// These enums index into a static name list.
|
||||
|
|
|
|||
|
|
@ -68,6 +68,16 @@ ConsoleDocClass( HoverVehicle,
|
|||
"@ingroup Vehicles\n"
|
||||
);
|
||||
|
||||
typedef HoverVehicleData::Sounds hoverSoundsEnum;
|
||||
DefineEnumType(hoverSoundsEnum);
|
||||
|
||||
ImplementEnumType(hoverSoundsEnum, "enum types.\n"
|
||||
"@ingroup HoverVehicleData\n\n")
|
||||
{ HoverVehicleData::JetSound, "JetSound", "..." },
|
||||
{ HoverVehicleData::EngineSound, "EngineSound", "..." },
|
||||
{ HoverVehicleData::FloatSound, "FloatSound", "..." },
|
||||
EndImplementEnumType;
|
||||
|
||||
namespace {
|
||||
|
||||
const U32 sCollisionMoveMask = (TerrainObjectType | PlayerObjectType |
|
||||
|
|
@ -152,7 +162,7 @@ HoverVehicleData::HoverVehicleData()
|
|||
jetEmitter[j] = 0;
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
sound[i] = 0;
|
||||
INIT_ASSET_ARRAY(HoverSounds, i);
|
||||
}
|
||||
|
||||
HoverVehicleData::~HoverVehicleData()
|
||||
|
|
@ -232,14 +242,8 @@ void HoverVehicleData::initPersistFields()
|
|||
addField( "pitchForce", TypeF32, Offset(pitchForce, HoverVehicleData),
|
||||
"Pitch (rotation about the X-axis) force applied when steering in the y-axis direction." );
|
||||
|
||||
addField( "jetSound", TYPEID< SFXProfile >(), Offset(sound[JetSound], HoverVehicleData),
|
||||
"Looping sound played when the vehicle is jetting." );
|
||||
addField( "engineSound", TYPEID< SFXProfile >(), Offset(sound[EngineSound], HoverVehicleData),
|
||||
"Looping engine sound.\nThe volume is dynamically adjusted based on the "
|
||||
"current thrust level." );
|
||||
addField( "floatSound", TYPEID< SFXProfile >(), Offset(sound[FloatSound], HoverVehicleData),
|
||||
"Looping sound played while the vehicle is floating.\n\n@see stabMinLen" );
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET_ENUMED(HoverSounds, hoverSoundsEnum, Sounds::MaxSounds, HoverVehicleData, "Sounds for hover vehicle.");
|
||||
|
||||
addField( "dustTrailEmitter", TYPEID< ParticleEmitterData >(), Offset(dustTrailEmitter, HoverVehicleData),
|
||||
"Emitter to generate particles for the vehicle's dust trail.\nThe trail "
|
||||
"of dust particles is generated only while the vehicle is moving." );
|
||||
|
|
@ -311,9 +315,13 @@ bool HoverVehicleData::preload(bool server, String &errorStr)
|
|||
|
||||
// Resolve objects transmitted from server
|
||||
if (!server) {
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
if (sound[i])
|
||||
Sim::findObject(SimObjectId((uintptr_t)sound[i]),sound[i]);
|
||||
if (getHoverSounds(i) != StringTable->EmptyString())
|
||||
{
|
||||
_setHoverSounds(getHoverSounds(i), i);
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < MaxJetEmitters; j++)
|
||||
if (jetEmitter[j])
|
||||
Sim::findObject(SimObjectId((uintptr_t)jetEmitter[j]),jetEmitter[j]);
|
||||
|
|
@ -361,9 +369,9 @@ void HoverVehicleData::packData(BitStream* stream)
|
|||
stream->write(dustTrailFreqMod);
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
if (stream->writeFlag(sound[i]))
|
||||
stream->writeRangedU32(mPacked ? SimObjectId((uintptr_t)sound[i]):
|
||||
sound[i]->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
|
||||
{
|
||||
PACKDATA_ASSET_ARRAY(HoverSounds, i);
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < MaxJetEmitters; j++)
|
||||
{
|
||||
|
|
@ -410,9 +418,9 @@ void HoverVehicleData::unpackData(BitStream* stream)
|
|||
stream->read(&dustTrailFreqMod);
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
sound[i] = stream->readFlag()?
|
||||
(SFXProfile*)(uintptr_t)stream->readRangedU32(DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast): 0;
|
||||
{
|
||||
UNPACKDATA_ASSET_ARRAY(HoverSounds, i);
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < MaxJetEmitters; j++) {
|
||||
jetEmitter[j] = NULL;
|
||||
|
|
@ -504,10 +512,6 @@ bool HoverVehicle::onAdd()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (isServerObject())
|
||||
scriptOnAdd();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -518,7 +522,6 @@ void HoverVehicle::onRemove()
|
|||
SFX_DELETE( mEngineSound );
|
||||
SFX_DELETE( mFloatSound );
|
||||
|
||||
scriptOnRemove();
|
||||
removeFromScene();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
@ -539,14 +542,14 @@ bool HoverVehicle::onNewDataBlock(GameBaseData* dptr, bool reload)
|
|||
SFX_DELETE( mFloatSound );
|
||||
SFX_DELETE( mJetSound );
|
||||
|
||||
if ( mDataBlock->sound[HoverVehicleData::EngineSound] )
|
||||
mEngineSound = SFX->createSource( mDataBlock->sound[HoverVehicleData::EngineSound], &getTransform() );
|
||||
if ( mDataBlock->getHoverSounds(HoverVehicleData::EngineSound) )
|
||||
mEngineSound = SFX->createSource( mDataBlock->getHoverSoundsProfile(HoverVehicleData::EngineSound), &getTransform() );
|
||||
|
||||
if ( !mDataBlock->sound[HoverVehicleData::FloatSound] )
|
||||
mFloatSound = SFX->createSource( mDataBlock->sound[HoverVehicleData::FloatSound], &getTransform() );
|
||||
if ( !mDataBlock->getHoverSounds(HoverVehicleData::FloatSound) )
|
||||
mFloatSound = SFX->createSource( mDataBlock->getHoverSoundsProfile(HoverVehicleData::FloatSound), &getTransform() );
|
||||
|
||||
if ( mDataBlock->sound[HoverVehicleData::JetSound] )
|
||||
mJetSound = SFX->createSource( mDataBlock->sound[HoverVehicleData::JetSound], &getTransform() );
|
||||
if ( mDataBlock->getHoverSounds(HoverVehicleData::JetSound) )
|
||||
mJetSound = SFX->createSource( mDataBlock->getHoverSoundsProfile(HoverVehicleData::JetSound), &getTransform() );
|
||||
}
|
||||
|
||||
// Todo: Uncomment if this is a "leaf" class
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class HoverVehicleData : public VehicleData
|
|||
FloatSound,
|
||||
MaxSounds
|
||||
};
|
||||
SFXProfile* sound[MaxSounds];
|
||||
DECLARE_SOUNDASSET_ARRAY(HoverVehicleData, HoverSounds, Sounds::MaxSounds);
|
||||
|
||||
enum Jets {
|
||||
// These enums index into a static name list.
|
||||
|
|
|
|||
|
|
@ -80,6 +80,28 @@ static U32 sTriggerMask = ItemObjectType |
|
|||
|
||||
IMPLEMENT_CONOBJECT(VehicleData);
|
||||
|
||||
typedef VehicleData::Body::Sounds bodySounds;
|
||||
DefineEnumType(bodySounds);
|
||||
|
||||
ImplementEnumType(bodySounds, "enum types.\n"
|
||||
"@ingroup VehicleData\n\n")
|
||||
{ VehicleData::Body::SoftImpactSound, "SoftImpactSound", "..." },
|
||||
{ VehicleData::Body::HardImpactSound, "HardImpactSound", "..." },
|
||||
EndImplementEnumType;
|
||||
|
||||
|
||||
typedef VehicleData::Sounds vehSoundsEnum;
|
||||
DefineEnumType(vehSoundsEnum);
|
||||
|
||||
ImplementEnumType(vehSoundsEnum, "enum types.\n"
|
||||
"@ingroup VehicleData\n\n")
|
||||
{ VehicleData::ExitWater, "ExitWater", "..." },
|
||||
{ VehicleData::ImpactSoft, "ImpactSoft", "..." },
|
||||
{ VehicleData::ImpactMedium, "ImpactMedium", "..." },
|
||||
{ VehicleData::ImpactHard, "ImpactHard", "..." },
|
||||
{ VehicleData::Wake, "Wake", "..." },
|
||||
EndImplementEnumType;
|
||||
|
||||
ConsoleDocClass( VehicleData,
|
||||
"@brief Base properties shared by all Vehicles (FlyingVehicle, HoverVehicle, "
|
||||
"WheeledVehicle).\n\n"
|
||||
|
|
@ -166,7 +188,9 @@ VehicleData::VehicleData()
|
|||
powerSteering = false;
|
||||
|
||||
for (S32 i = 0; i < Body::MaxSounds; i++)
|
||||
body.sound[i] = 0;
|
||||
{
|
||||
INIT_ASSET_ARRAY(VehicleBodySounds, i);
|
||||
}
|
||||
|
||||
dustEmitter = NULL;
|
||||
dustID = 0;
|
||||
|
|
@ -189,7 +213,8 @@ VehicleData::VehicleData()
|
|||
medSplashSoundVel = 2.0;
|
||||
hardSplashSoundVel = 3.0;
|
||||
|
||||
dMemset(waterSound, 0, sizeof(waterSound));
|
||||
for (S32 i = 0; i < Sounds::MaxSounds; i++)
|
||||
INIT_ASSET_ARRAY(VehicleWaterSounds, i);
|
||||
|
||||
collDamageThresholdVel = 20;
|
||||
collDamageMultiplier = 0.05f;
|
||||
|
|
@ -215,8 +240,20 @@ bool VehicleData::preload(bool server, String &errorStr)
|
|||
// Resolve objects transmitted from server
|
||||
if (!server) {
|
||||
for (S32 i = 0; i < Body::MaxSounds; i++)
|
||||
if (body.sound[i])
|
||||
Sim::findObject(SimObjectId((uintptr_t)body.sound[i]),body.sound[i]);
|
||||
{
|
||||
if (getVehicleBodySounds(i) != StringTable->EmptyString() )
|
||||
{
|
||||
_setVehicleBodySounds(getVehicleBodySounds(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < Sounds::MaxSounds; j++)
|
||||
{
|
||||
if (getVehicleWaterSounds(j) != StringTable->EmptyString())
|
||||
{
|
||||
_setVehicleWaterSounds(getVehicleWaterSounds(j), j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !dustEmitter && dustID != 0 )
|
||||
|
|
@ -264,10 +301,9 @@ void VehicleData::packData(BitStream* stream)
|
|||
stream->write(body.restitution);
|
||||
stream->write(body.friction);
|
||||
for (i = 0; i < Body::MaxSounds; i++)
|
||||
if (stream->writeFlag(body.sound[i]))
|
||||
stream->writeRangedU32(mPacked ? SimObjectId((uintptr_t)body.sound[i]):
|
||||
body.sound[i]->getId(),DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast);
|
||||
{
|
||||
PACKDATA_ASSET_ARRAY(VehicleBodySounds, i);
|
||||
}
|
||||
|
||||
stream->write(minImpactSpeed);
|
||||
stream->write(softImpactSpeed);
|
||||
|
|
@ -308,9 +344,10 @@ void VehicleData::packData(BitStream* stream)
|
|||
stream->write(enablePhysicsRep);
|
||||
|
||||
// write the water sound profiles
|
||||
for(i = 0; i < MaxSounds; i++)
|
||||
if(stream->writeFlag(waterSound[i]))
|
||||
stream->writeRangedU32(waterSound[i]->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
for (i = 0; i < MaxSounds; i++)
|
||||
{
|
||||
PACKDATA_ASSET_ARRAY(VehicleWaterSounds, i);
|
||||
}
|
||||
|
||||
if (stream->writeFlag( dustEmitter ))
|
||||
{
|
||||
|
|
@ -359,11 +396,9 @@ void VehicleData::unpackData(BitStream* stream)
|
|||
stream->read(&body.restitution);
|
||||
stream->read(&body.friction);
|
||||
S32 i;
|
||||
for (i = 0; i < Body::MaxSounds; i++) {
|
||||
body.sound[i] = NULL;
|
||||
if (stream->readFlag())
|
||||
body.sound[i] = (SFXProfile*)(uintptr_t)stream->readRangedU32(DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast);
|
||||
for (i = 0; i < Body::MaxSounds; i++)
|
||||
{
|
||||
UNPACKDATA_ASSET_ARRAY(VehicleBodySounds, i);
|
||||
}
|
||||
|
||||
stream->read(&minImpactSpeed);
|
||||
|
|
@ -405,12 +440,10 @@ void VehicleData::unpackData(BitStream* stream)
|
|||
stream->read(&enablePhysicsRep);
|
||||
|
||||
// write the water sound profiles
|
||||
for(i = 0; i < MaxSounds; i++)
|
||||
if(stream->readFlag())
|
||||
{
|
||||
U32 id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
waterSound[i] = dynamic_cast<SFXProfile*>( Sim::findObject(id) );
|
||||
}
|
||||
for (i = 0; i < Sounds::MaxSounds; i++)
|
||||
{
|
||||
UNPACKDATA_ASSET_ARRAY(VehicleWaterSounds, i);
|
||||
}
|
||||
|
||||
if( stream->readFlag() )
|
||||
{
|
||||
|
|
@ -491,15 +524,8 @@ void VehicleData::initPersistFields()
|
|||
addField( "bodyFriction", TypeF32, Offset(body.friction, VehicleData),
|
||||
"Collision friction coefficient.\nHow well this object will slide against "
|
||||
"objects it collides with." );
|
||||
addField( "softImpactSound", TYPEID< SFXProfile >(), Offset(body.sound[Body::SoftImpactSound], VehicleData),
|
||||
"@brief Sound to play on a 'soft' impact.\n\n"
|
||||
"This sound is played if the impact speed is < hardImpactSpeed and >= "
|
||||
"softImpactSpeed.\n\n"
|
||||
"@see softImpactSpeed" );
|
||||
addField( "hardImpactSound", TYPEID< SFXProfile >(), Offset(body.sound[Body::HardImpactSound], VehicleData),
|
||||
"@brief Sound to play on a 'hard' impact.\n\n"
|
||||
"This sound is played if the impact speed >= hardImpactSpeed.\n\n"
|
||||
"@see hardImpactSpeed" );
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET_ENUMED(VehicleBodySounds, bodySounds, Body::Sounds::MaxSounds, VehicleData, "Sounds for vehicle body impacts.");
|
||||
|
||||
addField( "minImpactSpeed", TypeF32, Offset(minImpactSpeed, VehicleData),
|
||||
"Minimum collision speed for the onImpact callback to be invoked." );
|
||||
|
|
@ -596,18 +622,8 @@ void VehicleData::initPersistFields()
|
|||
addField( "hardSplashSoundVelocity", TypeF32, Offset(hardSplashSoundVel, VehicleData),
|
||||
"Minimum velocity when entering the water for the imapactWaterHard sound "
|
||||
"to play.\n\n@see impactWaterHard" );
|
||||
addField( "exitingWater", TYPEID< SFXProfile >(), Offset(waterSound[ExitWater], VehicleData),
|
||||
"Sound to play when exiting the water." );
|
||||
addField( "impactWaterEasy", TYPEID< SFXProfile >(), Offset(waterSound[ImpactSoft], VehicleData),
|
||||
"Sound to play when entering the water with speed >= softSplashSoundVelocity "
|
||||
"and < mediumSplashSoundVelocity." );
|
||||
addField( "impactWaterMedium", TYPEID< SFXProfile >(), Offset(waterSound[ImpactMedium], VehicleData),
|
||||
"Sound to play when entering the water with speed >= mediumSplashSoundVelocity "
|
||||
"and < hardSplashSoundVelocity." );
|
||||
addField( "impactWaterHard", TYPEID< SFXProfile >(), Offset(waterSound[ImpactHard], VehicleData),
|
||||
"Sound to play when entering the water with speed >= hardSplashSoundVelocity." );
|
||||
addField( "waterWakeSound", TYPEID< SFXProfile >(), Offset(waterSound[Wake], VehicleData),
|
||||
"Looping sound to play while moving through the water." );
|
||||
|
||||
INITPERSISTFIELD_SOUNDASSET_ENUMED(WaterSounds, vehSoundsEnum, VehicleData::Sounds::MaxSounds, VehicleData, "Sounds for interacting with water.");
|
||||
|
||||
addField( "collDamageThresholdVel", TypeF32, Offset(collDamageThresholdVel, VehicleData),
|
||||
"Minimum collision velocity to cause damage to this vehicle.\nCurrently unused." );
|
||||
|
|
@ -876,8 +892,8 @@ bool Vehicle::onNewDataBlock(GameBaseData* dptr,bool reload)
|
|||
// costs and makes the system easier to understand.
|
||||
SFX_DELETE( mWakeSound );
|
||||
|
||||
if ( mDataBlock->waterSound[VehicleData::Wake] )
|
||||
mWakeSound = SFX->createSource( mDataBlock->waterSound[VehicleData::Wake], &getTransform() );
|
||||
if ( mDataBlock->getVehicleWaterSounds(VehicleData::Wake) != NULL )
|
||||
mWakeSound = SFX->createSource( mDataBlock->getVehicleWaterSoundsProfile(VehicleData::Wake), &getTransform() );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1140,27 +1156,27 @@ void Vehicle::updatePos(F32 dt)
|
|||
if (collSpeed >= mDataBlock->softImpactSpeed)
|
||||
impactSound = VehicleData::Body::SoftImpactSound;
|
||||
|
||||
if (impactSound != -1 && mDataBlock->body.sound[impactSound] != NULL)
|
||||
SFX->playOnce( mDataBlock->body.sound[impactSound], &getTransform() );
|
||||
if (impactSound != -1 && mDataBlock->getVehicleBodySoundsProfile(impactSound) != NULL)
|
||||
SFX->playOnce( mDataBlock->getVehicleBodySoundsProfile(impactSound), &getTransform() );
|
||||
}
|
||||
|
||||
// Water volume sounds
|
||||
F32 vSpeed = getVelocity().len();
|
||||
if (!inLiquid && mWaterCoverage >= 0.8f) {
|
||||
if (vSpeed >= mDataBlock->hardSplashSoundVel)
|
||||
SFX->playOnce( mDataBlock->waterSound[VehicleData::ImpactHard], &getTransform() );
|
||||
SFX->playOnce( mDataBlock->getVehicleWaterSoundsProfile(VehicleData::ImpactHard), &getTransform() );
|
||||
else
|
||||
if (vSpeed >= mDataBlock->medSplashSoundVel)
|
||||
SFX->playOnce( mDataBlock->waterSound[VehicleData::ImpactMedium], &getTransform() );
|
||||
SFX->playOnce( mDataBlock->getVehicleWaterSoundsProfile(VehicleData::ImpactMedium), &getTransform() );
|
||||
else
|
||||
if (vSpeed >= mDataBlock->softSplashSoundVel)
|
||||
SFX->playOnce( mDataBlock->waterSound[VehicleData::ImpactSoft], &getTransform() );
|
||||
SFX->playOnce( mDataBlock->getVehicleWaterSoundsProfile(VehicleData::ImpactSoft), &getTransform() );
|
||||
inLiquid = true;
|
||||
}
|
||||
else
|
||||
if(inLiquid && mWaterCoverage < 0.8f) {
|
||||
if (vSpeed >= mDataBlock->exitSplashSoundVel)
|
||||
SFX->playOnce( mDataBlock->waterSound[VehicleData::ExitWater], &getTransform() );
|
||||
SFX->playOnce( mDataBlock->getVehicleWaterSoundsProfile(VehicleData::ExitWater), &getTransform() );
|
||||
inLiquid = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,11 +45,12 @@ struct VehicleData : public RigidShapeData
|
|||
HardImpactSound,
|
||||
MaxSounds,
|
||||
};
|
||||
SFXProfile* sound[MaxSounds];
|
||||
F32 restitution;
|
||||
F32 friction;
|
||||
} body;
|
||||
|
||||
DECLARE_SOUNDASSET_ARRAY(VehicleData, VehicleBodySounds, Body::Sounds::MaxSounds)
|
||||
|
||||
enum VehicleConsts
|
||||
{
|
||||
VC_NUM_DUST_EMITTERS = 1,
|
||||
|
|
@ -69,7 +70,9 @@ struct VehicleData : public RigidShapeData
|
|||
Wake,
|
||||
MaxSounds
|
||||
};
|
||||
SFXProfile* waterSound[MaxSounds];
|
||||
|
||||
DECLARE_SOUNDASSET_ARRAY(VehicleData, VehicleWaterSounds, Sounds::MaxSounds)
|
||||
|
||||
F32 exitSplashSoundVel;
|
||||
F32 softSplashSoundVel;
|
||||
F32 medSplashSoundVel;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ ConsoleDocClass( WheeledVehicleTire,
|
|||
|
||||
WheeledVehicleTire::WheeledVehicleTire()
|
||||
{
|
||||
INIT_SHAPEASSET(Shape);
|
||||
INIT_ASSET(Shape);
|
||||
|
||||
staticFriction = 1;
|
||||
kineticFriction = 0.5f;
|
||||
|
|
@ -177,7 +177,7 @@ void WheeledVehicleTire::packData(BitStream* stream)
|
|||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
PACKDATA_SHAPEASSET(Shape);
|
||||
PACKDATA_ASSET(Shape);
|
||||
|
||||
stream->write(mass);
|
||||
stream->write(staticFriction);
|
||||
|
|
@ -196,7 +196,7 @@ void WheeledVehicleTire::unpackData(BitStream* stream)
|
|||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
UNPACKDATA_SHAPEASSET(Shape);
|
||||
UNPACKDATA_ASSET(Shape);
|
||||
|
||||
stream->read(&mass);
|
||||
stream->read(&staticFriction);
|
||||
|
|
@ -289,6 +289,17 @@ ConsoleDocClass( WheeledVehicleData,
|
|||
"@ingroup Vehicles\n"
|
||||
);
|
||||
|
||||
typedef WheeledVehicleData::Sounds wheelSoundsEnum;
|
||||
DefineEnumType(wheelSoundsEnum);
|
||||
|
||||
ImplementEnumType(wheelSoundsEnum, "enum types.\n"
|
||||
"@ingroup WheeledVehicleData\n\n")
|
||||
{WheeledVehicleData::JetSound, "JetSound", "..." },
|
||||
{WheeledVehicleData::EngineSound, "EngineSound", "..." },
|
||||
{WheeledVehicleData::SquealSound, "SquealSound", "..." },
|
||||
{WheeledVehicleData::WheelImpactSound, "WheelImpactSound", "..." },
|
||||
EndImplementEnumType;
|
||||
|
||||
WheeledVehicleData::WheeledVehicleData()
|
||||
{
|
||||
tireEmitter = 0;
|
||||
|
|
@ -301,7 +312,7 @@ WheeledVehicleData::WheeledVehicleData()
|
|||
wheelCount = 0;
|
||||
dMemset(&wheel, 0, sizeof(wheel));
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
sound[i] = 0;
|
||||
INIT_ASSET_ARRAY(WheeledVehicleSounds, i);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -335,10 +346,9 @@ bool WheeledVehicleData::preload(bool server, String &errorStr)
|
|||
if (!server) {
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
{
|
||||
if (!sfxResolve(&sound[i], errorStr))
|
||||
if (getWheeledVehicleSounds(i) != StringTable->EmptyString())
|
||||
{
|
||||
delete si;
|
||||
return false;
|
||||
_setWheeledVehicleSounds(getWheeledVehicleSounds(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -438,16 +448,7 @@ bool WheeledVehicleData::mirrorWheel(Wheel* we)
|
|||
|
||||
void WheeledVehicleData::initPersistFields()
|
||||
{
|
||||
addField( "jetSound", TYPEID< SFXTrack >(), Offset(sound[JetSound], WheeledVehicleData),
|
||||
"Looping sound played when the vehicle is jetting." );
|
||||
addField( "engineSound", TYPEID< SFXTrack >(), Offset(sound[EngineSound], WheeledVehicleData),
|
||||
"@brief Looping engine sound.\n\n"
|
||||
"The pitch is dynamically adjusted based on the current engine RPM" );
|
||||
addField("squealSound", TYPEID< SFXTrack >(), Offset(sound[SquealSound], WheeledVehicleData),
|
||||
"@brief Looping sound played while any of the wheels is slipping.\n\n"
|
||||
"The volume is dynamically adjusted based on how much the wheels are slipping." );
|
||||
addField("WheelImpactSound", TYPEID< SFXTrack >(), Offset(sound[WheelImpactSound], WheeledVehicleData),
|
||||
"Sound played when the wheels impact the ground.\nCurrently unused." );
|
||||
INITPERSISTFIELD_SOUNDASSET_ENUMED(WheeledVehicleSounds, wheelSoundsEnum, MaxSounds, WheeledVehicleData, "Sounds related to wheeled vehicle.");
|
||||
|
||||
addField("tireEmitter",TYPEID< ParticleEmitterData >(), Offset(tireEmitter, WheeledVehicleData),
|
||||
"ParticleEmitterData datablock used to generate particles from each wheel "
|
||||
|
|
@ -481,7 +482,9 @@ void WheeledVehicleData::packData(BitStream* stream)
|
|||
tireEmitter->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
sfxWrite( stream, sound[ i ] );
|
||||
{
|
||||
PACKDATA_ASSET_ARRAY(WheeledVehicleSounds, i);
|
||||
}
|
||||
|
||||
stream->write(maxWheelSpeed);
|
||||
stream->write(engineTorque);
|
||||
|
|
@ -498,7 +501,9 @@ void WheeledVehicleData::unpackData(BitStream* stream)
|
|||
DataBlockObjectIdLast): 0;
|
||||
|
||||
for (S32 i = 0; i < MaxSounds; i++)
|
||||
sfxRead( stream, &sound[ i ] );
|
||||
{
|
||||
UNPACKDATA_ASSET_ARRAY(WheeledVehicleSounds, i);
|
||||
}
|
||||
|
||||
stream->read(&maxWheelSpeed);
|
||||
stream->read(&engineTorque);
|
||||
|
|
@ -560,8 +565,6 @@ bool WheeledVehicle::onAdd()
|
|||
return false;
|
||||
|
||||
addToScene();
|
||||
if (isServerObject())
|
||||
scriptOnAdd();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -583,7 +586,6 @@ void WheeledVehicle::onRemove()
|
|||
SFX_DELETE( mSquealSound );
|
||||
|
||||
//
|
||||
scriptOnRemove();
|
||||
removeFromScene();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
@ -683,14 +685,14 @@ bool WheeledVehicle::onNewDataBlock(GameBaseData* dptr, bool reload)
|
|||
SFX_DELETE( mSquealSound );
|
||||
SFX_DELETE( mJetSound );
|
||||
|
||||
if ( mDataBlock->sound[WheeledVehicleData::EngineSound] )
|
||||
mEngineSound = SFX->createSource( mDataBlock->sound[WheeledVehicleData::EngineSound], &getTransform() );
|
||||
if ( mDataBlock->getWheeledVehicleSounds(WheeledVehicleData::EngineSound) )
|
||||
mEngineSound = SFX->createSource( mDataBlock->getWheeledVehicleSoundsProfile(WheeledVehicleData::EngineSound), &getTransform() );
|
||||
|
||||
if ( mDataBlock->sound[WheeledVehicleData::SquealSound] )
|
||||
mSquealSound = SFX->createSource( mDataBlock->sound[WheeledVehicleData::SquealSound], &getTransform() );
|
||||
if ( mDataBlock->getWheeledVehicleSounds(WheeledVehicleData::SquealSound) )
|
||||
mSquealSound = SFX->createSource( mDataBlock->getWheeledVehicleSoundsProfile(WheeledVehicleData::SquealSound), &getTransform() );
|
||||
|
||||
if ( mDataBlock->sound[WheeledVehicleData::JetSound] )
|
||||
mJetSound = SFX->createSource( mDataBlock->sound[WheeledVehicleData::JetSound], &getTransform() );
|
||||
if ( mDataBlock->getWheeledVehicleSounds(WheeledVehicleData::JetSound) )
|
||||
mJetSound = SFX->createSource( mDataBlock->getWheeledVehicleSoundsProfile(WheeledVehicleData::JetSound), &getTransform() );
|
||||
}
|
||||
|
||||
scriptOnNewDataBlock();
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ struct WheeledVehicleTire: public SimDataBlock
|
|||
typedef SimDataBlock Parent;
|
||||
|
||||
DECLARE_SHAPEASSET(WheeledVehicleTire, Shape, onShapeChanged);
|
||||
DECLARE_SHAPEASSET_SETGET(WheeledVehicleTire, Shape);
|
||||
DECLARE_ASSET_SETGET(WheeledVehicleTire, Shape);
|
||||
|
||||
// Physical properties
|
||||
F32 mass; // Mass of the whole wheel
|
||||
|
|
@ -118,7 +118,8 @@ struct WheeledVehicleData: public VehicleData
|
|||
WheelImpactSound,
|
||||
MaxSounds,
|
||||
};
|
||||
SFXTrack* sound[MaxSounds];
|
||||
|
||||
DECLARE_SOUNDASSET_ARRAY(WheeledVehicleData, WheeledVehicleSounds, Sounds::MaxSounds);
|
||||
|
||||
ParticleEmitterData* tireEmitter;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue