mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-11 14:44:36 +00:00
Merge branch 'Preview4_0' into feature-vfs-security
This commit is contained in:
commit
161ffc62fe
3013 changed files with 348715 additions and 182470 deletions
|
|
@ -102,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");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -115,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)
|
||||
|
|
@ -226,6 +226,13 @@ DefineEngineMethod(GUIAsset, getScriptPath, const char*, (), ,
|
|||
{
|
||||
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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -154,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.");
|
||||
}
|
||||
|
|
@ -173,7 +174,11 @@ void MaterialAsset::initializeAsset()
|
|||
return;
|
||||
}
|
||||
|
||||
if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
if (size() != 0 && mScriptPath == StringTable->EmptyString())
|
||||
{
|
||||
mLoadedState = EmbeddedDefinition;
|
||||
}
|
||||
else if (Torque::FS::IsScriptFile(mScriptPath))
|
||||
{
|
||||
if (!Sim::findObject(mMatDefinitionName))
|
||||
{
|
||||
|
|
@ -230,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.
|
||||
|
|
@ -245,9 +249,28 @@ void MaterialAsset::setScriptFile(const char* pScriptFile)
|
|||
void MaterialAsset::loadMaterial()
|
||||
{
|
||||
if (mMaterialDefinition)
|
||||
SAFE_DELETE(mMaterialDefinition);
|
||||
{
|
||||
mMaterialDefinition->safeDeleteObject();
|
||||
}
|
||||
|
||||
if ((mLoadedState == ScriptLoaded || mLoadedState == DefinitionAlreadyExists) && 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))
|
||||
|
|
@ -260,7 +283,7 @@ void MaterialAsset::loadMaterial()
|
|||
mMaterialDefinition = matDef;
|
||||
|
||||
mLoadedState = Ok;
|
||||
|
||||
mMaterialDefinition->setInternalName(getAssetId());
|
||||
mMaterialDefinition->reload();
|
||||
return;
|
||||
}
|
||||
|
|
@ -296,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;
|
||||
|
|
@ -388,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"
|
||||
|
|
@ -396,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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@
|
|||
#include "sim/netConnection.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUI_INSPECTOR_TYPES_H_
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
#endif
|
||||
|
||||
#include "materials/matTextureTarget.h"
|
||||
#include "materials/materialDefinition.h"
|
||||
|
|
@ -75,6 +77,7 @@ public:
|
|||
{
|
||||
ScriptLoaded = AssetErrCode::Extended,
|
||||
DefinitionAlreadyExists,
|
||||
EmbeddedDefinition,
|
||||
Extended
|
||||
};
|
||||
|
||||
|
|
@ -108,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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@
|
|||
#endif
|
||||
#include "util/imposterCapture.h"
|
||||
|
||||
#include "ts/tsShapeInstance.h"
|
||||
#include "gfx/bitmap/imageUtils.h"
|
||||
|
||||
StringTableEntry ShapeAsset::smNoShapeAssetFallback = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -470,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;
|
||||
}
|
||||
|
|
@ -560,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
|
||||
|
||||
|
|
@ -604,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")
|
||||
{
|
||||
|
|
@ -625,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), (""),
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ public:
|
|||
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:
|
||||
|
|
|
|||
|
|
@ -218,6 +218,9 @@ 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
|
||||
|
|
@ -225,6 +228,9 @@ bool SoundAsset::loadSound()
|
|||
mSFXProfile.setDescription(&mProfileDesc);
|
||||
mSFXProfile.setSoundFileName(mSoundPath);
|
||||
mSFXProfile.setPreload(mPreload);
|
||||
|
||||
//give it a nudge to preload if required
|
||||
mSFXProfile.getBuffer();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -257,7 +263,7 @@ StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName)
|
|||
if (fileName == StringTable->EmptyString())
|
||||
return StringTable->EmptyString();
|
||||
|
||||
StringTableEntry materialAssetId = "";
|
||||
StringTableEntry soundAssetId = StringTable->EmptyString();
|
||||
|
||||
AssetQuery query;
|
||||
U32 foundCount = AssetDatabase.findAssetType(&query, "SoundAsset");
|
||||
|
|
@ -268,7 +274,7 @@ StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName)
|
|||
SoundAsset* soundAsset = AssetDatabase.acquireAsset<SoundAsset>(query.mAssetList[i]);
|
||||
if (soundAsset && soundAsset->getSoundPath() == fileName)
|
||||
{
|
||||
materialAssetId = soundAsset->getAssetId();
|
||||
soundAssetId = soundAsset->getAssetId();
|
||||
AssetDatabase.releaseAsset(query.mAssetList[i]);
|
||||
break;
|
||||
}
|
||||
|
|
@ -276,7 +282,7 @@ StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName)
|
|||
}
|
||||
}
|
||||
|
||||
return materialAssetId;
|
||||
return soundAssetId;
|
||||
}
|
||||
|
||||
U32 SoundAsset::getAssetById(StringTableEntry assetId, AssetPtr<SoundAsset>* soundAsset)
|
||||
|
|
@ -330,15 +336,18 @@ DefineEngineMethod(SoundAsset, getSoundPath, const char*, (), , "")
|
|||
}
|
||||
|
||||
DefineEngineMethod(SoundAsset, playSound, S32, (Point3F position), (Point3F::Zero),
|
||||
"Gets the number of materials for this shape asset.\n"
|
||||
"@return Material count.\n")
|
||||
"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();
|
||||
if(source)
|
||||
return source->getId();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@
|
|||
#endif
|
||||
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
#ifndef _BITSTREAM_H_
|
||||
#include "core/stream/bitStream.h"
|
||||
|
|
@ -57,6 +60,10 @@
|
|||
#include "sfx/sfxProfile.h"
|
||||
#endif // !_SFXPROFILE_H_
|
||||
|
||||
#ifndef _RESOURCEMANAGER_H_
|
||||
#include "core/resourceManager.h"
|
||||
#endif
|
||||
|
||||
#include "assetMacroHelpers.h"
|
||||
class SFXResource;
|
||||
|
||||
|
|
@ -178,6 +185,8 @@ public:
|
|||
StringTableEntry m##name##AssetId;\
|
||||
AssetPtr<SoundAsset> m##name##Asset = NULL;\
|
||||
SFXProfile* m##name##Profile = NULL;\
|
||||
SFXDescription* m##name##Desc = NULL;\
|
||||
SimObjectId m##name##SFXId = NULL;\
|
||||
public: \
|
||||
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());}\
|
||||
|
|
@ -245,7 +254,7 @@ public: \
|
|||
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 && (m##name##Name != StringTable->EmptyString() && !Sim::findObject(m##name##Name)))\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s() - Couldn't load sound \"%s\"", macroText(className), getName(), macroText(name), _in);\
|
||||
return false;\
|
||||
|
|
@ -271,7 +280,15 @@ public: \
|
|||
SFXProfile* get##name##Profile()\
|
||||
{\
|
||||
if (get##name() != StringTable->EmptyString() && m##name##Asset.notNull())\
|
||||
return m##name##Asset->getSfxProfile();\
|
||||
m##name##Profile = m##name##Asset->getSfxProfile();\
|
||||
return m##name##Profile;\
|
||||
return NULL;\
|
||||
}\
|
||||
SFXDescription* get##name##Description()\
|
||||
{\
|
||||
if (get##name() != StringTable->EmptyString() && m##name##Asset.notNull())\
|
||||
m##name##Desc = m##name##Asset->getSfxDescription();\
|
||||
return m##name##Desc;\
|
||||
return NULL;\
|
||||
}\
|
||||
bool is##name##Valid() { return (get##name() != StringTable->EmptyString() && m##name##Asset->getStatus() == AssetBase::Ok); }
|
||||
|
|
@ -290,10 +307,61 @@ public: \
|
|||
|
||||
#endif // TORQUE_SHOW_LEGACY_FILE_FIELDS
|
||||
|
||||
//network send - datablock
|
||||
#define PACKDATA_SOUNDASSET(name)\
|
||||
if (stream->writeFlag(m##name##Asset.notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset.getAssetId());\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
if(stream->writeFlag(Sim::findObject(m##name##Name)))\
|
||||
{\
|
||||
SFXTrack* sndTrack;\
|
||||
Sim::findObject(m##name##Name, sndTrack);\
|
||||
stream->writeRangedU32(SimObjectId(sndTrack->getId()), DataBlockObjectIdFirst, DataBlockObjectIdLast);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
stream->writeString(m##name##Name);\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
//network recieve - datablock
|
||||
#define UNPACKDATA_SOUNDASSET(name)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId = stream->readSTString();\
|
||||
_set##name(m##name##AssetId);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
if(stream->readFlag())\
|
||||
{\
|
||||
m##name##SFXId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
m##name##Name = stream->readSTString(); \
|
||||
_set##name(m##name##Name); \
|
||||
}\
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Arrayed Asset Macros
|
||||
|
||||
#define INIT_SOUNDASSET_ARRAY(name, 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] = NULL;\
|
||||
m##name##SFXId[index] = 0;\
|
||||
}
|
||||
|
||||
#define DECLARE_SOUNDASSET_ARRAY(className,name,max) public: \
|
||||
static const U32 sm##name##Count = max;\
|
||||
Resource<SFXResource> m##name[max];\
|
||||
|
|
@ -301,6 +369,7 @@ public: \
|
|||
StringTableEntry m##name##AssetId[max];\
|
||||
AssetPtr<SoundAsset> m##name##Asset[max];\
|
||||
SFXProfile* m##name##Profile[max];\
|
||||
SimObjectId m##name##SFXId[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());}\
|
||||
|
|
@ -376,7 +445,7 @@ public: \
|
|||
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])\
|
||||
else if (!m##name[index] && (m##name##Name[index] != StringTable->EmptyString() && !Sim::findObject(m##name##Name[index])))\
|
||||
{\
|
||||
Con::errorf("%s(%s)::_set%s(%i) - Couldn't load sound \"%s\"", macroText(className), getName(), macroText(name),index, _in);\
|
||||
return false;\
|
||||
|
|
@ -448,6 +517,46 @@ if (m##name##AssetId[index] != StringTable->EmptyString())\
|
|||
addField(assetEnumNameConcat(enumString, Asset), TypeSoundAssetId, Offset(m##name##AssetId[0], consoleClass) + sizeof(m##name##AssetId[0])*i, assetText(name, asset reference.));\
|
||||
}\
|
||||
}
|
||||
|
||||
#define PACKDATA_SOUNDASSET_ARRAY(name, index)\
|
||||
if (stream->writeFlag(m##name##Asset[index].notNull()))\
|
||||
{\
|
||||
stream->writeString(m##name##Asset[index].getAssetId());\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
if(stream->writeFlag(Sim::findObject(m##name##Name[index])))\
|
||||
{\
|
||||
SFXTrack* sndTrack;\
|
||||
Sim::findObject(m##name##Name[index], sndTrack);\
|
||||
stream->writeRangedU32(SimObjectId(sndTrack->getId()), DataBlockObjectIdFirst, DataBlockObjectIdLast);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
stream->writeString(m##name##Name[index]);\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
//network recieve - datablock
|
||||
#define UNPACKDATA_SOUNDASSET_ARRAY(name, index)\
|
||||
if (stream->readFlag())\
|
||||
{\
|
||||
m##name##AssetId[index] = stream->readSTString();\
|
||||
_set##name(m##name##AssetId[index], index);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
if(stream->readFlag())\
|
||||
{\
|
||||
m##name##SFXId[index] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
m##name##Name[index] = stream->readSTString(); \
|
||||
_set##name(m##name##Name[index], index); \
|
||||
}\
|
||||
}
|
||||
#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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);",
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainMaterialAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
|
||||
mInspector->getIdString(), mCaption);
|
||||
mMatPreviewButton->setField("Command", szBuffer);
|
||||
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_
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ AssetImportConfig::AssetImportConfig() :
|
|||
SeparateAnimationPrefix(""),
|
||||
animTiming("FrameCount"),
|
||||
animFPS(false),
|
||||
AlwaysAddShapeAnimationSuffix(true),
|
||||
AddedShapeAnimationSuffix("_anim"),
|
||||
GenerateCollisions(false),
|
||||
GenCollisionType(""),
|
||||
CollisionMeshPrefix(""),
|
||||
|
|
@ -190,6 +192,8 @@ void AssetImportConfig::initPersistFields()
|
|||
addField("SeparateAnimationPrefix", TypeRealString, Offset(SeparateAnimationPrefix, AssetImportConfig), "If separating animations out from a source file, what prefix should be added to the names for grouping association");
|
||||
addField("animTiming", TypeRealString, Offset(animTiming, AssetImportConfig), "Defines the animation timing for the given animation sequence. Options are FrameTime, Seconds, Milliseconds");
|
||||
addField("animFPS", TypeBool, Offset(animFPS, AssetImportConfig), "The FPS of the animation sequence");
|
||||
addField("AlwaysAddShapeAnimationSuffix", TypeBool, Offset(AlwaysAddShapeAnimationSuffix, AssetImportConfig), "When importing a shape animation, this indicates if it should automatically add a standard suffix onto the name");
|
||||
addField("AddedShapeAnimationSuffix", TypeString, Offset(AddedShapeAnimationSuffix, AssetImportConfig), " If AlwaysAddShapeAnimationSuffix is on, this is the suffix to be added");
|
||||
endGroup("Animation");
|
||||
|
||||
addGroup("Collision");
|
||||
|
|
@ -287,6 +291,8 @@ void AssetImportConfig::loadImportConfig(Settings* configSettings, String config
|
|||
SeparateAnimationPrefix = configSettings->value(String(configName + "/Animations/SeparateAnimationPrefix").c_str());
|
||||
animTiming = configSettings->value(String(configName + "/Animations/animTiming").c_str());
|
||||
animFPS = dAtof(configSettings->value(String(configName + "/Animations/animFPS").c_str()));
|
||||
AlwaysAddShapeAnimationSuffix = dAtob(configSettings->value(String(configName + "/Animations/AlwaysAddShapeAnimationSuffix").c_str()));
|
||||
AddedShapeAnimationSuffix = configSettings->value(String(configName + "/Animations/AddedShapeAnimationSuffix").c_str());
|
||||
|
||||
//Collisions
|
||||
GenerateCollisions = dAtob(configSettings->value(String(configName + "/Collision/GenerateCollisions").c_str()));
|
||||
|
|
@ -379,6 +385,8 @@ void AssetImportConfig::CopyTo(AssetImportConfig* target) const
|
|||
target->SeparateAnimationPrefix = SeparateAnimationPrefix;
|
||||
target->animTiming = animTiming;
|
||||
target->animFPS = animFPS;
|
||||
target->AlwaysAddShapeAnimationSuffix = AlwaysAddShapeAnimationSuffix;
|
||||
target->AddedShapeAnimationSuffix = AddedShapeAnimationSuffix;
|
||||
|
||||
//Collisions
|
||||
target->GenerateCollisions = GenerateCollisions;
|
||||
|
|
@ -609,14 +617,32 @@ AssetImportObject* AssetImporter::addImportingAsset(String assetType, Torque::Pa
|
|||
assetImportObj->registerObject();
|
||||
|
||||
//sanitize
|
||||
assetName.replace(' ', '_');
|
||||
assetName.replace('~', '_');
|
||||
assetName.replace('`', '_');
|
||||
assetName.replace('-', '_');
|
||||
assetName.replace('*', '_');
|
||||
assetName.replace('-', '_');
|
||||
assetName.replace('+', '_');
|
||||
assetName.replace('&', '_');
|
||||
String processedString = assetName;
|
||||
|
||||
U32 start;
|
||||
U32 end;
|
||||
String firstNumber = String::GetFirstNumber(processedString, start, end);
|
||||
if (!firstNumber.isEmpty() && processedString.startsWith(firstNumber.c_str()))
|
||||
processedString = processedString.replace(firstNumber, "");
|
||||
|
||||
processedString = processedString.replace(" ", "_");
|
||||
|
||||
U32 len = processedString.length() + 1;
|
||||
char* sanitizedStr = Con::getReturnBuffer(len);
|
||||
dStrcpy(sanitizedStr, processedString.c_str(), len);
|
||||
|
||||
U32 pos = dStrcspn(sanitizedStr, "-+*/%$&<26>=()[].?\\\"#,;!~<>|<7C>^{}");
|
||||
while (pos < dStrlen(sanitizedStr))
|
||||
{
|
||||
dStrcpy(sanitizedStr + pos, sanitizedStr + pos + 1, len - pos);
|
||||
pos = dStrcspn(sanitizedStr, "-+*/%$&<26>=()[].?\\\"#,;!~<>|<7C>^{}");
|
||||
}
|
||||
|
||||
//If we did, indeed, modify the name, update it now
|
||||
if (String(sanitizedStr) != assetName)
|
||||
{
|
||||
assetName = sanitizedStr;
|
||||
}
|
||||
|
||||
assetImportObj->assetType = assetType;
|
||||
assetImportObj->filePath = filePath;
|
||||
|
|
@ -1513,13 +1539,15 @@ void AssetImporter::processImportAssets(AssetImportObject* assetItem)
|
|||
{
|
||||
processMaterialAsset(item);
|
||||
}
|
||||
/*else if (item->assetType == String("ShapeAnimationAsset"))
|
||||
ShapeAnimationAsset::prepareAssetForImport(this, item);*/
|
||||
else if (item->assetType == String("ShapeAnimationAsset"))
|
||||
{
|
||||
processShapeAnimationAsset(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
String processCommand = "process";
|
||||
processCommand += item->assetType;
|
||||
if(isMethod(processCommand.c_str()))
|
||||
if (isMethod(processCommand.c_str()))
|
||||
Con::executef(this, processCommand.c_str(), item);
|
||||
}
|
||||
|
||||
|
|
@ -1605,7 +1633,7 @@ void AssetImporter::processImageAsset(AssetImportObject* assetItem)
|
|||
{
|
||||
String diffuseToken = StringUnit::getUnit(activeImportConfig->DiffuseTypeSuffixes, 0, ",;\t");
|
||||
assetItem->assetName = assetItem->assetName + diffuseToken;
|
||||
assetItem->cleanAssetName = assetItem->assetName;
|
||||
//assetItem->cleanAssetName = assetItem->assetName;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1614,7 +1642,7 @@ void AssetImporter::processImageAsset(AssetImportObject* assetItem)
|
|||
if ((materialAsset && materialAsset->assetName.compare(assetItem->assetName) == 0) || activeImportConfig->AlwaysAddImageSuffix)
|
||||
{
|
||||
assetItem->assetName = assetItem->assetName + activeImportConfig->AddedImageSuffix;
|
||||
assetItem->cleanAssetName = assetItem->assetName;
|
||||
//assetItem->cleanAssetName = assetItem->assetName;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1645,8 +1673,8 @@ void AssetImporter::processImageAsset(AssetImportObject* assetItem)
|
|||
|
||||
if(assetItem->assetName == assetItem->cleanAssetName && activeImportConfig->AlwaysAddImageSuffix)
|
||||
{
|
||||
assetItem->assetName = assetItem->assetName + activeImportConfig->AddedImageSuffix;
|
||||
assetItem->cleanAssetName = assetItem->assetName;
|
||||
if (!assetItem->assetName.endsWith(activeImportConfig->AddedImageSuffix.c_str()))
|
||||
assetItem->assetName = assetItem->assetName + activeImportConfig->AddedImageSuffix;
|
||||
}
|
||||
|
||||
assetItem->importStatus = AssetImportObject::Processed;
|
||||
|
|
@ -1699,7 +1727,8 @@ void AssetImporter::processMaterialAsset(AssetImportObject* assetItem)
|
|||
|
||||
//If there was no existing assetId, then lets see if it already exists in a legacy file, like a materials.cs or materials.tscript
|
||||
//If it does, we'll just make our asset point to that instead of a new file
|
||||
Material* mat = MATMGR->getMaterialDefinitionByName(assetName);
|
||||
Material* mat;
|
||||
Sim::findObject(assetName, mat);
|
||||
|
||||
if (!mat)
|
||||
mat = MATMGR->getMaterialDefinitionByMapTo(assetName);
|
||||
|
|
@ -1724,8 +1753,8 @@ void AssetImporter::processMaterialAsset(AssetImportObject* assetItem)
|
|||
{
|
||||
if (activeImportConfig->AlwaysAddMaterialSuffix) //we only opt to force on the suffix if we're not obligating using the original material defs
|
||||
{
|
||||
assetItem->assetName += activeImportConfig->AddedMaterialSuffix;
|
||||
assetItem->cleanAssetName = assetItem->assetName;
|
||||
if(!assetItem->assetName.endsWith(activeImportConfig->AddedMaterialSuffix.c_str()))
|
||||
assetItem->assetName += activeImportConfig->AddedMaterialSuffix;
|
||||
}
|
||||
|
||||
if (activeImportConfig->PopulateMaterialMaps)
|
||||
|
|
@ -1908,7 +1937,7 @@ void AssetImporter::processMaterialAsset(AssetImportObject* assetItem)
|
|||
if (newImageAssetObj->assetName == assetItem->assetName)
|
||||
{
|
||||
newImageAssetObj->assetName += StringUnit::getUnit(suffixList.c_str(), 0, ",;\t");
|
||||
newImageAssetObj->cleanAssetName = newImageAssetObj->assetName;
|
||||
//newImageAssetObj->cleanAssetName = newImageAssetObj->assetName;
|
||||
}
|
||||
|
||||
newImageAssetObj->imageSuffixType = ImageAsset::getImageTypeNameFromType(ImageAsset::ImageTypes::Albedo);
|
||||
|
|
@ -1926,7 +1955,7 @@ void AssetImporter::processMaterialAsset(AssetImportObject* assetItem)
|
|||
if (matchedImageTypes[t]->assetName == assetItem->assetName)
|
||||
{
|
||||
matchedImageTypes[t]->assetName += StringUnit::getUnit(suffixList.c_str(), 0, ",;\t");
|
||||
matchedImageTypes[t]->cleanAssetName = matchedImageTypes[t]->assetName;
|
||||
//matchedImageTypes[t]->cleanAssetName = matchedImageTypes[t]->assetName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1972,8 +2001,8 @@ void AssetImporter::processShapeAsset(AssetImportObject* assetItem)
|
|||
|
||||
if (activeImportConfig->AlwaysAddShapeSuffix)
|
||||
{
|
||||
assetItem->assetName += activeImportConfig->AddedShapeSuffix;
|
||||
assetItem->cleanAssetName = assetItem->assetName;
|
||||
if(!assetItem->assetName.endsWith(activeImportConfig->AddedShapeSuffix.c_str()))
|
||||
assetItem->assetName += activeImportConfig->AddedShapeSuffix;
|
||||
}
|
||||
|
||||
S32 meshCount = dAtoi(assetItem->shapeInfo->getDataField(StringTable->insert("_meshCount"), nullptr));
|
||||
|
|
@ -2030,6 +2059,73 @@ void AssetImporter::processShapeAsset(AssetImportObject* assetItem)
|
|||
assetItem->importStatus = AssetImportObject::Processed;
|
||||
}
|
||||
|
||||
void AssetImporter::processShapeAnimationAsset(AssetImportObject* assetItem)
|
||||
{
|
||||
dSprintf(importLogBuffer, sizeof(importLogBuffer), "Preparing Shape Animation for Import: %s", assetItem->assetName.c_str());
|
||||
activityLog.push_back(importLogBuffer);
|
||||
|
||||
String filePath = assetItem->filePath.getFullPath();
|
||||
String fileName = assetItem->filePath.getFileName();
|
||||
String fileExt = assetItem->filePath.getExtension();
|
||||
|
||||
if (assetItem->shapeInfo == nullptr)
|
||||
{
|
||||
GuiTreeViewCtrl* shapeInfo = new GuiTreeViewCtrl();
|
||||
shapeInfo->registerObject();
|
||||
|
||||
if (fileExt.compare("dae") == 0)
|
||||
{
|
||||
enumColladaForImport(filePath, shapeInfo, false);
|
||||
}
|
||||
else if (fileExt.compare("dts") == 0 || fileExt.compare("dsq") == 0)
|
||||
{
|
||||
enumDTSForImport(filePath, shapeInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if a cached DTS is available => no need to import the source file
|
||||
// if we can load the DTS instead
|
||||
|
||||
AssimpShapeLoader loader;
|
||||
loader.fillGuiTreeView(filePath.c_str(), shapeInfo);
|
||||
}
|
||||
|
||||
assetItem->shapeInfo = shapeInfo;
|
||||
}
|
||||
|
||||
if (activeImportConfig->AlwaysAddShapeAnimationSuffix)
|
||||
{
|
||||
if (!assetItem->assetName.endsWith(activeImportConfig->AddedShapeAnimationSuffix.c_str()))
|
||||
assetItem->assetName += activeImportConfig->AddedShapeAnimationSuffix;
|
||||
}
|
||||
|
||||
S32 animCount = dAtoi(assetItem->shapeInfo->getDataField(StringTable->insert("_animCount"), nullptr));
|
||||
|
||||
dSprintf(importLogBuffer, sizeof(importLogBuffer), " Shape Animation Info: Anim Count: %i", animCount);
|
||||
activityLog.push_back(importLogBuffer);
|
||||
|
||||
AssetImportConfig* cachedConfig = new AssetImportConfig();;
|
||||
cachedConfig->registerObject();
|
||||
activeImportConfig->CopyTo(cachedConfig);
|
||||
|
||||
if (!activeImportConfig->UseManualShapeConfigRules)
|
||||
{
|
||||
//Try and load a sis file if it exists for this format
|
||||
activeImportConfig->loadSISFile(assetItem->filePath);
|
||||
}
|
||||
|
||||
if (activeImportConfig->ImportAnimations && animCount > 0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//restore the cached version just in case we loaded a sis file
|
||||
cachedConfig->CopyTo(activeImportConfig);
|
||||
cachedConfig->deleteObject();
|
||||
|
||||
assetItem->importStatus = AssetImportObject::Processed;
|
||||
}
|
||||
|
||||
void AssetImporter::processShapeMaterialInfo(AssetImportObject* assetItem, S32 materialItemId)
|
||||
{
|
||||
String matName = assetItem->shapeInfo->getItemText(materialItemId);
|
||||
|
|
@ -2099,22 +2195,28 @@ void AssetImporter::processShapeMaterialInfo(AssetImportObject* assetItem, S32 m
|
|||
String imgFileName = AssetImporter::findImagePath(testFilePath.getPath() + "/" + testFilePath.getFileName());
|
||||
if (imgFileName.isNotEmpty())
|
||||
filePath = imgFileName;
|
||||
else
|
||||
filePath = Torque::Path(""); //no luck, so we just won't try importing in the image
|
||||
}
|
||||
}
|
||||
|
||||
matAssetItem = addImportingAsset("MaterialAsset", shapePathBase + "/" + matName, assetItem, matName);
|
||||
AssetImportObject* imageAssetItem = addImportingAsset("ImageAsset", filePath, matAssetItem, "");
|
||||
|
||||
String suffixType;
|
||||
String suffix = parseImageSuffixes(imageAssetItem->assetName, &suffixType);
|
||||
if (suffix.isNotEmpty())
|
||||
if (!filePath.isEmpty())
|
||||
{
|
||||
imageAssetItem->imageSuffixType = suffixType;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we'll assume it's albedo
|
||||
imageAssetItem->imageSuffixType = "Albedo";
|
||||
AssetImportObject* imageAssetItem = addImportingAsset("ImageAsset", filePath, matAssetItem, "");
|
||||
|
||||
String suffixType;
|
||||
String suffix = parseImageSuffixes(imageAssetItem->assetName, &suffixType);
|
||||
if (suffix.isNotEmpty())
|
||||
{
|
||||
imageAssetItem->imageSuffixType = suffixType;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we'll assume it's albedo
|
||||
imageAssetItem->imageSuffixType = "Albedo";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -2136,8 +2238,8 @@ void AssetImporter::processSoundAsset(AssetImportObject* assetItem)
|
|||
|
||||
if (activeImportConfig->AlwaysAddSoundSuffix)
|
||||
{
|
||||
assetItem->assetName += activeImportConfig->AddedSoundSuffix;
|
||||
assetItem->cleanAssetName = assetItem->assetName;
|
||||
if (!assetItem->assetName.endsWith(activeImportConfig->AddedSoundSuffix.c_str()))
|
||||
assetItem->assetName += activeImportConfig->AddedSoundSuffix;
|
||||
}
|
||||
|
||||
assetItem->importStatus = AssetImportObject::Processed;
|
||||
|
|
@ -2164,9 +2266,20 @@ bool AssetImporter::validateAssets()
|
|||
|
||||
void AssetImporter::validateAsset(AssetImportObject* assetItem)
|
||||
{
|
||||
if (assetItem->importStatus == AssetImportObject::Skipped || assetItem->importStatus == AssetImportObject::NotProcessed)
|
||||
if (assetItem->importStatus == AssetImportObject::Skipped || assetItem->importStatus == AssetImportObject::NotProcessed
|
||||
|| assetItem->importStatus == AssetImportObject::UseForDependencies)
|
||||
return;
|
||||
|
||||
//If this item's already been marked as being in error, don't bother with it. It knows what it did.
|
||||
//This avoids running collision checks on an item already known to have a collision, which could erroneously
|
||||
//mark the original, not-colliding item as colliding with this item, invaliding both
|
||||
if (assetItem->status == String("Error") || assetItem->statusType.isNotEmpty())
|
||||
{
|
||||
importIssues = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//Runm this item against our other importing assets and check for any collisions
|
||||
if (checkAssetForCollision(assetItem))
|
||||
{
|
||||
importIssues = true;
|
||||
|
|
@ -2270,7 +2383,7 @@ bool AssetImporter::checkAssetForCollision(AssetImportObject* assetItemToCheck,
|
|||
{
|
||||
AssetImportObject* importingAsset = itemList[i];
|
||||
|
||||
if (importingAsset->importStatus == AssetImportObject::Skipped)
|
||||
if (importingAsset->importStatus == AssetImportObject::Skipped || importingAsset->importStatus == AssetImportObject::UseForDependencies)
|
||||
continue;
|
||||
|
||||
if ((assetItemToCheck->assetName.compare(importingAsset->assetName) == 0) && (assetItemToCheck->getId() != importingAsset->getId()))
|
||||
|
|
@ -2506,11 +2619,16 @@ StringTableEntry AssetImporter::autoImportFile(Torque::Path filePath, String typ
|
|||
else
|
||||
{
|
||||
importAssets();
|
||||
|
||||
acquireAssets();
|
||||
}
|
||||
|
||||
dumpActivityLog();
|
||||
|
||||
if (hasIssues)
|
||||
if (hasIssues ||
|
||||
assetItem->importStatus == AssetImportObject::Skipped ||
|
||||
assetItem->importStatus == AssetImportObject::UseForDependencies ||
|
||||
assetItem->importStatus == AssetImportObject::Error)
|
||||
{
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
|
@ -2560,6 +2678,10 @@ void AssetImporter::importAssets(AssetImportObject* assetItem)
|
|||
{
|
||||
assetPath = importMaterialAsset(item);
|
||||
}
|
||||
else if (item->assetType == String("ShapeAnimationAsset"))
|
||||
{
|
||||
assetPath = importShapeAnimationAsset(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
finalImportedAssetPath = String::EmptyString;
|
||||
|
|
@ -2601,7 +2723,7 @@ void AssetImporter::importAssets(AssetImportObject* assetItem)
|
|||
else
|
||||
{
|
||||
//Any special-case post-reg stuff here
|
||||
if (item->assetType == String("ShapeAsset"))
|
||||
if (item->assetType == String("ShapeAsset") || item->assetType == String("ShapeAnimationAsset"))
|
||||
{
|
||||
//forcefully update it's shape constructor
|
||||
TSShapeConstructor* tss = TSShapeConstructor::findShapeConstructorByAssetId(assetId);
|
||||
|
|
@ -2610,10 +2732,6 @@ void AssetImporter::importAssets(AssetImportObject* assetItem)
|
|||
tss->setShapeAssetId(assetId);
|
||||
}
|
||||
}
|
||||
|
||||
//Go ahead and force the asset to load now just to kick it for immediate use
|
||||
AssetBase* assetDef = AssetDatabase.acquireAsset<AssetBase>(assetId);
|
||||
AssetDatabase.releaseAsset(assetId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2638,6 +2756,34 @@ void AssetImporter::importAssets(AssetImportObject* assetItem)
|
|||
dumpActivityLog();
|
||||
}
|
||||
|
||||
void AssetImporter::acquireAssets(AssetImportObject* assetItem)
|
||||
{
|
||||
Vector<AssetImportObject*> itemList = importingAssets;
|
||||
if (assetItem != nullptr)
|
||||
itemList = assetItem->childAssetItems;
|
||||
|
||||
for (U32 i = 0; i < itemList.size(); i++)
|
||||
{
|
||||
AssetImportObject* item = itemList[i];
|
||||
if (item->importStatus == AssetImportObject::Skipped ||
|
||||
item->importStatus == AssetImportObject::NotProcessed ||
|
||||
item->importStatus == AssetImportObject::Error)
|
||||
continue;
|
||||
|
||||
//recurse if needed, we want to process child items first for dependency reasons
|
||||
acquireAssets(item);
|
||||
|
||||
//Go ahead and force the asset to load now just to kick it for immediate use
|
||||
String assetId = item->moduleName + ":" + item->assetName;
|
||||
|
||||
if (AssetDatabase.isDeclaredAsset(assetId))
|
||||
{
|
||||
AssetBase* assetDef = AssetDatabase.acquireAsset<AssetBase>(assetId);
|
||||
AssetDatabase.releaseAsset(assetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Type-specific import logic
|
||||
//
|
||||
|
|
@ -2673,7 +2819,7 @@ Torque::Path AssetImporter::importImageAsset(AssetImportObject* assetItem)
|
|||
|
||||
//If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original
|
||||
//file path for reimporting support later
|
||||
if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile))
|
||||
if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::isFile(qualifiedFromFile))
|
||||
{
|
||||
newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
|
||||
}
|
||||
|
|
@ -2724,8 +2870,6 @@ Torque::Path AssetImporter::importMaterialAsset(AssetImportObject* assetItem)
|
|||
StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str());
|
||||
|
||||
String tamlPath = targetPath + "/" + assetName + ".asset.taml";
|
||||
String scriptName = assetItem->assetName + "." TORQUE_SCRIPT_EXTENSION;
|
||||
String scriptPath = targetPath + "/" + scriptName;
|
||||
String originalPath = assetItem->filePath.getFullPath().c_str();
|
||||
|
||||
char qualifiedFromFile[2048];
|
||||
|
|
@ -2737,10 +2881,13 @@ Torque::Path AssetImporter::importMaterialAsset(AssetImportObject* assetItem)
|
|||
#endif
|
||||
|
||||
newAsset->setAssetName(assetName);
|
||||
newAsset->setScriptFile(scriptName.c_str());
|
||||
|
||||
if (!isReimport && Torque::FS::isFile(qualifiedFromFile))
|
||||
{
|
||||
newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
|
||||
}
|
||||
|
||||
newAsset->setDataField(StringTable->insert("materialDefinitionName"), nullptr, assetName);
|
||||
|
||||
|
||||
//iterate through and write out the material maps dependencies
|
||||
S32 dependencySlotId = 0;
|
||||
|
|
@ -2762,16 +2909,6 @@ Torque::Path AssetImporter::importMaterialAsset(AssetImportObject* assetItem)
|
|||
dependencySlotId++;
|
||||
}
|
||||
|
||||
Taml tamlWriter;
|
||||
bool importSuccessful = tamlWriter.write(newAsset, tamlPath.c_str());
|
||||
|
||||
if (!importSuccessful)
|
||||
{
|
||||
dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to write asset taml file %s", tamlPath.c_str());
|
||||
activityLog.push_back(importLogBuffer);
|
||||
return "";
|
||||
}
|
||||
|
||||
//build the ORMConfig file if we're flagged to and have valid image maps
|
||||
if (activeImportConfig->CreateORMConfig)
|
||||
{
|
||||
|
|
@ -2810,109 +2947,12 @@ Torque::Path AssetImporter::importMaterialAsset(AssetImportObject* assetItem)
|
|||
}
|
||||
}
|
||||
|
||||
FileObject* file = new FileObject();
|
||||
file->registerObject();
|
||||
|
||||
if (activeImportConfig->UseExistingMaterials && Torque::FS::IsFile(qualifiedFromFile))
|
||||
//If we're not using existing materials, or the material in question doesn't actually already exist, spool it up
|
||||
if (!activeImportConfig->UseExistingMaterials || !Sim::findObject(assetName))
|
||||
{
|
||||
//Now write the script file containing our material out
|
||||
//There's 2 ways to do this. If we're in-place importing an existing asset, we can see if the definition existed already, like in an old
|
||||
//materials.tscript file. if it does, we can just find the object by name, and save it out to our new file
|
||||
//If not, we'll just generate one
|
||||
Material* existingMat = MATMGR->getMaterialDefinitionByName(assetName);
|
||||
|
||||
//It's also possible that, for legacy models, the material hooks in via the material's mapTo field, and the material name is something completely different
|
||||
//So we'll check for that as well if we didn't find it by name up above
|
||||
if (existingMat == nullptr)
|
||||
existingMat = MATMGR->getMaterialDefinitionByMapTo(assetName);
|
||||
|
||||
if (existingMat == nullptr && assetItem->assetName != assetItem->cleanAssetName)
|
||||
{
|
||||
existingMat = MATMGR->getMaterialDefinitionByName(assetItem->cleanAssetName);
|
||||
if (existingMat == nullptr)
|
||||
existingMat = MATMGR->getMaterialDefinitionByMapTo(assetItem->cleanAssetName);
|
||||
}
|
||||
|
||||
if (existingMat)
|
||||
{
|
||||
PersistenceManager* persistMgr;
|
||||
if (Sim::findObject("ImageAssetValidator", persistMgr))
|
||||
{
|
||||
for (U32 i = 0; i < assetItem->childAssetItems.size(); i++)
|
||||
{
|
||||
AssetImportObject* childItem = assetItem->childAssetItems[i];
|
||||
|
||||
if (childItem->canImport() || childItem->assetType.compare("ImageAsset") != 0)
|
||||
continue;
|
||||
|
||||
String path = childItem->filePath.getFullFileName();
|
||||
|
||||
String mapFieldName = "";
|
||||
String assetFieldName = "";
|
||||
|
||||
ImageAsset::ImageTypes imageType = ImageAsset::getImageTypeFromName(childItem->imageSuffixType);
|
||||
|
||||
if (imageType == ImageAsset::ImageTypes::Albedo || childItem->imageSuffixType.isEmpty())
|
||||
{
|
||||
mapFieldName = "DiffuseMap";
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::Normal)
|
||||
{
|
||||
mapFieldName = "NormalMap";
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::ORMConfig)
|
||||
{
|
||||
mapFieldName = "ORMConfig";
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::Metalness)
|
||||
{
|
||||
mapFieldName = "MetalMap";
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::AO)
|
||||
{
|
||||
mapFieldName = "AOMap";
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::Roughness)
|
||||
{
|
||||
mapFieldName = "RoughMap";
|
||||
}
|
||||
|
||||
assetFieldName = mapFieldName + "Asset[0]";
|
||||
mapFieldName += "[0]";
|
||||
|
||||
//If there's already an existing image map file on the material definition in this slot, don't override it
|
||||
if (!path.isEmpty())
|
||||
existingMat->writeField(mapFieldName.c_str(), path.c_str());
|
||||
|
||||
String targetAsset = targetModuleId + ":" + childItem->assetName;
|
||||
|
||||
existingMat->writeField(assetFieldName.c_str(), targetAsset.c_str());
|
||||
}
|
||||
|
||||
persistMgr->setDirty(existingMat);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::errorf("ImageAssetValidator not found!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Failed to find original material definition %s!", assetName);
|
||||
activityLog.push_back(importLogBuffer);
|
||||
return tamlPath;
|
||||
}
|
||||
}
|
||||
else if (file->openForWrite(scriptPath.c_str()))
|
||||
{
|
||||
file->writeLine((U8*)"//--- OBJECT WRITE BEGIN ---");
|
||||
|
||||
char lineBuffer[1024];
|
||||
dSprintf(lineBuffer, 1024, "singleton Material(%s) {", assetName);
|
||||
file->writeLine((U8*)lineBuffer);
|
||||
|
||||
dSprintf(lineBuffer, 1024, " mapTo=\"%s\";", assetName);
|
||||
file->writeLine((U8*)lineBuffer);
|
||||
Material* newMat = new Material();
|
||||
newMat->registerObject(assetName);
|
||||
newMat->mMapTo = assetItem->cleanAssetName;
|
||||
|
||||
bool hasRoughness = false;
|
||||
for (U32 i = 0; i < assetItem->childAssetItems.size(); i++)
|
||||
|
|
@ -2922,63 +2962,58 @@ Torque::Path AssetImporter::importMaterialAsset(AssetImportObject* assetItem)
|
|||
if ((!childItem->canImport() && childItem->importStatus != AssetImportObject::UseForDependencies) || childItem->assetType.compare("ImageAsset") != 0)
|
||||
continue;
|
||||
|
||||
String mapFieldName = "";
|
||||
|
||||
String assetFieldName = "";
|
||||
|
||||
ImageAsset::ImageTypes imageType = ImageAsset::getImageTypeFromName(childItem->imageSuffixType);
|
||||
|
||||
String assetMapFillIn = targetModuleId + ":" + childItem->assetName;
|
||||
StringTableEntry assetMapFillInStr = StringTable->insert(assetMapFillIn.c_str());
|
||||
|
||||
if (imageType == ImageAsset::ImageTypes::Albedo || childItem->imageSuffixType.isEmpty())
|
||||
{
|
||||
mapFieldName = "DiffuseMap";
|
||||
newMat->mDiffuseMapAssetId[0] = assetMapFillInStr;
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::Normal)
|
||||
{
|
||||
mapFieldName = "NormalMap";
|
||||
newMat->mNormalMapAssetId[0] = assetMapFillInStr;
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::ORMConfig)
|
||||
{
|
||||
mapFieldName = "ORMConfigMap";
|
||||
newMat->mORMConfigMapAssetId[0] = assetMapFillInStr;
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::Metalness)
|
||||
{
|
||||
mapFieldName = "MetalMap";
|
||||
newMat->mMetalMapAssetId[0] = assetMapFillInStr;
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::AO)
|
||||
{
|
||||
mapFieldName = "AOMap";
|
||||
newMat->mAOMapAssetId[0] = assetMapFillInStr;
|
||||
}
|
||||
else if (imageType == ImageAsset::ImageTypes::Roughness)
|
||||
{
|
||||
mapFieldName = "RoughMap";
|
||||
newMat->mRoughMapAssetId[0] = assetMapFillInStr;
|
||||
hasRoughness = true;
|
||||
}
|
||||
|
||||
assetFieldName = mapFieldName + "Asset";
|
||||
assetFieldName += "[0]";
|
||||
|
||||
//String path = childItem->filePath.getFullFileName();
|
||||
//dSprintf(lineBuffer, 1024, " %s = \"%s\";", mapFieldName.c_str(), path.c_str());
|
||||
//file->writeLine((U8*)lineBuffer);
|
||||
|
||||
dSprintf(lineBuffer, 1024, " %s = \"%s:%s\";", assetFieldName.c_str(), targetModuleId.c_str(), childItem->assetName.c_str());
|
||||
file->writeLine((U8*)lineBuffer);
|
||||
}
|
||||
|
||||
if (hasRoughness)
|
||||
{
|
||||
file->writeLine((U8*)" invertSmoothness = true;");
|
||||
|
||||
newMat->mInvertRoughness[0] = true;
|
||||
}
|
||||
|
||||
file->writeLine((U8*)"};");
|
||||
file->writeLine((U8*)"//--- OBJECT WRITE END ---");
|
||||
|
||||
file->close();
|
||||
newAsset->addObject(newMat);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to write asset script file %s", scriptPath.c_str());
|
||||
dSprintf(importLogBuffer, sizeof(importLogBuffer), "Set to use an existing material, so avoiding writing a material definition to new asset definition for material: %s", assetName);
|
||||
activityLog.push_back(importLogBuffer);
|
||||
return "";
|
||||
}
|
||||
|
||||
Taml tamlWriter;
|
||||
bool importSuccessful = tamlWriter.write(newAsset, tamlPath.c_str());
|
||||
|
||||
if (!importSuccessful)
|
||||
{
|
||||
dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to write asset taml file %s", tamlPath.c_str());
|
||||
activityLog.push_back(importLogBuffer);
|
||||
return "";
|
||||
}
|
||||
|
|
@ -3037,7 +3072,7 @@ Torque::Path AssetImporter::importShapeAsset(AssetImportObject* assetItem)
|
|||
|
||||
//If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original
|
||||
//file path for reimporting support later
|
||||
if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile))
|
||||
if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::isFile(qualifiedFromFile))
|
||||
{
|
||||
newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
|
||||
}
|
||||
|
|
@ -3317,7 +3352,7 @@ Torque::Path AssetImporter::importSoundAsset(AssetImportObject* assetItem)
|
|||
|
||||
//If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original
|
||||
//file path for reimporting support later
|
||||
if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile))
|
||||
if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::isFile(qualifiedFromFile))
|
||||
{
|
||||
newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
|
||||
}
|
||||
|
|
@ -3378,7 +3413,7 @@ Torque::Path AssetImporter::importShapeAnimationAsset(AssetImportObject* assetIt
|
|||
|
||||
//If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original
|
||||
//file path for reimporting support later
|
||||
if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile))
|
||||
if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS:::isFile(qualifiedFromFile))
|
||||
{
|
||||
newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -800,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>
|
||||
|
|
@ -898,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
|
||||
|
|
|
|||
|
|
@ -92,7 +92,9 @@ DefineEngineMethod(AssetImporter, resolveAssetItemIssues, void, (AssetImportObje
|
|||
DefineEngineMethod(AssetImporter, importAssets, void, (),,
|
||||
"Runs the actual import action on the items.")
|
||||
{
|
||||
return object->importAssets();
|
||||
object->importAssets();
|
||||
|
||||
object->acquireAssets();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AssetImporter, getAssetItemCount, S32, (),,
|
||||
|
|
|
|||
|
|
@ -1205,11 +1205,15 @@ void ConvexShape::_updateMaterial()
|
|||
//update our custom surface materials
|
||||
for (U32 i = 0; i<mSurfaceTextures.size(); i++)
|
||||
{
|
||||
mSurfaceTextures[i]._setMaterial(mSurfaceTextures[i].getMaterial());
|
||||
//If we already have the material inst and it hasn't changed, skip
|
||||
if (mSurfaceTextures[i].materialInst &&
|
||||
mSurfaceTextures[i].getMaterialAsset()->getMaterialDefinitionName() == mSurfaceTextures[i].materialInst->getMaterial()->getName())
|
||||
mSurfaceTextures[i].getMaterialAsset()->getMaterialDefinitionName() == mSurfaceTextures[i].materialInst->getMaterial()->getName() &&
|
||||
mSurfaceTextures[i].materialInst->getVertexFormat() == getGFXVertexFormat<VertexType>())
|
||||
continue;
|
||||
|
||||
SAFE_DELETE(mSurfaceTextures[i].materialInst);
|
||||
|
||||
Material* material = mSurfaceTextures[i].getMaterialResource();
|
||||
|
||||
if (material == nullptr)
|
||||
|
|
@ -1227,8 +1231,10 @@ void ConvexShape::_updateMaterial()
|
|||
}
|
||||
}
|
||||
|
||||
_setMaterial(getMaterial());
|
||||
// If the material name matches then don't bother updating it.
|
||||
if (mMaterialInst && getMaterialAsset()->getMaterialDefinitionName() == mMaterialInst->getMaterial()->getName())
|
||||
if (mMaterialInst && getMaterialAsset()->getMaterialDefinitionName() == mMaterialInst->getMaterial()->getName() &&
|
||||
mMaterialInst->getVertexFormat() == getGFXVertexFormat<VertexType>())
|
||||
return;
|
||||
|
||||
SAFE_DELETE( mMaterialInst );
|
||||
|
|
@ -1240,12 +1246,6 @@ void ConvexShape::_updateMaterial()
|
|||
|
||||
mMaterialInst = material->createMatInstance();
|
||||
|
||||
//GFXStateBlockDesc desc;
|
||||
//desc.setCullMode( GFXCullNone );
|
||||
//desc.setBlend( false );
|
||||
|
||||
//mMaterialInst->addStateBlockDesc( desc );
|
||||
|
||||
FeatureSet features = MATMGR->getDefaultFeatures();
|
||||
//features.addFeature( MFT_DiffuseVertColor );
|
||||
|
||||
|
|
@ -1436,10 +1436,12 @@ void ConvexShape::_updateGeometry( bool updateCollision )
|
|||
for (S32 k = 0; k < 3; k++)
|
||||
{
|
||||
pVert->normal = face.normal;
|
||||
pVert->tangent = face.tangent;
|
||||
pVert->color = faceColor;
|
||||
pVert->T = face.tangent;
|
||||
pVert->B = mCross(face.normal,face.tangent);
|
||||
//pVert->color = faceColor;
|
||||
pVert->point = pointList[facePntMap[triangles[j][k]]];
|
||||
pVert->texCoord = face.texcoords[triangles[j][k]];
|
||||
pVert->texCoord2 = pVert->texCoord;
|
||||
|
||||
pVert++;
|
||||
vc++;
|
||||
|
|
|
|||
|
|
@ -77,9 +77,6 @@ GFXDeclareVertexFormat( ConvexVert )
|
|||
|
||||
class PhysicsBody;
|
||||
|
||||
// Define our vertex format here so we don't have to
|
||||
// change it in multiple spots later
|
||||
typedef ConvexVert VertexType;
|
||||
|
||||
class ConvexShape : public SceneObject
|
||||
{
|
||||
|
|
@ -100,6 +97,10 @@ public:
|
|||
// the otherwise excessively deep scoping we had.
|
||||
// eg. ConvexShape::Face::Triangle ...
|
||||
|
||||
// Define our vertex format here so we don't have to
|
||||
// change it in multiple spots later
|
||||
typedef GFXVertexPNTTB VertexType;
|
||||
|
||||
struct Edge
|
||||
{
|
||||
U32 p0;
|
||||
|
|
|
|||
|
|
@ -1425,6 +1425,7 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
ri->prim->numPrimitives = currentBatch->iCount / 3;
|
||||
ri->prim->startVertex = 0;
|
||||
ri->prim->numVertices = currentBatch->vCount;
|
||||
ri->translucentSort = !currentBatch->matInst->getMaterial()->isTranslucent();
|
||||
|
||||
// Ugly hack for ProjectedShadow!
|
||||
if ( customTex )
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ RenderMeshExample::RenderMeshExample()
|
|||
mTypeMask |= StaticObjectType | StaticShapeObjectType;
|
||||
|
||||
INIT_ASSET(Material);
|
||||
mMaterialInst = NULL;
|
||||
}
|
||||
|
||||
RenderMeshExample::~RenderMeshExample()
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ RenderShapeExample::RenderShapeExample()
|
|||
mTypeMask |= StaticObjectType | StaticShapeObjectType;
|
||||
|
||||
// Make sure to initialize our TSShapeInstance to NULL
|
||||
INIT_ASSET(Shape);
|
||||
mShapeInstance = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -652,6 +652,7 @@ void ExplosionData::packData(BitStream* stream)
|
|||
|
||||
PACKDATA_ASSET(ExplosionShape);
|
||||
|
||||
//PACKDATA_SOUNDASSET(Sound);
|
||||
PACKDATA_ASSET(Sound);
|
||||
|
||||
if (stream->writeFlag(particleEmitter))
|
||||
|
|
@ -859,9 +860,6 @@ bool ExplosionData::preload(bool server, String &errorStr)
|
|||
if (Parent::preload(server, errorStr) == false)
|
||||
return false;
|
||||
|
||||
if (!server && !getSoundProfile())
|
||||
return false;
|
||||
|
||||
if( !server )
|
||||
{
|
||||
|
||||
|
|
@ -870,12 +868,18 @@ bool ExplosionData::preload(bool server, String &errorStr)
|
|||
_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()) {
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
|
|
@ -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." );
|
||||
|
||||
|
|
@ -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];
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ void ParticleData::packData(BitStream* stream)
|
|||
stream->writeFloat( times[i], 8);
|
||||
}
|
||||
|
||||
//PACKDATA_ASSET(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_ASSET(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_ASSET(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_ASSET(Texture);
|
||||
UNPACKDATA_ASSET(TextureExt);
|
||||
|
||||
constrain_pos = stream->readFlag();
|
||||
start_angle = 360.0f*stream->readFloat(11);
|
||||
|
|
|
|||
|
|
@ -1562,33 +1562,45 @@ void GameConnection::packetDropped(PacketNotify *note)
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void GameConnection::play2D(SFXProfile* profile)
|
||||
void GameConnection::play2D(StringTableEntry assetId)
|
||||
{
|
||||
postNetEvent(new Sim2DAudioEvent(profile));
|
||||
if (AssetDatabase.isDeclaredAsset(assetId))
|
||||
{
|
||||
postNetEvent(new SimSoundAssetEvent(assetId));
|
||||
}
|
||||
}
|
||||
|
||||
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(assetId, *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(assetId, *transform));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GameConnection::doneScopingScene()
|
||||
|
|
@ -2010,49 +2022,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(StringTableEntry assetId, const MatrixF& mat)
|
||||
{
|
||||
// cant get here unless the asset is declared.
|
||||
mAsset = assetId;
|
||||
|
||||
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(StringTableEntry assetId = StringTable->EmptyString(), const MatrixF& mat = MatrixF::Identity);
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ extern F32 gDecalBias;
|
|||
extern GFXTexHandle gLevelAccuMap;
|
||||
|
||||
/// Default SFXAmbience used to reset the global soundscape.
|
||||
static SFXAmbience sDefaultAmbience;
|
||||
extern SFXAmbience* sDefaultAmbience;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -256,7 +256,7 @@ void LevelInfo::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|||
if( mSoundAmbience )
|
||||
mSoundscape->setAmbience( mSoundAmbience );
|
||||
else
|
||||
mSoundscape->setAmbience( &sDefaultAmbience );
|
||||
mSoundscape->setAmbience( sDefaultAmbience );
|
||||
}
|
||||
|
||||
SFX->setDistanceModel( mSoundDistanceModel );
|
||||
|
|
@ -302,7 +302,7 @@ bool LevelInfo::onAdd()
|
|||
void LevelInfo::onRemove()
|
||||
{
|
||||
if( mSoundscape )
|
||||
mSoundscape->setAmbience( &sDefaultAmbience );
|
||||
mSoundscape->setAmbience( sDefaultAmbience );
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -229,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()
|
||||
|
|
|
|||
|
|
@ -6365,15 +6365,11 @@ U32 Player::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
if(len > 8191)
|
||||
len = 8191;
|
||||
stream->writeInt((S32)len, 13);
|
||||
|
||||
// constrain the range of mRot.z
|
||||
while (mRot.z < 0.0f)
|
||||
mRot.z += M_2PI_F;
|
||||
while (mRot.z > M_2PI_F)
|
||||
mRot.z -= M_2PI_F;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// constrain the range of mRot.z
|
||||
mRot.z = mWrapF(mRot.z, 0.0f, M_2PI_F);
|
||||
|
||||
stream->writeFloat(mRot.z / M_2PI_F, 7);
|
||||
stream->writeSignedFloat(mHead.x / (mDataBlock->maxLookAngle - mDataBlock->minLookAngle), 6);
|
||||
stream->writeSignedFloat(mHead.z / mDataBlock->maxFreelookAngle, 6);
|
||||
|
|
|
|||
|
|
@ -616,3 +616,9 @@ void ExplodePrefabUndoAction::redo()
|
|||
name = Sim::getUniqueName( name );
|
||||
mGroup->assignName( name );
|
||||
}
|
||||
|
||||
DefineEngineMethod(Prefab, getChildGroup, S32, (),,
|
||||
"")
|
||||
{
|
||||
return object->getChildGroup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ struct ShapeBaseImageData: public GameBaseData {
|
|||
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
|
||||
|
|
@ -503,6 +504,8 @@ struct ShapeBaseImageData: public GameBaseData {
|
|||
|
||||
void inspectPostApply();
|
||||
|
||||
void handleStateSoundTrack(const U32& stateId);
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Callbacks
|
||||
|
|
@ -744,13 +747,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
|
||||
|
|
@ -1114,7 +1117,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.
|
||||
|
|
@ -1328,9 +1331,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
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ ShapeBaseImageData::StateData::StateData()
|
|||
spin = IgnoreSpin;
|
||||
recoil = NoRecoil;
|
||||
sound = NULL;
|
||||
soundTrack = NULL;
|
||||
emitter = NULL;
|
||||
shapeSequence = NULL;
|
||||
shapeSequenceScale = true;
|
||||
|
|
@ -257,7 +258,7 @@ ShapeBaseImageData::ShapeBaseImageData()
|
|||
stateShapeSequence[i] = 0;
|
||||
stateScaleShapeSequence[i] = false;
|
||||
|
||||
INIT_ASSET_ARRAY(stateSound, i);
|
||||
INIT_SOUNDASSET_ARRAY(stateSound, i);
|
||||
stateScript[i] = 0;
|
||||
stateEmitter[i] = 0;
|
||||
stateEmitterTime[i] = 0;
|
||||
|
|
@ -371,7 +372,8 @@ bool ShapeBaseImageData::onAdd()
|
|||
s.shapeSequenceScale = stateScaleShapeSequence[i];
|
||||
|
||||
//_setstateSound(getstateSound(i),i);
|
||||
s.sound = getstateSoundAsset(i);
|
||||
handleStateSoundTrack(i);
|
||||
|
||||
s.script = stateScript[i];
|
||||
s.emitter = stateEmitter[i];
|
||||
s.emitterTime = stateEmitterTime[i];
|
||||
|
|
@ -577,6 +579,45 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
return true;
|
||||
}
|
||||
|
||||
void ShapeBaseImageData::handleStateSoundTrack(const U32& stateId)
|
||||
{
|
||||
if (stateId > MaxStates)
|
||||
return;
|
||||
|
||||
StateData& s = state[stateId];
|
||||
|
||||
s.sound = getstateSoundAsset(stateId);
|
||||
|
||||
if (s.sound == NULL)
|
||||
{
|
||||
if (mstateSoundName[stateId] != 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[stateId], sndTrack))
|
||||
{
|
||||
Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %s but failed!", mstateSoundName[stateId]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.soundTrack = sndTrack;
|
||||
}
|
||||
}
|
||||
else if (mstateSoundSFXId[stateId] != 0)
|
||||
{
|
||||
SFXTrack* sndTrack;
|
||||
if (!Sim::findObject(mstateSoundSFXId[stateId], sndTrack))
|
||||
{
|
||||
Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %i but failed!", mstateSoundSFXId[stateId]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.soundTrack = sndTrack;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 ShapeBaseImageData::lookupState(const char* name)
|
||||
{
|
||||
if (!name || !name[0])
|
||||
|
|
@ -1146,7 +1187,7 @@ void ShapeBaseImageData::packData(BitStream* stream)
|
|||
}
|
||||
}
|
||||
|
||||
PACKDATA_ASSET_ARRAY(stateSound, i);
|
||||
PACKDATA_SOUNDASSET_ARRAY(stateSound, i);
|
||||
}
|
||||
stream->write(maxConcurrentSounds);
|
||||
stream->writeFlag(useRemainderDT);
|
||||
|
|
@ -1351,7 +1392,8 @@ void ShapeBaseImageData::unpackData(BitStream* stream)
|
|||
else
|
||||
s.emitter = 0;
|
||||
|
||||
UNPACKDATA_ASSET_ARRAY(stateSound, i);
|
||||
UNPACKDATA_SOUNDASSET_ARRAY(stateSound, i);
|
||||
handleStateSoundTrack(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2580,7 +2622,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;
|
||||
|
|
@ -2611,12 +2653,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...
|
||||
|
|
@ -2632,12 +2674,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;
|
||||
|
|
@ -2665,7 +2707,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;
|
||||
}
|
||||
|
||||
|
|
@ -2673,16 +2715,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2695,10 +2737,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);
|
||||
|
|
@ -2707,7 +2749,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) {
|
||||
|
|
@ -2723,11 +2765,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -2752,7 +2794,7 @@ 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])
|
||||
|
|
@ -2764,17 +2806,25 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
// 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->getSfxProfile(), &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()
|
||||
|
|
|
|||
|
|
@ -419,6 +419,8 @@ bool TSStatic::_createShape()
|
|||
// Reapply the current skin
|
||||
mAppliedSkinName = "";
|
||||
reSkin();
|
||||
|
||||
updateMaterials();
|
||||
}
|
||||
|
||||
prepCollision();
|
||||
|
|
@ -1619,8 +1621,6 @@ void TSStatic::updateMaterials()
|
|||
}
|
||||
}
|
||||
|
||||
mChangingMaterials.clear();
|
||||
|
||||
// Initialize the material instances
|
||||
mShapeInstance->initMaterialList();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue