Skip to content
Snippets Groups Projects
Commit e26bfe00 authored by Seth ProductEngine's avatar Seth ProductEngine
Browse files

STORM-380 FIXED Added syncing animations and sounds before the gesture starts playing.

The actual playing of animations and sounds of a gesture starts only when all needed animations and sound files are loaded into viewer cache. This reduces the delay between animations and sounds meant to be played simultaneously but may increase the delay between the moment a gesture is triggered and the moment it starts playing.

Fixed calling assets callback to clean up the void pointer in getAssetData() and avoid potential memory leaks.
parent 120f3150
No related branches found
No related tags found
No related merge requests found
......@@ -398,6 +398,12 @@ BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType
bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type,
LLGetAssetCallback callback, void *user_data)
{
if (user_data)
{
// The *user_data should not be passed without a callback to clean it up.
llassert(callback != NULL)
}
BOOL exists = mStaticVFS->getExists(uuid, type);
if (exists)
{
......@@ -432,15 +438,26 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL
llinfos << "ASSET_TRACE requesting " << uuid << " type " << LLAssetType::lookup(type) << llendl;
if (user_data)
{
// The *user_data should not be passed without a callback to clean it up.
llassert(callback != NULL)
}
if (mShutDown)
{
llinfos << "ASSET_TRACE cancelled " << uuid << " type " << LLAssetType::lookup(type) << " shutting down" << llendl;
return; // don't get the asset or do any callbacks, we are shutting down
if (callback)
{
callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_NONE);
}
return;
}
if (uuid.isNull())
{
// Special case early out for NULL uuid
// Special case early out for NULL uuid and for shutting down
if (callback)
{
callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
......
......@@ -33,8 +33,10 @@
#include <algorithm>
// library
#include "llaudioengine.h"
#include "lldatapacker.h"
#include "llinventory.h"
#include "llkeyframemotion.h"
#include "llmultigesture.h"
#include "llnotificationsutil.h"
#include "llstl.h"
......@@ -526,6 +528,66 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture)
gesture->mPlaying = TRUE;
mPlaying.push_back(gesture);
// Load all needed assets to minimize the delays
// when gesture is playing.
for (std::vector<LLGestureStep*>::iterator steps_it = gesture->mSteps.begin();
steps_it != gesture->mSteps.end();
++steps_it)
{
LLGestureStep* step = *steps_it;
switch(step->getType())
{
case STEP_ANIMATION:
{
LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
const LLUUID& anim_id = anim_step->mAnimAssetID;
// Don't request the animation if this step stops it or if it is already in Static VFS
if (!(anim_id.isNull()
|| anim_step->mFlags & ANIM_FLAG_STOP
|| gAssetStorage->hasLocalAsset(anim_id, LLAssetType::AT_ANIMATION)))
{
mLoadingAssets.insert(anim_id);
LLUUID* id = new LLUUID(gAgentID);
gAssetStorage->getAssetData(anim_id,
LLAssetType::AT_ANIMATION,
onAssetLoadComplete,
(void *)id,
TRUE);
}
break;
}
case STEP_SOUND:
{
LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
const LLUUID& sound_id = sound_step->mSoundAssetID;
if (!(sound_id.isNull()
|| gAssetStorage->hasLocalAsset(sound_id, LLAssetType::AT_SOUND)))
{
mLoadingAssets.insert(sound_id);
gAssetStorage->getAssetData(sound_id,
LLAssetType::AT_SOUND,
onAssetLoadComplete,
NULL,
TRUE);
}
break;
}
case STEP_CHAT:
case STEP_WAIT:
case STEP_EOF:
{
break;
}
default:
{
llwarns << "Unknown gesture step type: " << step->getType() << llendl;
}
}
}
// And get it going
stepGesture(gesture);
......@@ -741,7 +803,7 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture)
{
return;
}
if (!isAgentAvatarValid()) return;
if (!isAgentAvatarValid() || hasLoadingAssets(gesture)) return;
// Of the ones that started playing, have any stopped?
......@@ -1091,6 +1153,98 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs,
}
}
// static
void LLGestureMgr::onAssetLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status)
{
LLGestureMgr& self = LLGestureMgr::instance();
// Complete the asset loading process depending on the type and
// remove the asset id from pending downloads list.
switch(type)
{
case LLAssetType::AT_ANIMATION:
{
LLKeyframeMotion::onLoadComplete(vfs, asset_uuid, type, user_data, status, ext_status);
self.mLoadingAssets.erase(asset_uuid);
break;
}
case LLAssetType::AT_SOUND:
{
LLAudioEngine::assetCallback(vfs, asset_uuid, type, user_data, status, ext_status);
self.mLoadingAssets.erase(asset_uuid);
break;
}
default:
{
llwarns << "Unexpected asset type: " << type << llendl;
// We don't want to return from this callback without
// an animation or sound callback being fired
// and *user_data handled to avoid memory leaks.
llassert(type == LLAssetType::AT_ANIMATION || type == LLAssetType::AT_SOUND);
}
}
}
// static
bool LLGestureMgr::hasLoadingAssets(LLMultiGesture* gesture)
{
LLGestureMgr& self = LLGestureMgr::instance();
for (std::vector<LLGestureStep*>::iterator steps_it = gesture->mSteps.begin();
steps_it != gesture->mSteps.end();
++steps_it)
{
LLGestureStep* step = *steps_it;
switch(step->getType())
{
case STEP_ANIMATION:
{
LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
const LLUUID& anim_id = anim_step->mAnimAssetID;
if (!(anim_id.isNull()
|| anim_step->mFlags & ANIM_FLAG_STOP
|| self.mLoadingAssets.find(anim_id) == self.mLoadingAssets.end()))
{
return true;
}
break;
}
case STEP_SOUND:
{
LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
const LLUUID& sound_id = sound_step->mSoundAssetID;
if (!(sound_id.isNull()
|| self.mLoadingAssets.find(sound_id) == self.mLoadingAssets.end()))
{
return true;
}
break;
}
case STEP_CHAT:
case STEP_WAIT:
case STEP_EOF:
{
break;
}
default:
{
llwarns << "Unknown gesture step type: " << step->getType() << llendl;
}
}
}
return false;
}
void LLGestureMgr::stopGesture(LLMultiGesture* gesture)
{
......
......@@ -154,9 +154,20 @@ class LLGestureMgr : public LLSingleton<LLGestureMgr>, public LLInventoryFetchIt
// Used by loadGesture
static void onLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
// Used by playGesture to load an asset file
// required to play a gesture step
static void onAssetLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
// Checks whether all animation and sound assets
// needed to play a gesture are loaded.
static bool hasLoadingAssets(LLMultiGesture* gesture);
private:
// Active gestures.
......@@ -172,6 +183,8 @@ class LLGestureMgr : public LLSingleton<LLGestureMgr>, public LLInventoryFetchIt
callback_map_t mCallbackMap;
std::vector<LLMultiGesture*> mPlaying;
BOOL mValid;
std::set<LLUUID> mLoadingAssets;
};
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment