summaryrefslogtreecommitdiff
path: root/indra/newview/llgesturemgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llgesturemgr.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llgesturemgr.cpp532
1 files changed, 419 insertions, 113 deletions
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index 59274c8638..119872ec29 100644..100755
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -2,31 +2,25 @@
* @file llgesturemgr.cpp
* @brief Manager for playing gestures on the viewer
*
- * $LicenseInfo:firstyear=2004&license=viewergpl$
- *
- * Copyright (c) 2004-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,12 +31,15 @@
// system
#include <functional>
#include <algorithm>
-#include <boost/tokenizer.hpp>
// library
+#include "llaudioengine.h"
#include "lldatapacker.h"
+#include "llfloaterreg.h"
#include "llinventory.h"
+#include "llkeyframemotion.h"
#include "llmultigesture.h"
+#include "llnotificationsutil.h"
#include "llstl.h"
#include "llstring.h" // todo: remove
#include "llvfile.h"
@@ -52,30 +49,35 @@
#include "llagent.h"
#include "lldelayedgestureerror.h"
#include "llinventorymodel.h"
-#include "llnotify.h"
#include "llviewermessage.h"
#include "llvoavatarself.h"
#include "llviewerstats.h"
-#include "llnearbychatbar.h"
+#include "llfloaterimnearbychat.h"
+#include "llappearancemgr.h"
+#include "llgesturelistener.h"
// Longest time, in seconds, to wait for all animations to stop playing
const F32 MAX_WAIT_ANIM_SECS = 30.f;
+// If this gesture is a link, get the base gesture that this link points to,
+// otherwise just return this id.
+static const LLUUID& get_linked_uuid(const LLUUID& item_id);
// Lightweight constructor.
// init() does the heavy lifting.
-LLGestureManager::LLGestureManager()
+LLGestureMgr::LLGestureMgr()
: mValid(FALSE),
mPlaying(),
mActive(),
mLoadingCount(0)
{
gInventory.addObserver(this);
+ mListener.reset(new LLGestureListener());
}
// We own the data for gestures, so clean them up.
-LLGestureManager::~LLGestureManager()
+LLGestureMgr::~LLGestureMgr()
{
item_map_t::iterator it;
for (it = mActive.begin(); it != mActive.end(); ++it)
@@ -89,18 +91,55 @@ LLGestureManager::~LLGestureManager()
}
-void LLGestureManager::init()
+void LLGestureMgr::init()
{
// TODO
}
+void LLGestureMgr::changed(U32 mask)
+{
+ LLInventoryFetchItemsObserver::changed(mask);
+
+ if (mask & LLInventoryObserver::GESTURE)
+ {
+ // If there was a gesture label changed, update all the names in the
+ // active gestures and then notify observers
+ if (mask & LLInventoryObserver::LABEL)
+ {
+ for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
+ {
+ if(it->second)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(it->first);
+ if(item)
+ {
+ it->second->mName = item->getName();
+ }
+ }
+ }
+ notifyObservers();
+ }
+ // If there was a gesture added or removed notify observers
+ // STRUCTURE denotes that the inventory item has been moved
+ // In the case of deleting gesture, it is moved to the trash
+ else if(mask & LLInventoryObserver::ADD ||
+ mask & LLInventoryObserver::REMOVE ||
+ mask & LLInventoryObserver::STRUCTURE)
+ {
+ notifyObservers();
+ }
+ }
+}
+
// Use this version when you have the item_id but not the asset_id,
// and you KNOW the inventory is loaded.
-void LLGestureManager::activateGesture(const LLUUID& item_id)
+void LLGestureMgr::activateGesture(const LLUUID& item_id)
{
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if (!item) return;
+ if (item->getType() != LLAssetType::AT_GESTURE)
+ return;
LLUUID asset_id = item->getAssetUUID();
@@ -113,7 +152,7 @@ void LLGestureManager::activateGesture(const LLUUID& item_id)
}
-void LLGestureManager::activateGestures(LLViewerInventoryItem::item_array_t& items)
+void LLGestureMgr::activateGestures(LLViewerInventoryItem::item_array_t& items)
{
// Load up the assets
S32 count = 0;
@@ -127,7 +166,7 @@ void LLGestureManager::activateGestures(LLViewerInventoryItem::item_array_t& ite
continue;
}
else
- { // Make gesture active and persistent through login sessions. -spatters 07-12-06
+ { // Make gesture active and persistent through login sessions. -Aura 07-12-06
activateGesture(item->getUUID());
}
@@ -206,38 +245,43 @@ struct LLLoadInfo
// If inform_server is true, will send a message upstream to update
// the user_gesture_active table.
-void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
+/**
+ * It will load a gesture from remote storage
+ */
+void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id,
const LLUUID& asset_id,
BOOL inform_server,
BOOL deactivate_similar)
{
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
if( !gAssetStorage )
{
- llwarns << "LLGestureManager::activateGestureWithAsset without valid gAssetStorage" << llendl;
+ LL_WARNS() << "LLGestureMgr::activateGestureWithAsset without valid gAssetStorage" << LL_ENDL;
return;
}
// If gesture is already active, nothing to do.
if (isGestureActive(item_id))
{
- llwarns << "Tried to loadGesture twice " << item_id << llendl;
+ LL_WARNS() << "Tried to loadGesture twice " << item_id << LL_ENDL;
return;
}
// if (asset_id.isNull())
// {
-// llwarns << "loadGesture() - gesture has no asset" << llendl;
+// LL_WARNS() << "loadGesture() - gesture has no asset" << LL_ENDL;
// return;
// }
// For now, put NULL into the item map. We'll build a gesture
// class object when the asset data arrives.
- mActive[item_id] = NULL;
+ mActive[base_item_id] = NULL;
// Copy the UUID
if (asset_id.notNull())
{
LLLoadInfo* info = new LLLoadInfo;
- info->mItemID = item_id;
+ info->mItemID = base_item_id;
info->mInformServer = inform_server;
info->mDeactivateSimilar = deactivate_similar;
@@ -255,12 +299,19 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
}
-void LLGestureManager::deactivateGesture(const LLUUID& item_id)
+void notify_update_label(const LLUUID& base_item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id);
+ LLGestureMgr::instance().notifyObservers();
+}
+
+void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
+{
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end())
{
- llwarns << "deactivateGesture for inactive gesture " << item_id << llendl;
+ LL_WARNS() << "deactivateGesture for inactive gesture " << item_id << LL_ENDL;
return;
}
@@ -277,7 +328,6 @@ void LLGestureManager::deactivateGesture(const LLUUID& item_id)
}
mActive.erase(it);
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
// Inform the database of this change
LLMessageSystem* msg = gMessageSystem;
@@ -293,13 +343,18 @@ void LLGestureManager::deactivateGesture(const LLUUID& item_id)
gAgent.sendReliableMessage();
- notifyObservers();
+ LLPointer<LLInventoryCallback> cb =
+ new LLBoostFuncInventoryCallback(no_op_inventory_func,
+ boost::bind(notify_update_label,base_item_id));
+
+ LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id, cb);
}
-void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id)
+void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id)
{
- std::vector<LLUUID> gest_item_ids;
+ const LLUUID& base_in_item_id = get_linked_uuid(in_item_id);
+ uuid_vec_t gest_item_ids;
// Deactivate all gestures that match
item_map_t::iterator it;
@@ -310,7 +365,7 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI
// Don't deactivate the gesture we are looking for duplicates of
// (for replaceGesture)
- if (!gest || item_id == in_item_id)
+ if (!gest || item_id == base_in_item_id)
{
// legal, can have null pointers in list
++it;
@@ -338,7 +393,7 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI
// Inform database of the change
LLMessageSystem* msg = gMessageSystem;
BOOL start_message = TRUE;
- std::vector<LLUUID>::const_iterator vit = gest_item_ids.begin();
+ uuid_vec_t::const_iterator vit = gest_item_ids.begin();
while (vit != gest_item_ids.end())
{
if (start_message)
@@ -383,16 +438,19 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI
}
-BOOL LLGestureManager::isGestureActive(const LLUUID& item_id)
+BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+ item_map_t::iterator it = mActive.find(base_item_id);
return (it != mActive.end());
}
-BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id)
+BOOL LLGestureMgr::isGesturePlaying(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end()) return FALSE;
LLMultiGesture* gesture = (*it).second;
@@ -401,21 +459,33 @@ BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id)
return gesture->mPlaying;
}
-void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id)
+BOOL LLGestureMgr::isGesturePlaying(LLMultiGesture* gesture)
{
- item_map_t::iterator it = mActive.find(item_id);
+ if(!gesture)
+ {
+ return FALSE;
+ }
+
+ return gesture->mPlaying;
+}
+
+void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id)
+{
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end())
{
- llwarns << "replaceGesture for inactive gesture " << item_id << llendl;
+ LL_WARNS() << "replaceGesture for inactive gesture " << base_item_id << LL_ENDL;
return;
}
LLMultiGesture* old_gesture = (*it).second;
stopGesture(old_gesture);
- mActive.erase(item_id);
+ mActive.erase(base_item_id);
- mActive[item_id] = new_gesture;
+ mActive[base_item_id] = new_gesture;
delete old_gesture;
old_gesture = NULL;
@@ -426,7 +496,7 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new
mDeactivateSimilarNames.clear();
LLLoadInfo* info = new LLLoadInfo;
- info->mItemID = item_id;
+ info->mItemID = base_item_id;
info->mInformServer = TRUE;
info->mDeactivateSimilar = FALSE;
@@ -441,21 +511,23 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new
notifyObservers();
}
-void LLGestureManager::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)
+void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)
{
- item_map_t::iterator it = LLGestureManager::instance().mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = LLGestureMgr::instance().mActive.find(base_item_id);
if (it == mActive.end())
{
- llwarns << "replaceGesture for inactive gesture " << item_id << llendl;
+ LL_WARNS() << "replaceGesture for inactive gesture " << base_item_id << LL_ENDL;
return;
}
// mActive owns this gesture pointer, so clean up memory.
LLMultiGesture* gesture = (*it).second;
- LLGestureManager::instance().replaceGesture(item_id, gesture, new_asset_id);
+ LLGestureMgr::instance().replaceGesture(base_item_id, gesture, new_asset_id);
}
-void LLGestureManager::playGesture(LLMultiGesture* gesture)
+void LLGestureMgr::playGesture(LLMultiGesture* gesture)
{
if (!gesture) return;
@@ -466,6 +538,66 @@ void LLGestureManager::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:
+ {
+ LL_WARNS() << "Unknown gesture step type: " << step->getType() << LL_ENDL;
+ }
+ }
+ }
+
// And get it going
stepGesture(gesture);
@@ -474,9 +606,11 @@ void LLGestureManager::playGesture(LLMultiGesture* gesture)
// Convenience function that looks up the item_id for you.
-void LLGestureManager::playGesture(const LLUUID& item_id)
+void LLGestureMgr::playGesture(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end()) return;
LLMultiGesture* gesture = (*it).second;
@@ -489,7 +623,7 @@ void LLGestureManager::playGesture(const LLUUID& item_id)
// Iterates through space delimited tokens in string, triggering any gestures found.
// Generates a revised string that has the found tokens replaced by their replacement strings
// and (as a minor side effect) has multiple spaces in a row replaced by single spaces.
-BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::string* revised_string)
+BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::string* revised_string)
{
std::string tokenized = utf8str;
@@ -582,7 +716,7 @@ BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::s
}
-BOOL LLGestureManager::triggerGesture(KEY key, MASK mask)
+BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask)
{
std::vector <LLMultiGesture *> matching;
item_map_t::iterator it;
@@ -616,7 +750,7 @@ BOOL LLGestureManager::triggerGesture(KEY key, MASK mask)
}
-S32 LLGestureManager::getPlayingCount() const
+S32 LLGestureMgr::getPlayingCount() const
{
return mPlaying.size();
}
@@ -630,7 +764,7 @@ struct IsGesturePlaying : public std::unary_function<LLMultiGesture*, bool>
}
};
-void LLGestureManager::update()
+void LLGestureMgr::update()
{
S32 i;
for (i = 0; i < (S32)mPlaying.size(); ++i)
@@ -673,14 +807,13 @@ void LLGestureManager::update()
// Run all steps until you're either done or hit a wait.
-void LLGestureManager::stepGesture(LLMultiGesture* gesture)
+void LLGestureMgr::stepGesture(LLMultiGesture* gesture)
{
if (!gesture)
{
return;
}
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if (!avatar) return;
+ if (!isAgentAvatarValid() || hasLoadingAssets(gesture)) return;
// Of the ones that started playing, have any stopped?
@@ -691,8 +824,8 @@ void LLGestureManager::stepGesture(LLMultiGesture* gesture)
{
// look in signaled animations (simulator's view of what is
// currently playing.
- LLVOAvatar::AnimIterator play_it = avatar->mSignaledAnimations.find(*gest_it);
- if (play_it != avatar->mSignaledAnimations.end())
+ LLVOAvatar::AnimIterator play_it = gAgentAvatarp->mSignaledAnimations.find(*gest_it);
+ if (play_it != gAgentAvatarp->mSignaledAnimations.end())
{
++gest_it;
}
@@ -710,8 +843,8 @@ void LLGestureManager::stepGesture(LLMultiGesture* gesture)
gest_it != gesture->mRequestedAnimIDs.end();
)
{
- LLVOAvatar::AnimIterator play_it = avatar->mSignaledAnimations.find(*gest_it);
- if (play_it != avatar->mSignaledAnimations.end())
+ LLVOAvatar::AnimIterator play_it = gAgentAvatarp->mSignaledAnimations.find(*gest_it);
+ if (play_it != gAgentAvatarp->mSignaledAnimations.end())
{
// Hooray, this animation has started playing!
// Copy into playing.
@@ -781,8 +914,8 @@ void LLGestureManager::stepGesture(LLMultiGesture* gesture)
else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS)
{
// we've waited too long for an animation
- llinfos << "Waited too long for animations to stop, continuing gesture."
- << llendl;
+ LL_INFOS() << "Waited too long for animations to stop, continuing gesture."
+ << LL_ENDL;
gesture->mWaitingAnimations = FALSE;
gesture->mCurrentStep++;
}
@@ -821,7 +954,7 @@ void LLGestureManager::stepGesture(LLMultiGesture* gesture)
}
-void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step)
+void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)
{
switch(step->getType())
{
@@ -872,7 +1005,8 @@ void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step)
const BOOL animate = FALSE;
- LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
+ (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->
+ sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
gesture->mCurrentStep++;
break;
@@ -908,7 +1042,7 @@ void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step)
// static
-void LLGestureManager::onLoadComplete(LLVFS *vfs,
+void LLGestureMgr::onLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status)
@@ -921,8 +1055,8 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
delete info;
info = NULL;
-
- LLGestureManager::instance().mLoadingCount--;
+ LLGestureMgr& self = LLGestureMgr::instance();
+ self.mLoadingCount--;
if (0 == status)
{
@@ -944,16 +1078,16 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
{
if (deactivate_similar)
{
- LLGestureManager::instance().deactivateSimilarGestures(gesture, item_id);
+ self.deactivateSimilarGestures(gesture, item_id);
// Display deactivation message if this was the last of the bunch.
- if (LLGestureManager::instance().mLoadingCount == 0
- && LLGestureManager::instance().mDeactivateSimilarNames.length() > 0)
+ if (self.mLoadingCount == 0
+ && self.mDeactivateSimilarNames.length() > 0)
{
// we're done with this set of deactivations
LLSD args;
- args["NAMES"] = LLGestureManager::instance().mDeactivateSimilarNames;
- LLNotifications::instance().add("DeactivatedGesturesTrigger", args);
+ args["NAMES"] = self.mDeactivateSimilarNames;
+ LLNotificationsUtil::add("DeactivatedGesturesTrigger", args);
}
}
@@ -965,9 +1099,10 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
else
{
// Watch this item and set gesture name when item exists in inventory
- LLGestureManager::instance().watchItem(item_id);
+ self.setFetchID(item_id);
+ self.startFetch();
}
- LLGestureManager::instance().mActive[item_id] = gesture;
+ self.mActive[item_id] = gesture;
// Everything has been successful. Add to the active list.
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
@@ -989,14 +1124,21 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
gAgent.sendReliableMessage();
}
+ callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id);
+
+ if(i_cb != self.mCallbackMap.end())
+ {
+ i_cb->second(gesture);
+ self.mCallbackMap.erase(i_cb);
+ }
- LLGestureManager::instance().notifyObservers();
+ self.notifyObservers();
}
else
{
- llwarns << "Unable to load gesture" << llendl;
+ LL_WARNS() << "Unable to load gesture" << LL_ENDL;
- LLGestureManager::instance().mActive.erase(item_id);
+ self.mActive.erase(item_id);
delete gesture;
gesture = NULL;
@@ -1004,8 +1146,6 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
}
else
{
- LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
-
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
@@ -1016,14 +1156,106 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
LLDelayedGestureError::gestureFailedToLoad( item_id );
}
- llwarns << "Problem loading gesture: " << status << llendl;
+ LL_WARNS() << "Problem loading gesture: " << status << LL_ENDL;
- LLGestureManager::instance().mActive.erase(item_id);
+ LLGestureMgr::instance().mActive.erase(item_id);
}
}
+// 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);
-void LLGestureManager::stopGesture(LLMultiGesture* gesture)
+ 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:
+ {
+ LL_WARNS() << "Unexpected asset type: " << type << LL_ENDL;
+
+ // 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:
+ {
+ LL_WARNS() << "Unknown gesture step type: " << step->getType() << LL_ENDL;
+ }
+ }
+ }
+
+ return false;
+}
+
+void LLGestureMgr::stopGesture(LLMultiGesture* gesture)
{
if (!gesture) return;
@@ -1063,9 +1295,11 @@ void LLGestureManager::stopGesture(LLMultiGesture* gesture)
}
-void LLGestureManager::stopGesture(const LLUUID& item_id)
+void LLGestureMgr::stopGesture(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end()) return;
LLMultiGesture* gesture = (*it).second;
@@ -1075,12 +1309,12 @@ void LLGestureManager::stopGesture(const LLUUID& item_id)
}
-void LLGestureManager::addObserver(LLGestureManagerObserver* observer)
+void LLGestureMgr::addObserver(LLGestureManagerObserver* observer)
{
mObservers.push_back(observer);
}
-void LLGestureManager::removeObserver(LLGestureManagerObserver* observer)
+void LLGestureMgr::removeObserver(LLGestureManagerObserver* observer)
{
std::vector<LLGestureManagerObserver*>::iterator it;
it = std::find(mObservers.begin(), mObservers.end(), observer);
@@ -1093,24 +1327,24 @@ void LLGestureManager::removeObserver(LLGestureManagerObserver* observer)
// Call this method when it's time to update everyone on a new state.
// Copy the list because an observer could respond by removing itself
// from the list.
-void LLGestureManager::notifyObservers()
+void LLGestureMgr::notifyObservers()
{
- lldebugs << "LLGestureManager::notifyObservers" << llendl;
-
- std::vector<LLGestureManagerObserver*> observers = mObservers;
+ LL_DEBUGS() << "LLGestureMgr::notifyObservers" << LL_ENDL;
- std::vector<LLGestureManagerObserver*>::iterator it;
- for (it = observers.begin(); it != observers.end(); ++it)
+ for(std::vector<LLGestureManagerObserver*>::iterator iter = mObservers.begin();
+ iter != mObservers.end();
+ ++iter)
{
- LLGestureManagerObserver* observer = *it;
+ LLGestureManagerObserver* observer = (*iter);
observer->changed();
}
}
-BOOL LLGestureManager::matchPrefix(const std::string& in_str, std::string* out_str)
+BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str)
{
S32 in_len = in_str.length();
+ //return whole trigger, if received text equals to it
item_map_t::iterator it;
for (it = mActive.begin(); it != mActive.end(); ++it)
{
@@ -1118,7 +1352,24 @@ BOOL LLGestureManager::matchPrefix(const std::string& in_str, std::string* out_s
if (gesture)
{
const std::string& trigger = gesture->getTrigger();
-
+ if (!LLStringUtil::compareInsensitive(in_str, trigger))
+ {
+ *out_str = trigger;
+ return TRUE;
+ }
+ }
+ }
+
+ //return common chars, if more than one trigger matches the prefix
+ std::string rest_of_match = "";
+ std::string buf = "";
+ for (it = mActive.begin(); it != mActive.end(); ++it)
+ {
+ LLMultiGesture* gesture = (*it).second;
+ if (gesture)
+ {
+ const std::string& trigger = gesture->getTrigger();
+
if (in_len > (S32)trigger.length())
{
// too short, bail out
@@ -1129,16 +1380,54 @@ BOOL LLGestureManager::matchPrefix(const std::string& in_str, std::string* out_s
LLStringUtil::truncate(trigger_trunc, in_len);
if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc))
{
- *out_str = trigger;
- return TRUE;
+ if (rest_of_match.compare("") == 0)
+ {
+ rest_of_match = trigger.substr(in_str.size());
+ }
+ std::string cur_rest_of_match = trigger.substr(in_str.size());
+ buf = "";
+ S32 i=0;
+
+ while (i<rest_of_match.length() && i<cur_rest_of_match.length())
+ {
+ if (rest_of_match[i]==cur_rest_of_match[i])
+ {
+ buf.push_back(rest_of_match[i]);
+ }
+ else
+ {
+ if(i==0)
+ {
+ rest_of_match = "";
+ }
+ break;
+ }
+ i++;
+ }
+ if (rest_of_match.compare("") == 0)
+ {
+ return TRUE;
+ }
+ if (buf.compare("") != 0)
+ {
+ rest_of_match = buf;
+ }
+
}
}
}
+
+ if (rest_of_match.compare("") != 0)
+ {
+ *out_str = in_str+rest_of_match;
+ return TRUE;
+ }
+
return FALSE;
}
-void LLGestureManager::getItemIDs(std::vector<LLUUID>* ids)
+void LLGestureMgr::getItemIDs(uuid_vec_t* ids)
{
item_map_t::const_iterator it;
for (it = mActive.begin(); it != mActive.end(); ++it)
@@ -1147,8 +1436,9 @@ void LLGestureManager::getItemIDs(std::vector<LLUUID>* ids)
}
}
-void LLGestureManager::done()
+void LLGestureMgr::done()
{
+ bool notify = false;
for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
{
if(it->second && it->second->mName.empty())
@@ -1157,8 +1447,24 @@ void LLGestureManager::done()
if(item)
{
it->second->mName = item->getName();
+ notify = true;
}
}
}
- notifyObservers();
+ if(notify)
+ {
+ notifyObservers();
+ }
}
+
+// static
+const LLUUID& get_linked_uuid(const LLUUID &item_id)
+{
+ LLViewerInventoryItem* item = gInventory.getItem(item_id);
+ if (item && item->getIsLinkType())
+ {
+ return item->getLinkedUUID();
+ }
+ return item_id;
+}
+