mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-13 11:43:49 +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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ void VEditorButton::onRender( Point2I offset, const RectI& updateRect )
|
|||
{
|
||||
RectI boundsRect( offset, getExtent() );
|
||||
|
||||
if ( mDepressed || mStateOn || mMouseOver )
|
||||
if ( mDepressed || mStateOn || mHighlighted )
|
||||
{
|
||||
renderFilledBorder( boundsRect, mProfile->mBorderColorHL, mProfile->mFillColorHL );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ void afxSpellButton::onRender(Point2I offset, const RectI& updateRect)
|
|||
|
||||
if (mActive)
|
||||
{
|
||||
if (mMouseOver) state = HILIGHT;
|
||||
if (mHighlighted) state = HILIGHT;
|
||||
if (mDepressed || mStateOn) state = DEPRESSED;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -55,11 +55,11 @@ extern StringTableEntry assetAutoUnloadField;
|
|||
//#define ASSET_BASE_AUTOUNLOAD_FIELD "AssetAutoUnload"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class AssetBase : public SimObject
|
||||
class AssetBase : public SimGroup
|
||||
{
|
||||
friend class AssetManager;
|
||||
|
||||
typedef SimObject Parent;
|
||||
typedef SimGroup Parent;
|
||||
|
||||
protected:
|
||||
AssetManager* mpOwningAssetManager;
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@
|
|||
#include "console/sim.h"
|
||||
#endif
|
||||
|
||||
#ifndef _SIMOBJECT_H_
|
||||
#include "console/simObject.h"
|
||||
#ifndef _SIMSET_H_
|
||||
#include "console/simSet.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLEOBJECT_H_
|
||||
|
|
|
|||
|
|
@ -399,7 +399,12 @@ U32 ConditionalExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type)
|
|||
|
||||
TypeReq ConditionalExprNode::getPreferredType()
|
||||
{
|
||||
return trueExpr->getPreferredType();
|
||||
// We can't make it calculate a type based on subsequent expressions as the expression
|
||||
// could be a string, or just numbers. To play it safe, stringify anything that deals with
|
||||
// a conditional, and let the interpreter cast as needed to other types safely.
|
||||
//
|
||||
// See: Regression Test 7 in ScriptTest. It has a string result in the else portion of the ?: ternary.
|
||||
return TypeReqString;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1620,17 +1620,17 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
|
|||
++ip; // To skip the recurse flag if the object wasnt found
|
||||
if (curObject)
|
||||
{
|
||||
SimGroup* group = dynamic_cast<SimGroup*>(curObject);
|
||||
if (group)
|
||||
SimSet* set = dynamic_cast<SimSet*>(curObject);
|
||||
if (set)
|
||||
{
|
||||
StringTableEntry intName = StringTable->insert(stack[_STK].getString());
|
||||
bool recurse = code[ip - 1];
|
||||
SimObject* obj = group->findObjectByInternalName(intName, recurse);
|
||||
SimObject* obj = set->findObjectByInternalName(intName, recurse);
|
||||
stack[_STK].setInt(obj ? obj->getId() : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-group %s of class %s.", getFileLine(ip - 2), curObject->getName(), curObject->getClassName());
|
||||
Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-set %s of class %s.", getFileLine(ip - 2), curObject->getName(), curObject->getClassName());
|
||||
stack[_STK].setInt(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,29 +46,28 @@
|
|||
extern StringStack STR;
|
||||
extern ConsoleValueStack<4096> gCallStack;
|
||||
|
||||
Vector<ConsoleValue::ConversionBuffer> ConsoleValue::sConversionBuffer;
|
||||
DataChunker ConsoleValue::sConversionAllocator;
|
||||
|
||||
void ConsoleValue::init()
|
||||
{
|
||||
sConversionBuffer.reserve(8192);
|
||||
sConversionAllocator.setChunkSize(8092);
|
||||
}
|
||||
|
||||
void ConsoleValue::resetConversionBuffer()
|
||||
{
|
||||
sConversionBuffer.resetAndTreatAsScratchBuffer();
|
||||
sConversionAllocator.freeBlocks();
|
||||
}
|
||||
|
||||
char* ConsoleValue::convertToBuffer() const
|
||||
{
|
||||
ConversionBuffer conversion;
|
||||
char* buffer = static_cast<char*>(sConversionAllocator.alloc(32));
|
||||
|
||||
if (type == ConsoleValueType::cvFloat)
|
||||
dSprintf(conversion.buffer, ConversionBufferStride, "%.9g", f);
|
||||
dSprintf(buffer, 32, "%.9g", f);
|
||||
else
|
||||
dSprintf(conversion.buffer, ConversionBufferStride, "%lld", i);
|
||||
dSprintf(buffer, 32, "%lld", i);
|
||||
|
||||
sConversionBuffer.push_back(std::move(conversion));
|
||||
return sConversionBuffer.last().buffer;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char* ConsoleValue::getConsoleData() const
|
||||
|
|
|
|||
|
|
@ -146,17 +146,7 @@ class ConsoleValue
|
|||
|
||||
S32 type;
|
||||
|
||||
enum Constants
|
||||
{
|
||||
ConversionBufferStride = 32
|
||||
};
|
||||
|
||||
struct ConversionBuffer
|
||||
{
|
||||
char buffer[ConversionBufferStride];
|
||||
};
|
||||
|
||||
static Vector<ConversionBuffer> sConversionBuffer;
|
||||
static DataChunker sConversionAllocator;
|
||||
|
||||
char* convertToBuffer() const;
|
||||
|
||||
|
|
@ -239,8 +229,10 @@ public:
|
|||
return f;
|
||||
if (type == ConsoleValueType::cvInteger)
|
||||
return i;
|
||||
if (isStringType())
|
||||
return dAtof(s);
|
||||
if (type == ConsoleValueType::cvSTEntry)
|
||||
return s == StringTable->EmptyString() ? 0.0f : dAtof(s);
|
||||
if (type == ConsoleValueType::cvString)
|
||||
return dStrcmp(s, "") == 0 ? 0.0f : dAtof(s);
|
||||
return dAtof(getConsoleData());
|
||||
}
|
||||
|
||||
|
|
@ -250,8 +242,10 @@ public:
|
|||
return i;
|
||||
if (type == ConsoleValueType::cvFloat)
|
||||
return f;
|
||||
if (isStringType())
|
||||
return dAtoi(s);
|
||||
if (type == ConsoleValueType::cvSTEntry)
|
||||
return s == StringTable->EmptyString() ? 0 : dAtoi(s);
|
||||
if (type == ConsoleValueType::cvString)
|
||||
return dStrcmp(s, "") == 0 ? 0 : dAtoi(s);
|
||||
return dAtoi(getConsoleData());
|
||||
}
|
||||
|
||||
|
|
@ -275,8 +269,10 @@ public:
|
|||
return (bool)i;
|
||||
if (type == ConsoleValueType::cvFloat)
|
||||
return (bool)f;
|
||||
if (isStringType())
|
||||
return dAtob(s);
|
||||
if (type == ConsoleValueType::cvSTEntry)
|
||||
return s == StringTable->EmptyString() ? false : dAtob(s);
|
||||
if (type == ConsoleValueType::cvString)
|
||||
return dStrcmp(s, "") == 0 ? false : dAtob(s);
|
||||
return dAtob(getConsoleData());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2859,3 +2859,21 @@ DefineEngineFunction(getTimestamp, const char*, (), ,
|
|||
|
||||
return returnBuffer;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
DefineEngineFunction(systemCommand, S32, (const char* commandLineAction, const char* callBackFunction), (""), "")
|
||||
{
|
||||
if (commandLineAction != "")
|
||||
{
|
||||
S32 result = system(commandLineAction);
|
||||
|
||||
if (callBackFunction != "" && callBackFunction[0])
|
||||
{
|
||||
if (Con::isFunction(callBackFunction))
|
||||
Con::executef(callBackFunction, result);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -387,7 +387,17 @@ DefineEngineFunction(isFile, bool, ( const char* fileName ),,
|
|||
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
return Torque::FS::IsFile(fileName);
|
||||
Torque::Path givenPath(fileName);
|
||||
|
||||
if (givenPath.getFileName().isEmpty() && givenPath.getExtension().isNotEmpty())
|
||||
{
|
||||
//specially named or hidden files, like .gitignore parse incorrectly due to having
|
||||
//"no" filename, so we adjust that
|
||||
givenPath.setFileName(String(".") + givenPath.getExtension());
|
||||
givenPath.setExtension("");
|
||||
}
|
||||
|
||||
return Torque::FS::IsFile(givenPath);
|
||||
}
|
||||
|
||||
DefineEngineFunction(isScriptFile, bool, (const char* fileName), ,
|
||||
|
|
@ -860,4 +870,20 @@ DefineEngineFunction( createPath, bool, ( const char* path ),,
|
|||
return Torque::FS::CreatePath(path);
|
||||
}
|
||||
|
||||
DefineEngineFunction(deleteDirectory, bool, (const char* path), ,
|
||||
"@brief Delete a directory from the hard drive\n\n"
|
||||
|
||||
"@param path Name and path of the folder to delete\n"
|
||||
"@note THERE IS NO RECOVERY FROM THIS. Deleted files are gone for good.\n"
|
||||
"@return True if file was successfully deleted\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
static char fileName[1024];
|
||||
static char sandboxFileName[1024];
|
||||
|
||||
Con::expandScriptFilename(fileName, sizeof(fileName), path);
|
||||
Platform::makeFullPathName(fileName, sandboxFileName, sizeof(sandboxFileName));
|
||||
|
||||
return Platform::deleteDirectory(sandboxFileName);
|
||||
}
|
||||
#endif // TORQUE_TOOLS
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ namespace Sim
|
|||
ImplementNamedSet(SFXAmbienceSet)
|
||||
ImplementNamedSet(TerrainMaterialSet)
|
||||
ImplementNamedSet(DataBlockSet);
|
||||
ImplementNamedSet(ForestBrushSet);
|
||||
ImplementNamedSet(ForestItemDataSet);
|
||||
ImplementNamedGroup(ActionMapGroup)
|
||||
ImplementNamedGroup(ClientGroup)
|
||||
ImplementNamedGroup(GuiGroup)
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ namespace Sim
|
|||
DeclareNamedSet(SFXAmbienceSet);
|
||||
DeclareNamedSet(TerrainMaterialSet);
|
||||
DeclareNamedSet(DataBlockSet);
|
||||
DeclareNamedSet(ForestBrushSet);
|
||||
DeclareNamedSet(ForestItemDataSet);
|
||||
DeclareNamedGroup(ActionMapGroup)
|
||||
DeclareNamedGroup(ClientGroup)
|
||||
DeclareNamedGroup(GuiGroup)
|
||||
|
|
|
|||
|
|
@ -565,6 +565,8 @@ void init()
|
|||
InstantiateNamedSet(SFXAmbienceSet);
|
||||
InstantiateNamedSet(TerrainMaterialSet);
|
||||
InstantiateNamedSet(DataBlockSet);
|
||||
InstantiateNamedSet(ForestBrushSet);
|
||||
InstantiateNamedSet(ForestItemDataSet);
|
||||
InstantiateNamedGroup(ActionMapGroup);
|
||||
InstantiateNamedGroup(ClientGroup);
|
||||
InstantiateNamedGroup(GuiGroup);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ SimObject::SimObject()
|
|||
mObjectName = NULL;
|
||||
mOriginalName = NULL;
|
||||
mInternalName = NULL;
|
||||
mInheritFrom = NULL;
|
||||
nextNameObject = nullptr;
|
||||
nextManagerNameObject = nullptr;
|
||||
nextIdObject = NULL;
|
||||
|
|
@ -154,6 +155,9 @@ void SimObject::initPersistFields()
|
|||
|
||||
addProtectedField( "name", TypeName, Offset(mObjectName, SimObject), &setProtectedName, &defaultProtectedGetFn,
|
||||
"Optional global name of this object." );
|
||||
|
||||
addProtectedField("inheritFrom", TypeString, Offset(mInheritFrom, SimObject), &setInheritFrom, &defaultProtectedGetFn,
|
||||
"Optional Name of object to inherit from as a parent.");
|
||||
|
||||
endGroup( "Ungrouped" );
|
||||
|
||||
|
|
@ -300,6 +304,10 @@ bool SimObject::writeField(StringTableEntry fieldname, const char* value)
|
|||
void SimObject::writeFields(Stream &stream, U32 tabStop)
|
||||
{
|
||||
// Write static fields.
|
||||
|
||||
// Create a default object of the same type
|
||||
ConsoleObject* defaultConObject = ConsoleObject::create(getClassName());
|
||||
SimObject* defaultObject = dynamic_cast<SimObject*>(defaultConObject);
|
||||
|
||||
const AbstractClassRep::FieldList &list = getFieldList();
|
||||
|
||||
|
|
@ -328,6 +336,11 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
|
|||
if (!writeField(f->pFieldname, valCopy))
|
||||
continue;
|
||||
|
||||
//If the field hasn't been changed from the default value, then don't bother writing it out
|
||||
const char* defaultValueCheck = defaultObject->getDataField(f->pFieldname, array);
|
||||
if (defaultValueCheck && defaultValueCheck[0] != '\0' && dStricmp(defaultValueCheck, valCopy) == 0)
|
||||
continue;
|
||||
|
||||
val = valCopy;
|
||||
|
||||
U32 expandedBufferSize = ( nBufferSize * 2 ) + dStrlen(f->pFieldname) + 32;
|
||||
|
|
@ -362,6 +375,9 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
|
|||
|
||||
if(mFieldDictionary && mCanSaveFieldDictionary)
|
||||
mFieldDictionary->writeFields(this, stream, tabStop);
|
||||
|
||||
// Cleanup our created default object
|
||||
delete defaultConObject;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1133,7 +1149,7 @@ const char *SimObject::getPrefixedDataField(StringTableEntry fieldName, const ch
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *array, const char *value)
|
||||
void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *_array, const char *value)
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal(fieldName != NULL, "Cannot set object field value with NULL field name.");
|
||||
|
|
@ -1142,7 +1158,7 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
|
|||
// Set value without prefix if there's no value.
|
||||
if (*value == 0)
|
||||
{
|
||||
setDataField(fieldName, NULL, value);
|
||||
setDataField(fieldName, _array, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1156,7 +1172,7 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
|
|||
if (fieldPrefix == StringTable->EmptyString())
|
||||
{
|
||||
// No, so set the data field in the usual way.
|
||||
setDataField(fieldName, NULL, value);
|
||||
setDataField(fieldName, _array, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1167,23 +1183,23 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
|
|||
if (dStrnicmp(value, fieldPrefix, fieldPrefixLength) != 0)
|
||||
{
|
||||
// No, so set the data field in the usual way.
|
||||
setDataField(fieldName, NULL, value);
|
||||
setDataField(fieldName, _array, value);
|
||||
return;
|
||||
}
|
||||
|
||||
// Yes, so set the data excluding the prefix.
|
||||
setDataField(fieldName, NULL, value + fieldPrefixLength);
|
||||
setDataField(fieldName, _array, value + fieldPrefixLength);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const char *SimObject::getPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const S32 fieldType)
|
||||
const char *SimObject::getPrefixedDynamicDataField(StringTableEntry fieldName, const char *_array, const S32 fieldType)
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal(fieldName != NULL, "Cannot get field value with NULL field name.");
|
||||
|
||||
// Fetch field value.
|
||||
const char* pFieldValue = getDataField(fieldName, array);
|
||||
const char* pFieldValue = getDataField(fieldName, _array);
|
||||
|
||||
// Sanity.
|
||||
AssertFatal(pFieldValue != NULL, "Field value cannot be NULL.");
|
||||
|
|
@ -2235,10 +2251,10 @@ bool SimObject::setProtectedName(void *obj, const char *index, const char *data)
|
|||
{
|
||||
if (preventNameChanging)
|
||||
return false;
|
||||
SimObject *object = static_cast<SimObject*>(obj);
|
||||
|
||||
if ( object->isProperlyAdded() )
|
||||
object->assignName( data );
|
||||
SimObject* object = static_cast<SimObject*>(obj);
|
||||
|
||||
if (object->isProperlyAdded())
|
||||
object->assignName(data);
|
||||
|
||||
// always return false because we assign the name here
|
||||
return false;
|
||||
|
|
@ -2246,6 +2262,31 @@ bool SimObject::setProtectedName(void *obj, const char *index, const char *data)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SimObject::setInheritFrom(void* obj, const char* index, const char* data)
|
||||
{
|
||||
SimObject* object = static_cast<SimObject*>(obj);
|
||||
|
||||
SimObject* parent;
|
||||
if (Sim::findObject(data, parent))
|
||||
{
|
||||
object->setCopySource(parent);
|
||||
object->assignFieldsFrom(parent);
|
||||
|
||||
// copy any substitution statements
|
||||
SimDataBlock* parent_db = dynamic_cast<SimDataBlock*>(parent);
|
||||
if (parent_db)
|
||||
{
|
||||
SimDataBlock* currentNewObject_db = dynamic_cast<SimDataBlock*>(object);
|
||||
if (currentNewObject_db)
|
||||
currentNewObject_db->copySubstitutionsFrom(parent_db);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SimObject::inspectPreApply()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -299,6 +299,8 @@ class SimObject: public ConsoleObject, public TamlCallbacks
|
|||
SimObject* nextManagerNameObject;
|
||||
SimObject* nextIdObject;
|
||||
|
||||
StringTableEntry mInheritFrom;
|
||||
|
||||
/// SimGroup we're contained in, if any.
|
||||
SimGroup* mGroup;
|
||||
|
||||
|
|
@ -380,6 +382,9 @@ class SimObject: public ConsoleObject, public TamlCallbacks
|
|||
// Object name protected set method
|
||||
static bool setProtectedName(void *object, const char *index, const char *data);
|
||||
|
||||
// Sets object to inherit default values from
|
||||
static bool setInheritFrom(void* object, const char* index, const char* data);
|
||||
|
||||
public:
|
||||
inline void setProgenitorFile(const char* pFile) { mProgenitorFile = StringTable->insert(pFile); }
|
||||
inline StringTableEntry getProgenitorFile(void) const { return mProgenitorFile; }
|
||||
|
|
|
|||
|
|
@ -1079,6 +1079,22 @@ TEST(Script, MiscRegressions)
|
|||
)");
|
||||
|
||||
ASSERT_EQ(regression6.getBool(), true);
|
||||
|
||||
ConsoleValue regression7 = RunScript(R"(
|
||||
function Tween::vectorAdd(%v1, %v2)
|
||||
{
|
||||
%temp = "";
|
||||
for (%i = 0; %i < getWordCount(%v1); %i++) {
|
||||
%e = getWord(%v1, %i) + getWord(%v2, %i);
|
||||
%temp = %i == 0 ? %e : %temp SPC %e;
|
||||
}
|
||||
|
||||
return %temp;
|
||||
}
|
||||
return Tween::vectorAdd("1 2 3", "4 5 6");
|
||||
)");
|
||||
|
||||
ASSERT_STREQ(regression7.getString(), "5 7 9");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -254,17 +254,16 @@ class String::StringData : protected StringDataImpl
|
|||
public:
|
||||
|
||||
///
|
||||
StringData( const StringChar* data, bool interned = false )
|
||||
StringData( const StringChar* data, U32 length, bool interned = false )
|
||||
{
|
||||
mRefCount = 1;
|
||||
mNumChars = U32_MAX;
|
||||
mHashCase = U32_MAX;
|
||||
mHashNoCase = U32_MAX;
|
||||
mUTF16 = NULL;
|
||||
mLength = length;
|
||||
mIsInterned = interned;
|
||||
|
||||
// mLength is initialized by operator new()
|
||||
|
||||
if( data )
|
||||
{
|
||||
dMemcpy( mData, data, sizeof( StringChar ) * mLength );
|
||||
|
|
@ -280,14 +279,26 @@ class String::StringData : protected StringDataImpl
|
|||
|
||||
~StringData()
|
||||
{
|
||||
AssertFatal( mRefCount == 0, "StringData::~StringData invalid refcount" );
|
||||
|
||||
if( mUTF16 )
|
||||
delete [] mUTF16;
|
||||
}
|
||||
|
||||
TORQUE_NOINLINE void* operator new(size_t size, U32 len);
|
||||
TORQUE_NOINLINE void* operator new( size_t size, U32 len, DataChunker& chunker );
|
||||
void operator delete(void *);
|
||||
|
||||
|
||||
static StringData* Create(const StringChar* data, U32 len, bool interned = false)
|
||||
{
|
||||
void* memory = dMalloc(sizeof(StringData) + sizeof(StringChar) * len);
|
||||
StringData* result = new(memory) StringData(data, len, interned);
|
||||
return result;
|
||||
}
|
||||
|
||||
static StringData* Create(const StringChar* data, U32 len, DataChunker& chunker, bool interned = false)
|
||||
{
|
||||
void* memory = chunker.alloc( sizeof(StringData) + len * sizeof(StringChar));
|
||||
StringData* result = new(memory) StringData(data, len, interned);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isShared() const
|
||||
{
|
||||
return ( mRefCount > 1 );
|
||||
|
|
@ -492,51 +503,6 @@ DefineEngineFunction( dumpStringMemStats, void, (), , "()"
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void* String::StringData::operator new( size_t size, U32 len )
|
||||
{
|
||||
AssertFatal( len != 0, "String::StringData::operator new() - string must not be empty" );
|
||||
StringData *str = static_cast<StringData*>( dMalloc( size + len * sizeof(StringChar) ) );
|
||||
|
||||
str->mLength = len;
|
||||
|
||||
#ifdef TORQUE_DEBUG
|
||||
dFetchAndAdd( sgStringMemBytes, size + len * sizeof(StringChar) );
|
||||
dFetchAndAdd( sgStringInstances, 1 );
|
||||
#endif
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void String::StringData::operator delete(void *ptr)
|
||||
{
|
||||
StringData* sub = static_cast<StringData *>(ptr);
|
||||
AssertFatal( sub->mRefCount == 0, "StringData::delete() - invalid refcount" );
|
||||
|
||||
#ifdef TORQUE_DEBUG
|
||||
dFetchAndAdd( sgStringMemBytes, U32( -( S32( sizeof( StringData ) + sub->mLength * sizeof(StringChar) ) ) ) );
|
||||
dFetchAndAdd( sgStringInstances, U32( -1 ) );
|
||||
#endif
|
||||
|
||||
dFree( ptr );
|
||||
}
|
||||
|
||||
void* String::StringData::operator new( size_t size, U32 len, DataChunker& chunker )
|
||||
{
|
||||
AssertFatal( len != 0, "String::StringData::operator new() - string must not be empty" );
|
||||
StringData *str = static_cast<StringData*>( chunker.alloc( size + len * sizeof(StringChar) ) );
|
||||
|
||||
str->mLength = len;
|
||||
|
||||
#ifdef TORQUE_DEBUG
|
||||
dFetchAndAdd( sgStringMemBytes, size + len * sizeof(StringChar) );
|
||||
dFetchAndAdd( sgStringInstances, 1 );
|
||||
#endif
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
String::String()
|
||||
{
|
||||
PROFILE_SCOPE(String_default_constructor);
|
||||
|
|
@ -556,7 +522,7 @@ String::String(const StringChar *str)
|
|||
if( str && *str )
|
||||
{
|
||||
U32 len = dStrlen(str);
|
||||
_string = new ( len ) StringData( str );
|
||||
_string = StringData::Create(str, len);
|
||||
}
|
||||
else
|
||||
_string = StringData::Empty();
|
||||
|
|
@ -567,7 +533,7 @@ String::String(const StringChar *str, SizeType len)
|
|||
PROFILE_SCOPE(String_char_len_constructor);
|
||||
if (str && *str && len!=0)
|
||||
{
|
||||
_string = new ( len ) StringData( str );
|
||||
_string = StringData::Create(str, len);
|
||||
}
|
||||
else
|
||||
_string = StringData::Empty();
|
||||
|
|
@ -581,7 +547,7 @@ String::String(const UTF16 *str)
|
|||
{
|
||||
UTF8* utf8 = createUTF8string( str );
|
||||
U32 len = dStrlen( utf8 );
|
||||
_string = new ( len ) StringData( utf8 );
|
||||
_string = StringData::Create(utf8, len);
|
||||
delete [] utf8;
|
||||
}
|
||||
else
|
||||
|
|
@ -619,7 +585,7 @@ String String::intern() const
|
|||
|
||||
// Create new.
|
||||
|
||||
StringData* data = new ( length(), sInternTable->mChunker ) StringData( c_str(), true );
|
||||
StringData* data = StringData::Create(c_str(), length(), sInternTable->mChunker, true);
|
||||
iter = sInternTable->insertUnique( data, data );
|
||||
|
||||
return ( *iter ).value;
|
||||
|
|
@ -710,7 +676,7 @@ String& String::operator=(StringChar c)
|
|||
{
|
||||
_string->release();
|
||||
|
||||
_string = new ( 2 ) StringData( 0 );
|
||||
_string = StringData::Create(NULL, 2);
|
||||
_string->utf8()[ 0 ] = c;
|
||||
_string->utf8()[ 1 ] = '\0';
|
||||
|
||||
|
|
@ -721,8 +687,8 @@ String& String::operator+=(StringChar c)
|
|||
{
|
||||
// Append the given string into a new string
|
||||
U32 len = _string->getLength();
|
||||
StringData* sub = new ( len + 1 ) StringData( NULL );
|
||||
|
||||
StringData* sub = StringData::Create(NULL, len + 1);
|
||||
|
||||
copy( sub->utf8(), _string->utf8(), len );
|
||||
sub->utf8()[len] = c;
|
||||
sub->utf8()[len+1] = 0;
|
||||
|
|
@ -748,7 +714,7 @@ String& String::operator=(const StringChar *str)
|
|||
if (str && *str)
|
||||
{
|
||||
U32 len = dStrlen(str);
|
||||
_string = new ( len ) StringData( str );
|
||||
_string = StringData::Create(str, len);
|
||||
}
|
||||
else
|
||||
_string = StringData::Empty();
|
||||
|
|
@ -782,7 +748,7 @@ String& String::operator+=(const StringChar *src)
|
|||
sub = StringData::Empty();
|
||||
else
|
||||
{
|
||||
sub = new ( newlen ) StringData( NULL );
|
||||
sub = StringData::Create(NULL, newlen);
|
||||
|
||||
copy(sub->utf8(),_string->utf8(),lena);
|
||||
copy(sub->utf8() + lena,src,lenb + 1);
|
||||
|
|
@ -809,7 +775,7 @@ String& String::operator+=(const String &src)
|
|||
sub = StringData::Empty();
|
||||
else
|
||||
{
|
||||
sub = new ( newlen ) StringData( NULL );
|
||||
sub = StringData::Create(NULL, newlen);
|
||||
|
||||
copy(sub->utf8(),_string->utf8(),lena);
|
||||
copy(sub->utf8() + lena,src._string->utf8(),lenb + 1);
|
||||
|
|
@ -835,7 +801,7 @@ String operator+(const String &a, const String &b)
|
|||
U32 lena = a.length();
|
||||
U32 lenb = b.length();
|
||||
|
||||
String::StringData *sub = new ( lena + lenb ) String::StringData( NULL );
|
||||
String::StringData* sub = String::StringData::Create(NULL, lena + lenb);
|
||||
|
||||
String::copy(sub->utf8(),a._string->utf8(),lena);
|
||||
String::copy(sub->utf8() + lena,b._string->utf8(),lenb + 1);
|
||||
|
|
@ -848,7 +814,7 @@ String operator+(const String &a, StringChar c)
|
|||
//PROFILE_SCOPE( String_String_plus_Char );
|
||||
|
||||
U32 lena = a.length();
|
||||
String::StringData *sub = new ( lena + 1 ) String::StringData( NULL );
|
||||
String::StringData* sub = String::StringData::Create(NULL, lena + 1);
|
||||
|
||||
String::copy(sub->utf8(),a._string->utf8(),lena);
|
||||
|
||||
|
|
@ -863,7 +829,7 @@ String operator+(StringChar c, const String &a)
|
|||
//PROFILE_SCOPE( String_Char_plus_String );
|
||||
|
||||
U32 lena = a.length();
|
||||
String::StringData *sub = new ( lena + 1 ) String::StringData( NULL );
|
||||
String::StringData* sub = String::StringData::Create(NULL, lena + 1);
|
||||
|
||||
String::copy(sub->utf8() + 1,a._string->utf8(),lena + 1);
|
||||
sub->utf8()[0] = c;
|
||||
|
|
@ -886,7 +852,7 @@ String operator+(const String &a, const StringChar *b)
|
|||
if( !lenb )
|
||||
return a;
|
||||
|
||||
String::StringData *sub = new ( lena + lenb ) String::StringData( NULL );
|
||||
String::StringData* sub = String::StringData::Create(NULL, lena + lenb);
|
||||
|
||||
String::copy(sub->utf8(),a._string->utf8(),lena);
|
||||
String::copy(sub->utf8() + lena,b,lenb + 1);
|
||||
|
|
@ -908,7 +874,7 @@ String operator+(const StringChar *a, const String &b)
|
|||
|
||||
U32 lenb = b.length();
|
||||
|
||||
String::StringData* sub = new ( lena + lenb ) String::StringData( NULL );
|
||||
String::StringData* sub = String::StringData::Create(NULL, lena + lenb);
|
||||
|
||||
String::copy(sub->utf8(),a,lena);
|
||||
String::copy(sub->utf8() + lena,b._string->utf8(),lenb + 1);
|
||||
|
|
@ -1117,7 +1083,7 @@ String& String::insert(SizeType pos, const StringChar *str, SizeType len)
|
|||
sub = StringData::Empty();
|
||||
else
|
||||
{
|
||||
sub = new ( newlen ) StringData( NULL );
|
||||
sub = StringData::Create(NULL, newlen);
|
||||
|
||||
String::copy(sub->utf8(),_string->utf8(),pos);
|
||||
String::copy(sub->utf8() + pos,str,len);
|
||||
|
|
@ -1146,7 +1112,7 @@ String& String::erase(SizeType pos, SizeType len)
|
|||
sub = StringData::Empty();
|
||||
else
|
||||
{
|
||||
sub = new ( newlen ) StringData( NULL );
|
||||
sub = StringData::Create(NULL, newlen);
|
||||
|
||||
if (pos > 0)
|
||||
String::copy(sub->utf8(),_string->utf8(),pos);
|
||||
|
|
@ -1176,7 +1142,7 @@ String& String::replace(SizeType pos, SizeType len, const StringChar *str)
|
|||
sub = StringData::Empty();
|
||||
else
|
||||
{
|
||||
sub = new ( newlen ) StringData( NULL );
|
||||
sub = StringData::Create(NULL, newlen);
|
||||
|
||||
String::copy(sub->utf8(),_string->utf8(), pos);
|
||||
String::copy(sub->utf8() + pos,str,rlen);
|
||||
|
|
@ -1207,7 +1173,8 @@ String& String::replace( StringChar c1, StringChar c2 )
|
|||
{
|
||||
if( !foundReplacement )
|
||||
{
|
||||
sub = new ( length() ) StringData( _string->utf8() );
|
||||
sub = StringData::Create(_string->utf8(), length());
|
||||
|
||||
c = &sub->utf8()[ c - _string->utf8() ];
|
||||
foundReplacement = true;
|
||||
}
|
||||
|
|
@ -1261,7 +1228,7 @@ String &String::replace(const String &s1, const String &s2)
|
|||
sub = StringData::Empty();
|
||||
else
|
||||
{
|
||||
sub = new (newSize - 1 ) StringData( NULL );
|
||||
sub = StringData::Create(NULL, newSize - 1);
|
||||
|
||||
// Now assemble the new string from the pieces of the old...
|
||||
|
||||
|
|
@ -1327,7 +1294,7 @@ String String::substr(SizeType pos, SizeType len) const
|
|||
if( !len )
|
||||
sub = StringData::Empty();
|
||||
else
|
||||
sub = new ( len ) StringData( _string->utf8() + pos );
|
||||
sub = StringData::Create(_string->utf8() + pos, len);
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
|
@ -1356,7 +1323,7 @@ String String::trim() const
|
|||
if( !len )
|
||||
sub = StringData::Empty();
|
||||
else
|
||||
sub = new ( len ) StringData( start );
|
||||
sub = StringData::Create(start, len);
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
|
@ -1573,7 +1540,7 @@ String String::VToString(const char* str, va_list args)
|
|||
sub = StringData::Empty();
|
||||
else
|
||||
{
|
||||
sub = new ( len ) StringData( NULL );
|
||||
sub = StringData::Create(NULL, len);
|
||||
|
||||
format.copy( sub->utf8() );
|
||||
sub->utf8()[ len ] = 0;
|
||||
|
|
@ -1590,7 +1557,7 @@ String String::SpanToString(const char *start, const char *end)
|
|||
AssertFatal( end > start, "Invalid arguments to String::SpanToString - end is before start" );
|
||||
|
||||
U32 len = U32(end - start);
|
||||
StringData* sub = new ( len ) StringData( start );
|
||||
String::StringData* sub = StringData::Create(start, len);
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
|
@ -1600,7 +1567,8 @@ String String::ToLower(const String &string)
|
|||
if ( string.isEmpty() )
|
||||
return String();
|
||||
|
||||
StringData* sub = new ( string.length() ) StringData( string );
|
||||
String::StringData* sub = StringData::Create(string, string.length());
|
||||
|
||||
dStrlwr( sub->utf8() );
|
||||
|
||||
return sub;
|
||||
|
|
@ -1611,7 +1579,8 @@ String String::ToUpper(const String &string)
|
|||
if ( string.isEmpty() )
|
||||
return String();
|
||||
|
||||
StringData* sub = new ( string.length() ) StringData( string );
|
||||
String::StringData* sub = StringData::Create(string, string.length());
|
||||
|
||||
dStrupr( sub->utf8() );
|
||||
|
||||
return sub;
|
||||
|
|
|
|||
|
|
@ -160,7 +160,6 @@ class Vector
|
|||
void erase(U32 index, U32 count);
|
||||
void erase_fast(iterator);
|
||||
void clear();
|
||||
void resetAndTreatAsScratchBuffer();
|
||||
void compact();
|
||||
void sort(compare_func f);
|
||||
void fill( const T& value );
|
||||
|
|
@ -530,15 +529,6 @@ template<class T> inline void Vector<T>::clear()
|
|||
mElementCount = 0;
|
||||
}
|
||||
|
||||
/// This method sets the vector as its 0 and will overwrite memory on subsequent usage.
|
||||
/// Note that the current memory in use is never freed or deallocated, so only use this if the vector
|
||||
/// is being used as a scratch buffer only.
|
||||
template<class T> inline
|
||||
void Vector<T>::resetAndTreatAsScratchBuffer()
|
||||
{
|
||||
mElementCount = 0;
|
||||
}
|
||||
|
||||
template<class T> inline void Vector<T>::compact()
|
||||
{
|
||||
resize(mElementCount);
|
||||
|
|
|
|||
|
|
@ -904,10 +904,6 @@ S32 MountSystem::findByPattern( const Path &inBasePath, const String &inFilePatt
|
|||
|
||||
while ( dir->read( &attrs ) )
|
||||
{
|
||||
// skip hidden files
|
||||
if ( attrs.name.c_str()[0] == '.' )
|
||||
continue;
|
||||
|
||||
String name( attrs.name );
|
||||
|
||||
if ( (attrs.flags & FileNode::Directory) && inRecursive )
|
||||
|
|
|
|||
|
|
@ -734,7 +734,7 @@ void DecalRoad::prepRenderImage( SceneRenderState* state )
|
|||
coreRI.sortDistSq = F32_MAX;
|
||||
|
||||
// If we need lights then set them up.
|
||||
if ( matInst->isForwardLit() )
|
||||
if ( matInst->isForwardLit() && !coreRI.lights[0])
|
||||
{
|
||||
LightQuery query;
|
||||
query.init( getWorldSphere() );
|
||||
|
|
@ -784,6 +784,7 @@ void DecalRoad::prepRenderImage( SceneRenderState* state )
|
|||
|
||||
*ri = coreRI;
|
||||
|
||||
ri->matInst = matInst;
|
||||
ri->prim = renderPass->allocPrim();
|
||||
ri->prim->type = GFXTriangleList;
|
||||
ri->prim->minIndex = 0;
|
||||
|
|
@ -791,6 +792,7 @@ void DecalRoad::prepRenderImage( SceneRenderState* state )
|
|||
ri->prim->numPrimitives = triangleCount;
|
||||
ri->prim->startVertex = 0;
|
||||
ri->prim->numVertices = endBatch.endVert + 1;
|
||||
ri->translucentSort = !matInst->getMaterial()->isTranslucent();
|
||||
|
||||
// For sorting we first sort by render priority
|
||||
// and then by objectId.
|
||||
|
|
|
|||
|
|
@ -651,7 +651,7 @@ void ScatterSky::prepRenderImage( SceneRenderState *state )
|
|||
ObjectRenderInst *ri = renderPass->allocInst<ObjectRenderInst>();
|
||||
ri->renderDelegate.bind( this, &ScatterSky::_render );
|
||||
ri->type = RenderPassManager::RIT_Sky;
|
||||
ri->defaultKey = 10;
|
||||
ri->defaultKey = 15;
|
||||
ri->defaultKey2 = 0;
|
||||
renderPass->addInst(ri);
|
||||
|
||||
|
|
@ -700,7 +700,7 @@ void ScatterSky::prepRenderImage( SceneRenderState *state )
|
|||
moonRI->renderDelegate.bind( this, &ScatterSky::_renderMoon );
|
||||
moonRI->type = RenderPassManager::RIT_Sky;
|
||||
// Render after sky objects and before CloudLayer!
|
||||
moonRI->defaultKey = 5;
|
||||
moonRI->defaultKey = 10;
|
||||
moonRI->defaultKey2 = 0;
|
||||
renderPass->addInst(moonRI);
|
||||
}
|
||||
|
|
@ -758,73 +758,146 @@ bool ScatterSky::_initShader()
|
|||
return true;
|
||||
}
|
||||
|
||||
void ScatterSky::clearVectors()
|
||||
{
|
||||
tmpVertices.clear();
|
||||
vertsVec.clear();
|
||||
}
|
||||
|
||||
void ScatterSky::addVertex(Point3F vert)
|
||||
{
|
||||
vertsVec.push_back(vert.x);
|
||||
vertsVec.push_back(vert.y);
|
||||
vertsVec.push_back(vert.z);
|
||||
}
|
||||
|
||||
void ScatterSky::BuildFinalVert()
|
||||
{
|
||||
U32 count = vertsVec.size();
|
||||
U32 i, j;
|
||||
for (i = 0, j = 0; i < count; i += 3, j += 2)
|
||||
{
|
||||
FinalVertexData temp;
|
||||
temp.pos.set(Point3F(vertsVec[i], vertsVec[i + 1], vertsVec[i + 2]));
|
||||
|
||||
finalVertData.push_back(temp);
|
||||
}
|
||||
}
|
||||
|
||||
void ScatterSky::_initVBIB()
|
||||
{
|
||||
U32 rings = 18;
|
||||
U32 height = 9;
|
||||
U32 radius = 10;
|
||||
|
||||
F32 x, y, z, xy; // vertex position
|
||||
|
||||
F32 ringStep = M_2PI / rings;
|
||||
F32 heightStep = M_HALFPI / height; // M_PI for full sphere.
|
||||
F32 ringAng, heightAng;
|
||||
|
||||
//clear vecs
|
||||
clearVectors();
|
||||
|
||||
for (U32 i = 0; i <= height; ++i)
|
||||
{
|
||||
heightAng = M_PI / 2 - (F32)i * heightStep;
|
||||
xy = radius * mCos(heightAng);
|
||||
z = radius * mSin(heightAng);
|
||||
|
||||
for (U32 j = 0; j <= rings; ++j)
|
||||
{
|
||||
SphereVertex vert;
|
||||
ringAng = j * ringStep;
|
||||
x = xy * mCos(ringAng);
|
||||
y = xy * mSin(ringAng);
|
||||
vert.pos.set(Point3F(x, y, z));
|
||||
|
||||
tmpVertices.push_back(vert);
|
||||
}
|
||||
}
|
||||
|
||||
SphereVertex v1, v2, v3, v4;
|
||||
U32 vi1, vi2 = 0;
|
||||
|
||||
for (U32 i = 0; i < height; ++i)
|
||||
{
|
||||
vi1 = i * (rings + 1);
|
||||
vi2 = (i + 1) * (rings + 1);
|
||||
|
||||
for (U32 j = 0; j < rings; ++j, ++vi1, ++vi2)
|
||||
{
|
||||
v1 = tmpVertices[vi1];
|
||||
v2 = tmpVertices[vi2];
|
||||
v3 = tmpVertices[vi1 + 1];
|
||||
v4 = tmpVertices[vi2 + 1];
|
||||
|
||||
// 1st = triangle.
|
||||
if (i == 0)
|
||||
{
|
||||
// verts for tri.
|
||||
addVertex(v1.pos);
|
||||
addVertex(v2.pos);
|
||||
addVertex(v4.pos);
|
||||
}
|
||||
/* UNCOMMENT WHEN FULL SPHERE
|
||||
else if (i == (height - 1))
|
||||
{
|
||||
// verts for tri.
|
||||
addVertex(v1.pos);
|
||||
addVertex(v2.pos);
|
||||
addVertex(v3.pos);
|
||||
}*/
|
||||
else
|
||||
{
|
||||
// verts for quad.
|
||||
addVertex(v1.pos);
|
||||
addVertex(v2.pos);
|
||||
addVertex(v3.pos);
|
||||
|
||||
addVertex(v3.pos);
|
||||
addVertex(v4.pos);
|
||||
addVertex(v2.pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BuildFinalVert();
|
||||
|
||||
// Vertex Buffer...
|
||||
U32 vertStride = 50;
|
||||
U32 strideMinusOne = vertStride - 1;
|
||||
mVertCount = vertStride * vertStride;
|
||||
mPrimCount = strideMinusOne * strideMinusOne * 2;
|
||||
|
||||
Point3F vertScale( 16.0f, 16.0f, 4.0f );
|
||||
|
||||
F32 zOffset = -( mCos( mSqrt( 1.0f ) ) + 0.01f );
|
||||
mVertCount = finalVertData.size();
|
||||
mPrimCount = mVertCount / 3;
|
||||
|
||||
mVB.set( GFX, mVertCount, GFXBufferTypeStatic );
|
||||
GFXVertexP *pVert = mVB.lock();
|
||||
if(!pVert) return;
|
||||
|
||||
for ( U32 y = 0; y < vertStride; y++ )
|
||||
for ( U32 i = 0; i < mVertCount; i++ )
|
||||
{
|
||||
F32 v = ( (F32)y / (F32)strideMinusOne - 0.5f ) * 2.0f;
|
||||
|
||||
for ( U32 x = 0; x < vertStride; x++ )
|
||||
{
|
||||
F32 u = ( (F32)x / (F32)strideMinusOne - 0.5f ) * 2.0f;
|
||||
|
||||
F32 sx = u;
|
||||
F32 sy = v;
|
||||
F32 sz = (mCos( mSqrt( sx*sx + sy*sy ) ) * 1.0f) + zOffset;
|
||||
//F32 sz = 1.0f;
|
||||
pVert->point.set( sx, sy, sz );
|
||||
pVert->point *= vertScale;
|
||||
pVert->point.set(finalVertData[i].pos);
|
||||
|
||||
pVert->point.normalize();
|
||||
pVert->point *= 200000.0f;
|
||||
|
||||
pVert++;
|
||||
}
|
||||
}
|
||||
|
||||
mVB.unlock();
|
||||
|
||||
// Primitive Buffer...
|
||||
mPrimBuffer.set( GFX, mPrimCount * 3, mPrimCount, GFXBufferTypeStatic );
|
||||
mPrimBuffer.set( GFX, mVertCount, mPrimCount, GFXBufferTypeStatic );
|
||||
|
||||
U16 *pIdx = NULL;
|
||||
mPrimBuffer.lock(&pIdx);
|
||||
U32 curIdx = 0;
|
||||
|
||||
for ( U32 y = 0; y < strideMinusOne; y++ )
|
||||
for ( U32 i = 0, k = 0; i < mPrimCount; i++, k+=3 )
|
||||
{
|
||||
for ( U32 x = 0; x < strideMinusOne; x++ )
|
||||
{
|
||||
U32 offset = x + y * vertStride;
|
||||
|
||||
pIdx[curIdx] = offset;
|
||||
pIdx[curIdx] = k;
|
||||
curIdx++;
|
||||
pIdx[curIdx] = offset + 1;
|
||||
pIdx[curIdx] = k + 1;
|
||||
curIdx++;
|
||||
pIdx[curIdx] = offset + vertStride + 1;
|
||||
pIdx[curIdx] = k + 2;
|
||||
curIdx++;
|
||||
|
||||
pIdx[curIdx] = offset;
|
||||
curIdx++;
|
||||
pIdx[curIdx] = offset + vertStride + 1;
|
||||
curIdx++;
|
||||
pIdx[curIdx] = offset + vertStride;
|
||||
curIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
mPrimBuffer.unlock();
|
||||
|
|
@ -963,21 +1036,17 @@ void ScatterSky::_render( ObjectRenderInst *ri, SceneRenderState *state, BaseMat
|
|||
|
||||
Point3F camPos2 = state->getCameraPosition();
|
||||
MatrixF xfm(true);
|
||||
xfm.setPosition(camPos2 - Point3F(0, 0, mZOffset));
|
||||
xfm.setPosition(Point3F(
|
||||
camPos2.x,
|
||||
camPos2.y,
|
||||
mZOffset) );
|
||||
|
||||
GFX->multWorld(xfm);
|
||||
|
||||
MatrixF xform(proj);//GFX->getProjectionMatrix());
|
||||
xform *= GFX->getViewMatrix();
|
||||
xform *= GFX->getWorldMatrix();
|
||||
|
||||
if(state->isReflectPass())
|
||||
{
|
||||
static MatrixF rotMat(EulerF(0.0, 0.0, M_PI_F));
|
||||
xform.mul(rotMat);
|
||||
rotMat.set(EulerF(M_PI_F, 0.0, 0.0));
|
||||
xform.mul(rotMat);
|
||||
}
|
||||
|
||||
mShaderConsts->setSafe( mModelViewProjSC, xform );
|
||||
mShaderConsts->setSafe( mMiscSC, miscParams );
|
||||
mShaderConsts->setSafe( mSphereRadiiSC, sphereRadii );
|
||||
|
|
|
|||
|
|
@ -104,6 +104,27 @@ public:
|
|||
///
|
||||
F32 getElevation() const { return mSunElevation; }
|
||||
|
||||
struct SphereVertex
|
||||
{
|
||||
Point3F pos;
|
||||
};
|
||||
|
||||
Vector<SphereVertex> tmpVertices;
|
||||
Vector<F32> vertsVec;
|
||||
|
||||
struct FinalVertexData
|
||||
{
|
||||
Point3F pos;
|
||||
};
|
||||
|
||||
Vector<FinalVertexData> finalVertData;
|
||||
|
||||
void addVertex(Point3F vert);
|
||||
|
||||
void BuildFinalVert();
|
||||
|
||||
void clearVectors();
|
||||
|
||||
protected:
|
||||
|
||||
void _render( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
|
||||
|
|
|
|||
|
|
@ -645,4 +645,4 @@ BaseMatInstance* SkyBox::_getMaterialInstance()
|
|||
DefineEngineMethod( SkyBox, postApply, void, (), , "")
|
||||
{
|
||||
object->inspectPostApply();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
645
Engine/source/environment/skySphere.cpp
Normal file
645
Engine/source/environment/skySphere.cpp
Normal file
|
|
@ -0,0 +1,645 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "environment/skySphere.h"
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "scene/sceneRenderState.h"
|
||||
#include "renderInstance/renderPassManager.h"
|
||||
#include "gfx/primBuilder.h"
|
||||
#include "gfx/gfxTransformSaver.h"
|
||||
#include "core/stream/fileStream.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "materials/materialManager.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
#include "materials/sceneData.h"
|
||||
#include "T3D/gameFunctions.h"
|
||||
#include "renderInstance/renderBinManager.h"
|
||||
#include "materials/processedMaterial.h"
|
||||
#include "gfx/gfxDebugEvent.h"
|
||||
#include "math/util/matrixSet.h"
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(SkySphere);
|
||||
|
||||
ConsoleDocClass(SkySphere,
|
||||
"@brief Represents the sky with an artist-created spherical map.\n\n"
|
||||
|
||||
"SkySphere is not a directional light and should be used in conjunction with a Sun object.\n\n"
|
||||
|
||||
"@ingroup Atmosphere"
|
||||
);
|
||||
|
||||
SkySphere::SkySphere()
|
||||
{
|
||||
mTypeMask |= EnvironmentObjectType | StaticObjectType;
|
||||
mNetFlags.set(Ghostable | ScopeAlways);
|
||||
|
||||
INIT_ASSET(Material);
|
||||
mMatInstance = NULL;
|
||||
|
||||
mIsVBDirty = false;
|
||||
mPrimCount = 0;
|
||||
mFogBandHeight = 0;
|
||||
mFogPrimCount = 0;
|
||||
|
||||
mMatrixSet = reinterpret_cast<MatrixSet*>(dMalloc_aligned(sizeof(MatrixSet), 16));
|
||||
constructInPlace(mMatrixSet);
|
||||
|
||||
mFogBandMat = NULL;
|
||||
mFogBandMatInst = NULL;
|
||||
}
|
||||
|
||||
SkySphere::~SkySphere()
|
||||
{
|
||||
dFree_aligned(mMatrixSet);
|
||||
|
||||
if (mMatInstance)
|
||||
SAFE_DELETE(mMatInstance);
|
||||
|
||||
SAFE_DELETE(mFogBandMatInst);
|
||||
|
||||
if (mFogBandMat)
|
||||
{
|
||||
mFogBandMat->deleteObject();
|
||||
mFogBandMat = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool SkySphere::onAdd()
|
||||
{
|
||||
if (!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
setGlobalBounds();
|
||||
resetWorldBox();
|
||||
|
||||
addToScene();
|
||||
|
||||
if (isClientObject())
|
||||
{
|
||||
_initRender();
|
||||
_updateMaterial();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkySphere::onRemove()
|
||||
{
|
||||
removeFromScene();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
void SkySphere::initPersistFields()
|
||||
{
|
||||
addGroup("Sky Sphere");
|
||||
|
||||
INITPERSISTFIELD_MATERIALASSET(Material, SkySphere, "The name of a cubemap material for the sky box.");
|
||||
|
||||
addField("fogBandHeight", TypeF32, Offset(mFogBandHeight, SkySphere),
|
||||
"The height (0-1) of the fog band from the horizon to the top of the SkySphere.");
|
||||
|
||||
endGroup("Sky Sphere");
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
void SkySphere::inspectPostApply()
|
||||
{
|
||||
Parent::inspectPostApply();
|
||||
_updateMaterial();
|
||||
}
|
||||
|
||||
U32 SkySphere::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
|
||||
{
|
||||
U32 retMask = Parent::packUpdate(conn, mask, stream);
|
||||
|
||||
PACK_ASSET(conn, Material);
|
||||
|
||||
stream->write(mFogBandHeight);
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
void SkySphere::unpackUpdate(NetConnection* conn, BitStream* stream)
|
||||
{
|
||||
Parent::unpackUpdate(conn, stream);
|
||||
|
||||
StringTableEntry oldMatName = getMaterial();
|
||||
UNPACK_ASSET(conn, Material);
|
||||
if (oldMatName != getMaterial())
|
||||
{
|
||||
_updateMaterial();
|
||||
}
|
||||
|
||||
F32 bandHeight = 0;
|
||||
stream->read(&bandHeight);
|
||||
|
||||
// If this flag has changed
|
||||
// we need to update the vertex buffer.
|
||||
if ( bandHeight != mFogBandHeight)
|
||||
{
|
||||
mFogBandHeight = bandHeight;
|
||||
mIsVBDirty = true;
|
||||
_initRender();
|
||||
}
|
||||
}
|
||||
|
||||
void SkySphere::prepRenderImage(SceneRenderState* state)
|
||||
{
|
||||
PROFILE_SCOPE(SkySphere_prepRenderImage);
|
||||
|
||||
if (state->isShadowPass() ||
|
||||
mVB.isNull() ||
|
||||
mFogBandVB.isNull() ||
|
||||
!mMatInstance)
|
||||
return;
|
||||
|
||||
mMatrixSet->setSceneView(GFX->getWorldMatrix());
|
||||
mMatrixSet->setSceneProjection(GFX->getProjectionMatrix());
|
||||
|
||||
ObjectRenderInst* ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
|
||||
ri->renderDelegate.bind(this, &SkySphere::_renderObject);
|
||||
ri->type = RenderPassManager::RIT_Sky;
|
||||
ri->defaultKey = 9;
|
||||
ri->defaultKey2 = 0;
|
||||
state->getRenderPass()->addInst(ri);
|
||||
}
|
||||
|
||||
void SkySphere::_renderObject(ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* mi)
|
||||
{
|
||||
GFXDEBUGEVENT_SCOPE(SkySphere_RenderObject, ColorI::WHITE);
|
||||
|
||||
GFXTransformSaver saver;
|
||||
GFX->setVertexBuffer(mVB);
|
||||
|
||||
MatrixF worldMat = MatrixF::Identity;
|
||||
worldMat.setPosition(Point3F(
|
||||
state->getCameraPosition().x,
|
||||
state->getCameraPosition().y,
|
||||
state->getCameraPosition().z));
|
||||
|
||||
SceneData sgData;
|
||||
sgData.init(state);
|
||||
sgData.objTrans = &worldMat;
|
||||
|
||||
mMatrixSet->restoreSceneViewProjection();
|
||||
mMatrixSet->setWorld(worldMat);
|
||||
if (state->isReflectPass())
|
||||
mMatrixSet->setProjection(state->getSceneManager()->getNonClipProjection());
|
||||
|
||||
while (mMatInstance->setupPass(state, sgData))
|
||||
{
|
||||
mMatInstance->setTransforms(*mMatrixSet, state);
|
||||
mMatInstance->setSceneInfo(state, sgData);
|
||||
|
||||
GFX->drawPrimitive(GFXTriangleList, 0, mPrimCount);
|
||||
}
|
||||
|
||||
// Draw render band.
|
||||
if (mFogBandHeight > 0 && mFogBandMatInst)
|
||||
{
|
||||
const FogData& fog = state->getSceneManager()->getFogData();
|
||||
if (mLastFogColor != fog.color)
|
||||
{
|
||||
mLastFogColor = fog.color;
|
||||
_initRender();
|
||||
}
|
||||
|
||||
// Just need it to follow the camera... no rotation.
|
||||
MatrixF camPosMat(MatrixF::Identity);
|
||||
camPosMat.setPosition(worldMat.getPosition());
|
||||
sgData.objTrans = &camPosMat;
|
||||
mMatrixSet->setWorld(*sgData.objTrans);
|
||||
|
||||
while (mFogBandMatInst->setupPass(state, sgData))
|
||||
{
|
||||
mFogBandMatInst->setTransforms(*mMatrixSet, state);
|
||||
mFogBandMatInst->setSceneInfo(state, sgData);
|
||||
|
||||
GFX->setVertexBuffer(mFogBandVB);
|
||||
GFX->drawPrimitive(GFXTriangleList, 0, mFogPrimCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkySphere::clearVectors()
|
||||
{
|
||||
tmpVertices.clear();
|
||||
finalFogVertex.clear();
|
||||
tempFogVertex.clear();
|
||||
colVec.clear();
|
||||
fogVerts.clear();
|
||||
vertsVec.clear();
|
||||
normsVec.clear();
|
||||
texCoordVec.clear();
|
||||
finalVertData.clear();
|
||||
}
|
||||
|
||||
void SkySphere::addVertex(Point3F vert)
|
||||
{
|
||||
vertsVec.push_back(vert.x);
|
||||
vertsVec.push_back(vert.y);
|
||||
vertsVec.push_back(vert.z);
|
||||
}
|
||||
|
||||
void SkySphere::addNormal(Point3F nor)
|
||||
{
|
||||
normsVec.push_back(nor.x);
|
||||
normsVec.push_back(nor.y);
|
||||
normsVec.push_back(nor.z);
|
||||
}
|
||||
|
||||
void SkySphere::addTexcoord(F32 s, F32 t)
|
||||
{
|
||||
texCoordVec.push_back(s);
|
||||
texCoordVec.push_back(t);
|
||||
}
|
||||
|
||||
void SkySphere::addColor(ColorI col)
|
||||
{
|
||||
colVec.push_back(col);
|
||||
}
|
||||
|
||||
void SkySphere::BuildFinalVert()
|
||||
{
|
||||
U32 count = vertsVec.size();
|
||||
U32 i, j;
|
||||
for (i = 0, j = 0; i < count; i += 3, j += 2)
|
||||
{
|
||||
FinalVertexData temp;
|
||||
temp.pos.set(Point3F(vertsVec[i], vertsVec[i + 1], vertsVec[i + 2]));
|
||||
temp.nor.set(Point3F(normsVec[i], normsVec[i + 1], normsVec[i + 2]));
|
||||
temp.s = texCoordVec[j];
|
||||
temp.t = texCoordVec[j+1];
|
||||
|
||||
finalVertData.push_back(temp);
|
||||
}
|
||||
}
|
||||
|
||||
void SkySphere::BuildFinalFogVert()
|
||||
{
|
||||
U32 count = vertsVec.size();
|
||||
U32 i, j;
|
||||
for (i = 0, j = 0; i < count; i+=3, j++ )
|
||||
{
|
||||
FogVertex temp;
|
||||
temp.pos.set(Point3F(vertsVec[i], vertsVec[i + 1], vertsVec[i + 2]));
|
||||
temp.col = colVec[j];
|
||||
|
||||
finalFogVertex.push_back(temp);
|
||||
}
|
||||
}
|
||||
|
||||
void SkySphere::_initRender()
|
||||
{
|
||||
U32 rings = 32;
|
||||
U32 height = 16;
|
||||
U32 radius = 1;
|
||||
|
||||
F32 x, y, z, xy; // vertex position
|
||||
F32 nx, ny, nz, lengthInv = 1.0f / radius; // normal
|
||||
F32 s, t; // texCoord
|
||||
|
||||
F32 ringStep = M_2PI / rings;
|
||||
F32 heightStep = M_PI / height; // M_HALFPI for dome.
|
||||
F32 ringAng, heightAng;
|
||||
|
||||
//clear vecs
|
||||
clearVectors();
|
||||
|
||||
for (U32 i = 0; i <= height; ++i)
|
||||
{
|
||||
heightAng = M_PI / 2 - (F32)i * heightStep;
|
||||
F32 xy = radius * mCos(heightAng);
|
||||
F32 z = radius * mSin(heightAng);
|
||||
|
||||
for (U32 j = 0; j <= rings; ++j)
|
||||
{
|
||||
SphereVertex vert;
|
||||
ringAng = j * ringStep;
|
||||
x = xy * mCos(ringAng);
|
||||
y = xy * mSin(ringAng);
|
||||
vert.pos.set(Point3F(x,y,z));
|
||||
|
||||
nx = x * lengthInv;
|
||||
ny = y * lengthInv;
|
||||
nz = z * lengthInv;
|
||||
vert.nor.set(Point3F(nx, ny, nz));
|
||||
|
||||
s = (F32)j / rings;
|
||||
t = (F32)i / height;
|
||||
vert.s = s;
|
||||
vert.t = t;
|
||||
|
||||
tmpVertices.push_back(vert);
|
||||
}
|
||||
}
|
||||
|
||||
SphereVertex v1, v2, v3, v4;
|
||||
U32 vi1, vi2 = 0;
|
||||
|
||||
for (U32 i = 0; i < height; ++i)
|
||||
{
|
||||
vi1 = i * (rings + 1);
|
||||
vi2 = (i + 1) * (rings + 1);
|
||||
|
||||
for (U32 j = 0; j < rings; ++j, ++vi1, ++vi2)
|
||||
{
|
||||
v1 = tmpVertices[vi1];
|
||||
v2 = tmpVertices[vi2];
|
||||
v3 = tmpVertices[vi1 + 1];
|
||||
v4 = tmpVertices[vi2 + 1];
|
||||
|
||||
// 1st = triangle.
|
||||
if (i == 0)
|
||||
{
|
||||
// verts for tri.
|
||||
addVertex(v1.pos);
|
||||
addVertex(v2.pos);
|
||||
addVertex(v4.pos);
|
||||
|
||||
// texcoords for tri.
|
||||
addTexcoord(v1.s, v1.t);
|
||||
addTexcoord(v2.s, v2.t);
|
||||
addTexcoord(v4.s, v4.t);
|
||||
|
||||
// normals for tri.
|
||||
addNormal(v1.nor);
|
||||
addNormal(v2.nor);
|
||||
addNormal(v4.nor);
|
||||
}
|
||||
else if (i == (height - 1))
|
||||
{
|
||||
// verts for tri.
|
||||
addVertex(v1.pos);
|
||||
addVertex(v2.pos);
|
||||
addVertex(v3.pos);
|
||||
|
||||
// texcoords for tri.
|
||||
addTexcoord(v1.s, v1.t);
|
||||
addTexcoord(v2.s, v2.t);
|
||||
addTexcoord(v3.s, v3.t);
|
||||
|
||||
// normals for quad.
|
||||
addNormal(v1.nor);
|
||||
addNormal(v2.nor);
|
||||
addNormal(v3.nor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// verts for quad.
|
||||
addVertex(v1.pos);
|
||||
addVertex(v2.pos);
|
||||
addVertex(v3.pos);
|
||||
|
||||
addVertex(v3.pos);
|
||||
addVertex(v4.pos);
|
||||
addVertex(v2.pos);
|
||||
|
||||
// texcoords for quad.
|
||||
addTexcoord(v1.s, v1.t);
|
||||
addTexcoord(v2.s, v2.t);
|
||||
addTexcoord(v3.s, v3.t);
|
||||
|
||||
addTexcoord(v3.s, v3.t);
|
||||
addTexcoord(v4.s, v4.t);
|
||||
addTexcoord(v2.s, v2.t);
|
||||
|
||||
// normals for quad.
|
||||
addNormal(v1.nor);
|
||||
addNormal(v2.nor);
|
||||
addNormal(v3.nor);
|
||||
|
||||
addNormal(v3.nor);
|
||||
addNormal(v4.nor);
|
||||
addNormal(v2.nor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BuildFinalVert();
|
||||
|
||||
GFXVertexPNT* tmpVerts = NULL;
|
||||
U32 vertCount = finalVertData.size();
|
||||
tmpVerts = new GFXVertexPNT[(vertCount)];
|
||||
mPrimCount = vertCount / 3;
|
||||
|
||||
for (U32 i = 0; i < vertCount; i++)
|
||||
{
|
||||
tmpVerts[i].point.set(finalVertData[i].pos);
|
||||
tmpVerts[i].normal.set(finalVertData[i].nor);
|
||||
tmpVerts[i].texCoord.set(finalVertData[i].s, finalVertData[i].t);
|
||||
}
|
||||
|
||||
if (mVB.isNull() || mIsVBDirty)
|
||||
{
|
||||
mVB.set(GFX, vertCount, GFXBufferTypeStatic);
|
||||
mIsVBDirty = false;
|
||||
}
|
||||
|
||||
GFXVertexPNT* vertPtr = mVB.lock();
|
||||
if (!vertPtr)
|
||||
{
|
||||
delete[] tmpVerts;
|
||||
return;
|
||||
}
|
||||
|
||||
dMemcpy(vertPtr, tmpVerts, sizeof(GFXVertexPNT) * vertCount);
|
||||
|
||||
mVB.unlock();
|
||||
|
||||
// Clean up temp verts.
|
||||
delete[] tmpVerts;
|
||||
|
||||
// Grab the fog color.
|
||||
ColorI fogColor(mLastFogColor.red * 255, mLastFogColor.green * 255, mLastFogColor.blue * 255);
|
||||
ColorI fogColorAlpha(mLastFogColor.red * 255, mLastFogColor.green * 255, mLastFogColor.blue * 255, 0);
|
||||
|
||||
clearVectors();
|
||||
|
||||
U32 stepCount = 16;
|
||||
F32 cylStep = M_2PI / stepCount;
|
||||
F32 cylAngle;
|
||||
F32 cylRadius = 10;
|
||||
|
||||
for (U32 i = 0; i <= stepCount; ++i)
|
||||
{
|
||||
cylAngle = (F32)i * cylStep;
|
||||
fogVerts.push_back(mCos(cylAngle));
|
||||
fogVerts.push_back(mSin(cylAngle));
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < 2; ++i)
|
||||
{
|
||||
for (U32 j = 0, k = 0; j <= stepCount; ++j, k += 2)
|
||||
{
|
||||
FogVertex temp;
|
||||
F32 ux = fogVerts[k];
|
||||
F32 uy = fogVerts[k+1];
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
temp.pos.set(Point3F((ux * cylRadius), (uy * cylRadius), mFogBandHeight));
|
||||
temp.col = fogColorAlpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.pos.set(Point3F((ux * cylRadius), (uy * cylRadius), -mFogBandHeight));
|
||||
temp.col = fogColor;
|
||||
}
|
||||
|
||||
tempFogVertex.push_back(temp);
|
||||
}
|
||||
}
|
||||
|
||||
FogVertex f1, f2, f3, f4;
|
||||
U32 k1 = 0;
|
||||
U32 k2 = stepCount + 1;
|
||||
|
||||
for (U32 i = 0; i < stepCount; ++i, ++k1, ++k2)
|
||||
{
|
||||
f1 = tempFogVertex[k1];
|
||||
f2 = tempFogVertex[k1 + 1];
|
||||
f3 = tempFogVertex[k2];
|
||||
f4 = tempFogVertex[k2 + 1];
|
||||
addVertex(f3.pos);
|
||||
addVertex(f2.pos);
|
||||
addVertex(f4.pos);
|
||||
addColor(f3.col);
|
||||
addColor(f2.col);
|
||||
addColor(f4.col);
|
||||
addVertex(f1.pos);
|
||||
addVertex(f2.pos);
|
||||
addVertex(f3.pos);
|
||||
addColor(f1.col);
|
||||
addColor(f2.col);
|
||||
addColor(f3.col);
|
||||
}
|
||||
|
||||
BuildFinalFogVert();
|
||||
|
||||
U32 fogVertCount = finalFogVertex.size();
|
||||
mFogPrimCount = fogVertCount / 3;
|
||||
|
||||
if (mFogBandVB.isNull())
|
||||
mFogBandVB.set(GFX, fogVertCount, GFXBufferTypeStatic);
|
||||
|
||||
GFXVertexPC* bandVertPtr = mFogBandVB.lock();
|
||||
if (!bandVertPtr) return;
|
||||
|
||||
for (U32 i = 0; i < fogVertCount; i++)
|
||||
{
|
||||
bandVertPtr[i].point.set(finalFogVertex[i].pos);
|
||||
bandVertPtr[i].color.set(finalFogVertex[i].col);
|
||||
}
|
||||
|
||||
mFogBandVB.unlock();
|
||||
|
||||
SAFE_DELETE(mFogBandMatInst);
|
||||
if (mFogBandMat)
|
||||
{
|
||||
mFogBandMat->deleteObject();
|
||||
mFogBandMat = NULL;
|
||||
}
|
||||
|
||||
// Setup the material for this imposter.
|
||||
mFogBandMat = MATMGR->allocateAndRegister(String::EmptyString);
|
||||
mFogBandMat->mAutoGenerated = true;
|
||||
mFogBandMat->mTranslucent = true;
|
||||
mFogBandMat->mVertColor[0] = true;
|
||||
mFogBandMat->mDoubleSided = true;
|
||||
mFogBandMat->mEmissive[0] = true;
|
||||
|
||||
FeatureSet features = MATMGR->getDefaultFeatures();
|
||||
features.addFeature(MFT_isBackground);
|
||||
mFogBandMatInst = mFogBandMat->createMatInstance();
|
||||
mFogBandMatInst->init(features, getGFXVertexFormat<GFXVertexPC>());
|
||||
}
|
||||
|
||||
void SkySphere::onStaticModified(const char* slotName, const char* newValue)
|
||||
{
|
||||
Parent::onStaticModified(slotName, newValue);
|
||||
|
||||
if (dStricmp(slotName, "material") == 0)
|
||||
setMaskBits(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void SkySphere::_initMaterial()
|
||||
{
|
||||
if (mMatInstance)
|
||||
SAFE_DELETE(mMatInstance);
|
||||
|
||||
if (mMaterial)
|
||||
mMatInstance = mMaterial->createMatInstance();
|
||||
else
|
||||
mMatInstance = MATMGR->createMatInstance("WarningMaterial");
|
||||
|
||||
// We want to disable culling and z write.
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode(GFXCullNone);
|
||||
desc.setBlend(true);
|
||||
desc.setZReadWrite(true, false);
|
||||
desc.zFunc = GFXCmpLessEqual;
|
||||
mMatInstance->addStateBlockDesc(desc);
|
||||
|
||||
// Also disable lighting on the skysphere material by default.
|
||||
FeatureSet features = MATMGR->getDefaultFeatures();
|
||||
features.removeFeature(MFT_RTLighting);
|
||||
features.removeFeature(MFT_Visibility);
|
||||
features.addFeature(MFT_isBackground);
|
||||
|
||||
// Now initialize the material.
|
||||
mMatInstance->init(features, getGFXVertexFormat<GFXVertexPNT>());
|
||||
}
|
||||
|
||||
void SkySphere::_updateMaterial()
|
||||
{
|
||||
if (!getMaterialResource().isValid())
|
||||
{
|
||||
//If our materialDef isn't valid, try setting it
|
||||
_setMaterial(getMaterial());
|
||||
}
|
||||
|
||||
if (getMaterialResource().isValid())
|
||||
{
|
||||
_initMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
BaseMatInstance* SkySphere::_getMaterialInstance()
|
||||
{
|
||||
if (!mMaterial || !mMatInstance || mMatInstance->getMaterial() != mMaterial)
|
||||
_initMaterial();
|
||||
|
||||
if (!mMatInstance)
|
||||
return NULL;
|
||||
|
||||
return mMatInstance;
|
||||
}
|
||||
|
||||
DefineEngineMethod(SkySphere, postApply, void, (), , "")
|
||||
{
|
||||
object->inspectPostApply();
|
||||
}
|
||||
172
Engine/source/environment/skySphere.h
Normal file
172
Engine/source/environment/skySphere.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _SKYSPHERE_H_
|
||||
#define _SKYSPHERE_H_
|
||||
|
||||
#ifndef _SCENEOBJECT_H_
|
||||
#include "scene/sceneObject.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXDEVICE_H_
|
||||
#include "gfx/gfxDevice.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CUBEMAPDATA_H_
|
||||
#include "gfx/sim/cubemapData.h"
|
||||
#endif
|
||||
|
||||
#ifndef _MATERIALLIST_H_
|
||||
#include "materials/materialList.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXVERTEXBUFFER_H_
|
||||
#include "gfx/gfxVertexBuffer.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXPRIMITIVEBUFFER_H_
|
||||
#include "gfx/gfxPrimitiveBuffer.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/assets/MaterialAsset.h"
|
||||
|
||||
struct SkyMatParams
|
||||
{
|
||||
void init(BaseMatInstance* matInst) {};
|
||||
};
|
||||
|
||||
class MatrixSet;
|
||||
|
||||
class SkySphere : public SceneObject
|
||||
{
|
||||
typedef SceneObject Parent;
|
||||
|
||||
public:
|
||||
|
||||
SkySphere();
|
||||
virtual ~SkySphere();
|
||||
|
||||
DECLARE_CONOBJECT(SkySphere);
|
||||
|
||||
// SimObject
|
||||
void onStaticModified(const char* slotName, const char* newValue);
|
||||
|
||||
// ConsoleObject
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
static void initPersistFields();
|
||||
virtual void inspectPostApply();
|
||||
|
||||
// NetObject
|
||||
virtual U32 packUpdate(NetConnection* conn, U32 mask, BitStream* stream);
|
||||
virtual void unpackUpdate(NetConnection* conn, BitStream* stream);
|
||||
|
||||
// SceneObject
|
||||
void prepRenderImage(SceneRenderState* state);
|
||||
|
||||
/// Our render delegate.
|
||||
void _renderObject(ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* mi);
|
||||
|
||||
void clearVectors();
|
||||
|
||||
void addVertex(Point3F vert);
|
||||
|
||||
void addNormal(Point3F nor);
|
||||
|
||||
void addTexcoord(F32 s, F32 t);
|
||||
|
||||
void addColor(ColorI col);
|
||||
|
||||
void BuildFinalVert();
|
||||
|
||||
void BuildFinalFogVert();
|
||||
|
||||
/// Prepares rendering structures and geometry.
|
||||
void _initRender();
|
||||
|
||||
struct SphereVertex
|
||||
{
|
||||
Point3F pos;
|
||||
Point3F nor;
|
||||
F32 s, t;
|
||||
};
|
||||
|
||||
Vector<SphereVertex> tmpVertices;
|
||||
Vector<F32> vertsVec;
|
||||
Vector<F32> texCoordVec;
|
||||
Vector<F32> normsVec;
|
||||
|
||||
struct FinalVertexData
|
||||
{
|
||||
Point3F pos;
|
||||
Point3F nor;
|
||||
F32 s;
|
||||
F32 t;
|
||||
};
|
||||
|
||||
Vector<FinalVertexData> finalVertData;
|
||||
|
||||
struct FogVertex
|
||||
{
|
||||
// might need normals for smoothing.
|
||||
Point3F pos;
|
||||
ColorI col;
|
||||
};
|
||||
|
||||
Vector<FogVertex> finalFogVertex;
|
||||
Vector<FogVertex> tempFogVertex;
|
||||
Vector<ColorI> colVec;
|
||||
Vector<F32> fogVerts;
|
||||
|
||||
protected:
|
||||
|
||||
// Material
|
||||
DECLARE_MATERIALASSET(SkySphere, Material);
|
||||
DECLARE_ASSET_NET_SETGET(SkySphere, Material, -1);
|
||||
|
||||
BaseMatInstance* mMatInstance;
|
||||
SkyMatParams mMatParamHandle;
|
||||
|
||||
GFXVertexBufferHandle<GFXVertexPNT> mVB;
|
||||
|
||||
GFXVertexBufferHandle<GFXVertexPC> mFogBandVB;
|
||||
Material* mFogBandMat;
|
||||
BaseMatInstance* mFogBandMatInst;
|
||||
|
||||
LinearColorF mLastFogColor;
|
||||
|
||||
bool mIsVBDirty;
|
||||
U32 mPrimCount;
|
||||
|
||||
MatrixSet* mMatrixSet;
|
||||
|
||||
F32 mFogBandHeight;
|
||||
U32 mFogPrimCount;
|
||||
|
||||
void _updateMaterial();
|
||||
void _initMaterial();
|
||||
|
||||
BaseMatInstance* _getMaterialInstance();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -197,4 +197,78 @@ DefineEngineMethod( ForestBrush, containsItemData, bool, ( const char * obj ), ,
|
|||
}
|
||||
|
||||
return object->containsItemData( data );
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// ForestBrushGroupSet
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(ForestBrushGroup);
|
||||
|
||||
ConsoleDocClass(ForestBrushGroup,
|
||||
"@brief Container class for ForestBrushes\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
ForestBrushGroup::ForestBrushGroup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool ForestBrushGroup::onAdd()
|
||||
{
|
||||
if (!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
SimSet* forestBrushSet;
|
||||
if (!Sim::findObject("ForestBrushSet", forestBrushSet))
|
||||
{
|
||||
Con::errorf("ForestBrushGroup::onAdd() - failed to find ForestBrushSet to add new ForestBrushGroup to!");
|
||||
}
|
||||
|
||||
forestBrushSet->addObject(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ForestBrushGroup::addObject(SimObject* inObj)
|
||||
{
|
||||
ForestBrush* ele = dynamic_cast<ForestBrush*>(inObj);
|
||||
if (!ele)
|
||||
return;
|
||||
|
||||
//if ( containsItemData( ele->mData ) )
|
||||
// return;
|
||||
|
||||
Parent::addObject(inObj);
|
||||
}
|
||||
|
||||
bool ForestBrushGroup::containsBrushData(const ForestBrush* inData)
|
||||
{
|
||||
SimObjectList::iterator iter = mObjectList.begin();
|
||||
for (; iter != mObjectList.end(); iter++)
|
||||
{
|
||||
ForestBrush* pElement = dynamic_cast<ForestBrush*>(*iter);
|
||||
|
||||
if (!pElement)
|
||||
continue;
|
||||
|
||||
if (pElement == inData)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DefineEngineMethod(ForestBrushGroup, containsBrushData, bool, (const char* obj), , "( ForestBrush obj )")
|
||||
{
|
||||
ForestBrush* data = NULL;
|
||||
if (!Sim::findObject(obj, data))
|
||||
{
|
||||
Con::warnf("ForestBrush::containsBrushData - invalid object passed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return object->containsBrushData(data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,5 +121,28 @@ protected:
|
|||
static SimObjectPtr<SimGroup> smGroup;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// ForestBrushGroup
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#endif // _FOREST_EDITOR_BRUSHELEMENT_H_
|
||||
class ForestBrushGroup : public SimGroup
|
||||
{
|
||||
typedef SimGroup Parent;
|
||||
|
||||
public:
|
||||
|
||||
ForestBrushGroup();
|
||||
|
||||
DECLARE_CONOBJECT(ForestBrushGroup);
|
||||
|
||||
virtual bool onAdd();
|
||||
|
||||
virtual void addObject(SimObject*);
|
||||
|
||||
bool containsBrushData(const ForestBrush* inData);
|
||||
protected:
|
||||
|
||||
static SimObjectPtr<SimGroup> smGroup;
|
||||
};
|
||||
|
||||
#endif // _FOREST_EDITOR_BRUSHELEMENT_H_
|
||||
|
|
|
|||
|
|
@ -610,9 +610,14 @@ void ForestBrushTool::_collectElements()
|
|||
}
|
||||
|
||||
// Find all ForestBrushElements that are directly or indirectly selected.
|
||||
SimSet* brushSet;
|
||||
if (!Sim::findObject("ForestBrushSet", brushSet))
|
||||
{
|
||||
Con::errorf("ForestBrushTool::_collectElements() - could not find ForestBrushSet!");
|
||||
return;
|
||||
}
|
||||
|
||||
SimGroup *brushGroup = ForestBrush::getGroup();
|
||||
brushGroup->findObjectByCallback( findSelectedElements, mElements );
|
||||
brushSet->findObjectByCallback( findSelectedElements, mElements );
|
||||
|
||||
// We just needed to flag these objects as selected for the benefit of our
|
||||
// findSelectedElements callback, we can now mark them un-selected again.
|
||||
|
|
|
|||
|
|
@ -328,10 +328,16 @@ void ForestEditorCtrl::deleteMeshSafe( ForestItemData *mesh )
|
|||
}
|
||||
|
||||
// Find ForestBrushElement(s) referencing this datablock.
|
||||
SimGroup *brushGroup = ForestBrush::getGroup();
|
||||
SimSet* brushSet;
|
||||
if (!Sim::findObject("ForestBrushSet", brushSet))
|
||||
{
|
||||
Con::errorf("ForestBrushTool::_collectElements() - could not find ForestBrushSet!");
|
||||
return;
|
||||
}
|
||||
|
||||
sKey = mesh;
|
||||
Vector<SimObject*> foundElements;
|
||||
brushGroup->findObjectByCallback( &findMeshReferences, foundElements );
|
||||
brushSet->findObjectByCallback( &findMeshReferences, foundElements );
|
||||
|
||||
// Add UndoAction to delete the ForestBrushElement(s) and the ForestItemData.
|
||||
MEDeleteUndoAction *elementAction = new MEDeleteUndoAction();
|
||||
|
|
@ -408,4 +414,4 @@ DefineEngineMethod(ForestEditorCtrl, setActiveForest, void, (const char * obj),
|
|||
return;
|
||||
|
||||
object->setActiveForest(forestObject);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "console/console.h"
|
||||
#include "platform/profiler.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "gfx/bitmap/ddsFile.h"
|
||||
|
||||
using namespace Torque;
|
||||
|
||||
|
|
@ -1361,44 +1362,78 @@ DefineEngineFunction( getBitmapInfo, String, ( const char *filename ),,
|
|||
image->getFormat());
|
||||
}
|
||||
|
||||
DefineEngineFunction(saveScaledImage, bool, (const char* bitmapSource, const char* bitmapDest, S32 resolutionSize), ("", "", 512),
|
||||
"Returns image info in the following format: width TAB height TAB bytesPerPixel TAB format. "
|
||||
"It will return an empty string if the file is not found.\n"
|
||||
"@ingroup Rendering\n")
|
||||
DefineEngineFunction(saveScaledImage, bool, (const char* bitmapSource, const char* bitmapDest, S32 resolutionSize), ("", "", 256),
|
||||
"Loads an image from the source path, and scales it down to the target resolution before"
|
||||
"Saving it out to the destination path.\n")
|
||||
{
|
||||
Resource<GBitmap> image = GBitmap::load(bitmapSource);
|
||||
if (!image)
|
||||
return false;
|
||||
bool isDDS = false;
|
||||
|
||||
Torque::Path sourcePath = Torque::Path(bitmapSource);
|
||||
|
||||
/*if (String("dds").equal(sourcePath.getExtension(), String::NoCase))
|
||||
if (bitmapSource == 0 || bitmapSource[0] == '\0' || bitmapDest == 0 || bitmapDest[0] == '\0')
|
||||
{
|
||||
dds = DDSFile::load(correctPath, scalePower);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Platform::isFile(bitmapSource))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//First, gotta check the extension, as we have some extra work to do if it's
|
||||
//a DDS file
|
||||
const char* ret = dStrrchr(bitmapSource, '.');
|
||||
if (ret)
|
||||
{
|
||||
if (String::ToLower(ret) == String(".dds"))
|
||||
isDDS = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; //no extension? bail out
|
||||
}
|
||||
|
||||
GBitmap* image = NULL;
|
||||
if (isDDS)
|
||||
{
|
||||
Resource<DDSFile> dds = DDSFile::load(bitmapSource, 0);
|
||||
if (dds != NULL)
|
||||
{
|
||||
image = new GBitmap();
|
||||
if (!dds->decompressToGBitmap(image))
|
||||
{
|
||||
delete image;
|
||||
image = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if (isPow2(image->getWidth())&& isPow2(image->getHeight()))
|
||||
}
|
||||
else
|
||||
{
|
||||
Resource<GBitmap> resImage = GBitmap::load(bitmapSource);
|
||||
image = new GBitmap(*resImage);
|
||||
}
|
||||
|
||||
if (!image)
|
||||
return false;
|
||||
Torque::Path sourcePath = Torque::Path(bitmapSource);
|
||||
|
||||
if (isPow2(image->getWidth()) && isPow2(image->getHeight()))
|
||||
image->extrudeMipLevels();
|
||||
|
||||
U32 mipCount = image->getNumMipLevels();
|
||||
U32 targetMips = mFloor(mLog2((F32)resolutionSize)) + 1;
|
||||
U32 targetMips = mFloor(mLog2((F32)(resolutionSize ? resolutionSize : 256))) + 1;
|
||||
|
||||
if (mipCount > targetMips)
|
||||
{
|
||||
image->chopTopMips(mipCount - targetMips);
|
||||
}
|
||||
|
||||
//TODO: support different format targets, for now we just force
|
||||
//to png for simplicity
|
||||
Torque::Path destinationPath = Torque::Path(bitmapDest);
|
||||
destinationPath.setExtension("png");
|
||||
|
||||
// Open up the file on disk.
|
||||
FileStream fs;
|
||||
if (!fs.open(bitmapDest, Torque::FS::File::Write))
|
||||
if (!fs.open(destinationPath.getFullPath(), Torque::FS::File::Write))
|
||||
{
|
||||
Con::errorf("saveScaledImage() - Failed to open output file '%s'!", bitmapDest);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ void GFXCardProfiler::loadProfileScript(const char* aScriptName)
|
|||
|
||||
if(data == NULL)
|
||||
{
|
||||
#if TORQUE_DEBUG
|
||||
#ifdef TORQUE_DEBUG
|
||||
Con::warnf(" - No card profile %s exists", scriptName.c_str());
|
||||
#endif
|
||||
return;
|
||||
|
|
@ -54,7 +54,7 @@ void GFXCardProfiler::loadProfileScript(const char* aScriptName)
|
|||
|
||||
const char *script = static_cast<const char *>(data);
|
||||
|
||||
#if TORQUE_DEBUG
|
||||
#ifdef TORQUE_DEBUG
|
||||
Con::printf(" - Loaded card profile %s", scriptName.c_str());
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@ S32 GFXTextureManager::smTextureReductionLevel = 0;
|
|||
String GFXTextureManager::smMissingTexturePath(Con::getVariable("$Core::MissingTexturePath"));
|
||||
String GFXTextureManager::smUnavailableTexturePath(Con::getVariable("$Core::UnAvailableTexturePath"));
|
||||
String GFXTextureManager::smWarningTexturePath(Con::getVariable("$Core::WarningTexturePath"));
|
||||
String GFXTextureManager::smDefaultIrradianceCubemapPath(Con::getVariable("$Core::DefaultIrradianceCubemap"));
|
||||
String GFXTextureManager::smDefaultPrefilterCubemapPath(Con::getVariable("$Core::DefaultPrefilterCubemap"));
|
||||
String GFXTextureManager::smBRDFTexturePath(Con::getVariable("$Core::BRDFTexture"));
|
||||
|
||||
GFXTextureManager::EventSignal GFXTextureManager::smEventSignal;
|
||||
|
|
@ -75,14 +73,6 @@ void GFXTextureManager::init()
|
|||
"The file path of the texture used to warn the developer.\n"
|
||||
"@ingroup GFX\n" );
|
||||
|
||||
Con::addVariable("$Core::DefaultIrradianceCubemap", TypeRealString, &smDefaultIrradianceCubemapPath,
|
||||
"The file path of the texture used as the default irradiance cubemap for PBR.\n"
|
||||
"@ingroup GFX\n");
|
||||
|
||||
Con::addVariable("$Core::DefaultPrefilterCubemap", TypeRealString, &smDefaultPrefilterCubemapPath,
|
||||
"The file path of the texture used as the default specular cubemap for PBR.\n"
|
||||
"@ingroup GFX\n");
|
||||
|
||||
Con::addVariable("$Core::BRDFTexture", TypeRealString, &smBRDFTexturePath,
|
||||
"The file path of the texture used as the default irradiance cubemap for PBR.\n"
|
||||
"@ingroup GFX\n");
|
||||
|
|
@ -1248,7 +1238,7 @@ GFXTextureObject *GFXTextureManager::createCompositeTexture(GBitmap*bmp[4], U32
|
|||
if (bmp[2])
|
||||
bChan = bmp[2]->getChanelValueAt(x, y, inputKey[2]);
|
||||
else
|
||||
bChan = 255;
|
||||
bChan = 0;
|
||||
|
||||
if (bmp[3])
|
||||
aChan = bmp[3]->getChanelValueAt(x, y, inputKey[3]);
|
||||
|
|
|
|||
|
|
@ -75,9 +75,6 @@ public:
|
|||
/// Provide the path to the texture used to warn the developer
|
||||
static const String& getWarningTexturePath() { return smWarningTexturePath; }
|
||||
|
||||
static const String& getDefaultIrradianceCubemapPath() { return smDefaultIrradianceCubemapPath; }
|
||||
static const String& getDefaultPrefilterCubemapPath() { return smDefaultPrefilterCubemapPath; }
|
||||
|
||||
static const String& getBRDFTexturePath() { return smBRDFTexturePath; }
|
||||
|
||||
/// Update width and height based on available resources.
|
||||
|
|
@ -217,8 +214,6 @@ protected:
|
|||
/// File path to the warning texture
|
||||
static String smWarningTexturePath;
|
||||
|
||||
static String smDefaultIrradianceCubemapPath;
|
||||
static String smDefaultPrefilterCubemapPath;
|
||||
static String smBRDFTexturePath;
|
||||
|
||||
GFXTextureObject *mListHead;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ GFXGLTextureObject::GFXGLTextureObject(GFXDevice * aDevice, GFXTextureProfile *p
|
|||
mFrameAllocatorPtr(NULL)
|
||||
{
|
||||
|
||||
#if TORQUE_DEBUG
|
||||
#ifdef TORQUE_DEBUG
|
||||
mFrameAllocatorMarkGuard = FrameAllocator::getWaterMark();
|
||||
#endif
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel, RectI *inRect)
|
|||
mFrameAllocatorMark = FrameAllocator::getWaterMark();
|
||||
mFrameAllocatorPtr = (U8*)FrameAllocator::alloc( size );
|
||||
mLockedRect.bits = mFrameAllocatorPtr;
|
||||
#if TORQUE_DEBUG
|
||||
#ifdef TORQUE_DEBUG
|
||||
mFrameAllocatorMarkGuard = FrameAllocator::getWaterMark();
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -102,10 +102,10 @@ private:
|
|||
|
||||
//FrameAllocator
|
||||
U32 mFrameAllocatorMark;
|
||||
#if TORQUE_DEBUG
|
||||
#ifdef TORQUE_DEBUG
|
||||
U32 mFrameAllocatorMarkGuard;
|
||||
#endif
|
||||
U8 *mFrameAllocatorPtr;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_READ_FRAMEBUFFER, GL
|
|||
GFXGLPreserveInteger TORQUE_CONCAT(preserve2_, __LINE__) (GL_DRAW_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindFramebuffer)
|
||||
|
||||
|
||||
#if TORQUE_DEBUG
|
||||
#ifdef TORQUE_DEBUG
|
||||
|
||||
// Handy macro for checking the status of a framebuffer. Framebuffers can fail in
|
||||
// all sorts of interesting ways, these are just the most common. Further, no existing GL profiling
|
||||
|
|
|
|||
|
|
@ -138,10 +138,15 @@ void GuiBitmapButtonCtrl::initPersistFields()
|
|||
{
|
||||
addGroup( "Bitmap" );
|
||||
|
||||
INITPERSISTFIELD_IMAGEASSET(Bitmap, GuiBitmapButtonCtrl, "Texture file to display on this button.\n"
|
||||
addProtectedField("Bitmap", TypeImageFilename, Offset(mBitmapName, GuiBitmapButtonCtrl), _setBitmapFieldData, &defaultProtectedGetFn, "Texture file to display on this button.\n"
|
||||
"If useStates is false, this will be the file that renders on the control. Otherwise, this will "
|
||||
"specify the default texture name to which the various state and modifier suffixes are appended "
|
||||
"to find the per-state and per-modifier (if enabled) textures.", AbstractClassRep::FIELD_HideInInspectors); \
|
||||
addProtectedField("BitmapAsset", TypeImageAssetId, Offset(mBitmapAssetId, GuiBitmapButtonCtrl), _setBitmapFieldData, &defaultProtectedGetFn, "Texture file to display on this button.\n"
|
||||
"If useStates is false, this will be the file that renders on the control. Otherwise, this will "
|
||||
"specify the default texture name to which the various state and modifier suffixes are appended "
|
||||
"to find the per-state and per-modifier (if enabled) textures.");
|
||||
|
||||
addField("color", TypeColorI, Offset(mColor, GuiBitmapButtonCtrl), "color mul");
|
||||
|
||||
addField( "bitmapMode", TYPEID< BitmapMode >(), Offset( mBitmapMode, GuiBitmapButtonCtrl ),
|
||||
|
|
@ -196,6 +201,9 @@ void GuiBitmapButtonCtrl::onSleep()
|
|||
mTextures[ i ].mTextureInactive = NULL;
|
||||
}
|
||||
|
||||
if (mBitmapAsset.notNull())
|
||||
mBitmap = NULL;
|
||||
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ class GuiBitmapButtonCtrl : public GuiButtonCtrl
|
|||
if( mActive )
|
||||
{
|
||||
if( mDepressed || mStateOn ) return DEPRESSED;
|
||||
if( mMouseOver ) return HILIGHT;
|
||||
if( mHighlighted ) return HILIGHT;
|
||||
return NORMAL;
|
||||
}
|
||||
else
|
||||
|
|
@ -185,6 +185,14 @@ class GuiBitmapButtonCtrl : public GuiButtonCtrl
|
|||
DECLARE_CONOBJECT(GuiBitmapButtonCtrl);
|
||||
DECLARE_DESCRIPTION( "A button control rendered entirely from bitmaps.\n"
|
||||
"The individual button states are represented with separate bitmaps." );
|
||||
|
||||
//Basically a wrapper function to do our special state handling setup when the fields change
|
||||
static bool _setBitmapFieldData(void* obj, const char* index, const char* data)
|
||||
{
|
||||
GuiBitmapButtonCtrl* object = static_cast<GuiBitmapButtonCtrl*>(obj);
|
||||
object->setBitmap(StringTable->insert(data));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef GuiBitmapButtonCtrl::BitmapMode GuiBitmapMode;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ void GuiBorderButtonCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|||
}
|
||||
}
|
||||
|
||||
if ( mMouseOver )
|
||||
if ( mHighlighted )
|
||||
{
|
||||
RectI bounds( offset, getExtent() );
|
||||
for ( S32 i=0; i < mProfile->mBorderThickness; i++ )
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ EndImplementEnumType;
|
|||
GuiButtonBaseCtrl::GuiButtonBaseCtrl()
|
||||
{
|
||||
mDepressed = false;
|
||||
mMouseOver = false;
|
||||
mHighlighted = false;
|
||||
mActive = true;
|
||||
static StringTableEntry sButton = StringTable->insert( "Button" );
|
||||
mButtonText = sButton;
|
||||
|
|
@ -288,14 +288,14 @@ void GuiButtonBaseCtrl::onMouseEnter(const GuiEvent &event)
|
|||
if(isMouseLocked())
|
||||
{
|
||||
mDepressed = true;
|
||||
mMouseOver = true;
|
||||
mHighlighted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mActive && mProfile->mSoundButtonOver )
|
||||
SFX->playOnce(mProfile->mSoundButtonOver);
|
||||
|
||||
mMouseOver = true;
|
||||
mHighlighted = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -309,7 +309,7 @@ void GuiButtonBaseCtrl::onMouseLeave(const GuiEvent &)
|
|||
onMouseLeave_callback();
|
||||
if( isMouseLocked() )
|
||||
mDepressed = false;
|
||||
mMouseOver = false;
|
||||
mHighlighted = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -542,3 +542,17 @@ DefineEngineMethod( GuiButtonBaseCtrl, resetState, void, (),,
|
|||
{
|
||||
object->resetState();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiButtonBaseCtrl, setHighlighted, void, (bool highlighted), (false),
|
||||
"Reset the mousing state of the button.\n\n"
|
||||
"This method should not generally be called.")
|
||||
{
|
||||
object->setHighlighted(highlighted);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiButtonBaseCtrl, isHighlighted, bool, (),,
|
||||
"Reset the mousing state of the button.\n\n"
|
||||
"This method should not generally be called.")
|
||||
{
|
||||
return object->isHighlighted();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class GuiButtonBaseCtrl : public GuiControl
|
|||
StringTableEntry mButtonText;
|
||||
StringTableEntry mButtonTextID;
|
||||
bool mDepressed;
|
||||
bool mMouseOver;
|
||||
bool mHighlighted;
|
||||
bool mStateOn;
|
||||
S32 mButtonType;
|
||||
S32 mRadioGroup;
|
||||
|
|
@ -95,7 +95,10 @@ class GuiButtonBaseCtrl : public GuiControl
|
|||
bool getStateOn() const { return mStateOn; }
|
||||
|
||||
void setDepressed( bool depressed ) { mDepressed = depressed; }
|
||||
void resetState() {mDepressed = false; mMouseOver = false;}
|
||||
void resetState() {mDepressed = false; mHighlighted = false;}
|
||||
|
||||
void setHighlighted(bool highlighted) { mHighlighted = highlighted; }
|
||||
bool isHighlighted() { return mHighlighted; }
|
||||
|
||||
void acceleratorKeyPress(U32 index);
|
||||
void acceleratorKeyRelease(U32 index);
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ bool GuiButtonCtrl::onWake()
|
|||
void GuiButtonCtrl::onRender(Point2I offset,
|
||||
const RectI& updateRect)
|
||||
{
|
||||
bool highlight = mMouseOver;
|
||||
bool highlight = mHighlighted;
|
||||
bool depressed = mDepressed;
|
||||
|
||||
ColorI fontColor = mActive ? ( highlight ? mProfile->mFontColorHL : mProfile->mFontColor ) : mProfile->mFontColorNA;
|
||||
|
|
@ -107,7 +107,7 @@ void GuiButtonCtrl::onRender(Point2I offset,
|
|||
indexMultiplier = 4;
|
||||
else if ( mDepressed || mStateOn )
|
||||
indexMultiplier = 2;
|
||||
else if ( mMouseOver )
|
||||
else if ( mHighlighted )
|
||||
indexMultiplier = 3;
|
||||
|
||||
renderSizableBitmapBordersFilled( boundsRect, indexMultiplier, mProfile );
|
||||
|
|
@ -123,3 +123,4 @@ void GuiButtonCtrl::onRender(Point2I offset,
|
|||
//render the children
|
||||
renderChildControls( offset, updateRect);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ void GuiCheckBoxCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|||
}
|
||||
|
||||
ColorI backColor = mActive ? mProfile->mFillColor : mProfile->mFillColorNA;
|
||||
ColorI fontColor = mActive ? (mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor) : mProfile->mFontColorNA;
|
||||
ColorI fontColor = mActive ? (mHighlighted ? mProfile->mFontColorHL : mProfile->mFontColor) : mProfile->mFontColorNA;
|
||||
ColorI insideBorderColor = isFirstResponder() ? mProfile->mBorderColorHL : mProfile->mBorderColor;
|
||||
|
||||
// just draw the check box and the text:
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ void GuiIconButtonCtrl::onRender(Point2I offset, const RectI& updateRect)
|
|||
|
||||
void GuiIconButtonCtrl::renderButton( Point2I &offset, const RectI& updateRect )
|
||||
{
|
||||
bool highlight = mMouseOver;
|
||||
bool highlight = mHighlighted;
|
||||
bool depressed = mDepressed;
|
||||
|
||||
ColorI fontColor = mActive ? (highlight ? mProfile->mFontColorHL : mProfile->mFontColor) : mProfile->mFontColorNA;
|
||||
|
|
@ -236,14 +236,19 @@ void GuiIconButtonCtrl::renderButton( Point2I &offset, const RectI& updateRect )
|
|||
else
|
||||
renderSlightlyLoweredBox(boundsRect, mProfile);
|
||||
}
|
||||
else if(mMouseOver && mActive)
|
||||
else if(mHighlighted && mActive)
|
||||
{
|
||||
// If there is a bitmap array then render using it.
|
||||
// Otherwise use a standard fill.
|
||||
if(mProfile->mUseBitmapArray && mProfile->mBitmapArrayRects.size())
|
||||
if (mProfile->mUseBitmapArray && mProfile->mBitmapArrayRects.size())
|
||||
{
|
||||
renderBitmapArray(boundsRect, stateMouseOver);
|
||||
}
|
||||
else
|
||||
renderSlightlyRaisedBox(boundsRect, mProfile);
|
||||
{
|
||||
drawer->drawRectFill(boundsRect, mProfile->mFillColorHL);
|
||||
drawer->drawRect(boundsRect, mProfile->mBorderColorHL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -258,8 +263,16 @@ void GuiIconButtonCtrl::renderButton( Point2I &offset, const RectI& updateRect )
|
|||
}
|
||||
else
|
||||
{
|
||||
drawer->drawRectFill(boundsRect, mProfile->mFillColorNA);
|
||||
drawer->drawRect(boundsRect, mProfile->mBorderColorNA);
|
||||
if (mActive)
|
||||
{
|
||||
drawer->drawRectFill(boundsRect, mProfile->mFillColor);
|
||||
drawer->drawRect(boundsRect, mProfile->mBorderColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawer->drawRectFill(boundsRect, mProfile->mFillColorNA);
|
||||
drawer->drawRect(boundsRect, mProfile->mBorderColorNA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +315,7 @@ void GuiIconButtonCtrl::renderButton( Point2I &offset, const RectI& updateRect )
|
|||
}
|
||||
else
|
||||
{
|
||||
iconRect.set( offset + mButtonMargin, getExtent() - (mButtonMargin * 2) );
|
||||
iconRect.set( offset + mButtonMargin, getExtent() - (Point2I(mAbs(mButtonMargin.x), mAbs(mButtonMargin.y)) * 2) );
|
||||
|
||||
if ( mMakeIconSquare )
|
||||
{
|
||||
|
|
@ -313,6 +326,20 @@ void GuiIconButtonCtrl::renderButton( Point2I &offset, const RectI& updateRect )
|
|||
iconRect.extent.x = iconRect.extent.y;
|
||||
}
|
||||
|
||||
if (mIconLocation == IconLocRight)
|
||||
{
|
||||
iconRect.point.x = (offset.x + getWidth()) - iconRect.extent.x + mButtonMargin.x;
|
||||
}
|
||||
else if (mIconLocation == IconLocLeft)
|
||||
{
|
||||
//default state presumes left positioning
|
||||
}
|
||||
else if (mIconLocation == IconLocCenter)
|
||||
{
|
||||
iconRect.point.x = offset.x + (getWidth() / 2) - (iconRect.extent.x / 2) + mButtonMargin.x;
|
||||
iconRect.point.y = offset.y + (getHeight() / 2) - (iconRect.extent.y / 2) + mButtonMargin.y;
|
||||
}
|
||||
|
||||
drawer->drawBitmapStretch( mBitmap, iconRect );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ bool GuiSwatchButtonCtrl::onWake()
|
|||
|
||||
void GuiSwatchButtonCtrl::onRender( Point2I offset, const RectI &updateRect )
|
||||
{
|
||||
bool highlight = mMouseOver;
|
||||
bool highlight = mHighlighted;
|
||||
|
||||
ColorI borderColor = mActive ? ( highlight ? mProfile->mBorderColorHL : mProfile->mBorderColor ) : mProfile->mBorderColorNA;
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ void GuiToggleButtonCtrl::onPreRender()
|
|||
void GuiToggleButtonCtrl::onRender(Point2I offset,
|
||||
const RectI& updateRect)
|
||||
{
|
||||
bool highlight = mMouseOver;
|
||||
bool highlight = mHighlighted;
|
||||
bool depressed = mDepressed;
|
||||
|
||||
ColorI fontColor = mActive ? ( highlight ? mProfile->mFontColorHL : mProfile->mFontColor ) : mProfile->mFontColorNA;
|
||||
|
|
@ -89,7 +89,7 @@ void GuiToggleButtonCtrl::onRender(Point2I offset,
|
|||
indexMultiplier = 4;
|
||||
else if ( mDepressed || mStateOn )
|
||||
indexMultiplier = 2;
|
||||
else if ( mMouseOver )
|
||||
else if ( mHighlighted )
|
||||
indexMultiplier = 3;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ void GuiToolboxButtonCtrl::onRender(Point2I offset, const RectI& updateRect)
|
|||
RectI r(offset, getExtent());
|
||||
if ( mDepressed || mStateOn )
|
||||
renderStateRect( mLoweredBitmap , r );
|
||||
else if ( mMouseOver )
|
||||
else if ( mHighlighted )
|
||||
renderStateRect( mHoverBitmap , r );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ IMPLEMENT_CALLBACK( GuiWindowCtrl, onCollapse, void, (), (),
|
|||
"Called when the window is collapsed by clicking its title bar." );
|
||||
IMPLEMENT_CALLBACK( GuiWindowCtrl, onRestore, void, (), (),
|
||||
"Called when the window is restored from minimized, maximized, or collapsed state." );
|
||||
IMPLEMENT_CALLBACK(GuiWindowCtrl, onResize, void, (S32 posX, S32 posY, S32 width, S32 height), (0, 0, 0, 0),
|
||||
"Called when the window is resized in a regular manner by mouse manipulation.");
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -1557,6 +1560,8 @@ bool GuiWindowCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
|
|||
// Set the button coords
|
||||
positionButtons();
|
||||
|
||||
onResize_callback(newPosition.x, newPosition.y, newExtent.x, newExtent.y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ class GuiWindowCtrl : public GuiContainer
|
|||
DECLARE_CALLBACK( void, onMaximize, () );
|
||||
DECLARE_CALLBACK( void, onCollapse, () );
|
||||
DECLARE_CALLBACK( void, onRestore, () );
|
||||
DECLARE_CALLBACK(void, onResize, (S32 posX, S32 posY, S32 width, S32 height));
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ bool GuiBitmapCtrl::onWake()
|
|||
return false;
|
||||
setActive(true);
|
||||
|
||||
setBitmap(getBitmap());
|
||||
if (mBitmapName != StringTable->insert("texhandle"))
|
||||
setBitmap(getBitmap());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +153,7 @@ void GuiBitmapCtrl::setBitmapHandle(GFXTexHandle handle, bool resize)
|
|||
{
|
||||
mBitmap = handle;
|
||||
|
||||
mBitmapName = String("texhandle");
|
||||
mBitmapName = StringTable->insert("texhandle");
|
||||
|
||||
// Resize the control to fit the bitmap
|
||||
if (resize)
|
||||
|
|
|
|||
|
|
@ -146,12 +146,14 @@ void GuiDecoyCtrl::onMouseMove(const GuiEvent &event)
|
|||
GuiControl *tempControl = parent->findHitControl(localPoint);
|
||||
|
||||
//the decoy control has the responsibility of keeping track of the decoyed controls status
|
||||
if(mMouseOverDecoy == false && mDecoyReference != NULL)
|
||||
if(mMouseOverDecoy == false && mDecoyReference != NULL &&
|
||||
!mDecoyReference->isDeleted() && !mDecoyReference->isRemoved())
|
||||
{
|
||||
tempControl->onMouseEnter(event);
|
||||
mMouseOverDecoy = true;
|
||||
}
|
||||
else if(tempControl != mDecoyReference && mDecoyReference != NULL)
|
||||
else if(tempControl != mDecoyReference && mDecoyReference != NULL &&
|
||||
!mDecoyReference->isDeleted() && !mDecoyReference->isRemoved())
|
||||
{
|
||||
mDecoyReference->onMouseLeave(event);
|
||||
mMouseOverDecoy = false;
|
||||
|
|
|
|||
1157
Engine/source/gui/controls/guiGameSettingsCtrl.cpp
Normal file
1157
Engine/source/gui/controls/guiGameSettingsCtrl.cpp
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue