00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llgesturemgr.h"
00035
00036
00037 #include <functional>
00038 #include <algorithm>
00039 #include <boost/tokenizer.hpp>
00040
00041
00042 #include "lldatapacker.h"
00043 #include "llinventory.h"
00044 #include "llmultigesture.h"
00045 #include "llstl.h"
00046 #include "llstring.h"
00047 #include "llvfile.h"
00048 #include "message.h"
00049
00050
00051 #include "llagent.h"
00052 #include "llchatbar.h"
00053 #include "llinventorymodel.h"
00054 #include "llnotify.h"
00055 #include "llviewermessage.h"
00056 #include "llvoavatar.h"
00057 #include "llviewerstats.h"
00058 #include "viewer.h"
00059
00060 LLGestureManager gGestureManager;
00061
00062
00063 const F32 MAX_WAIT_ANIM_SECS = 30.f;
00064
00065
00066
00067
00068 LLGestureManager::LLGestureManager()
00069 : mValid(FALSE),
00070 mPlaying(),
00071 mActive(),
00072 mLoadingCount(0)
00073 { }
00074
00075
00076
00077 LLGestureManager::~LLGestureManager()
00078 {
00079 item_map_t::iterator it;
00080 for (it = mActive.begin(); it != mActive.end(); ++it)
00081 {
00082 LLMultiGesture* gesture = (*it).second;
00083
00084 delete gesture;
00085 gesture = NULL;
00086 }
00087 }
00088
00089
00090 void LLGestureManager::init()
00091 {
00092
00093 }
00094
00095
00096
00097
00098 void LLGestureManager::activateGesture(const LLUUID& item_id)
00099 {
00100 LLViewerInventoryItem* item = gInventory.getItem(item_id);
00101 if (!item) return;
00102
00103 LLUUID asset_id = item->getAssetUUID();
00104
00105 mLoadingCount = 1;
00106 mDeactivateSimilarNames.clear();
00107
00108 const BOOL inform_server = TRUE;
00109 const BOOL deactivate_similar = FALSE;
00110 activateGestureWithAsset(item_id, asset_id, inform_server, deactivate_similar);
00111 }
00112
00113
00114 void LLGestureManager::activateGestures(LLViewerInventoryItem::item_array_t& items)
00115 {
00116
00117 S32 count = 0;
00118 LLViewerInventoryItem::item_array_t::const_iterator it;
00119 for (it = items.begin(); it != items.end(); ++it)
00120 {
00121 LLViewerInventoryItem* item = *it;
00122
00123 if (isGestureActive(item->getUUID()))
00124 {
00125 continue;
00126 }
00127 else
00128 {
00129 activateGesture(item->getUUID());
00130 }
00131
00132 count++;
00133 }
00134
00135 mLoadingCount = count;
00136 mDeactivateSimilarNames.clear();
00137
00138 for (it = items.begin(); it != items.end(); ++it)
00139 {
00140 LLViewerInventoryItem* item = *it;
00141
00142 if (isGestureActive(item->getUUID()))
00143 {
00144 continue;
00145 }
00146
00147
00148 const BOOL no_inform_server = FALSE;
00149 const BOOL deactivate_similar = TRUE;
00150 activateGestureWithAsset(item->getUUID(), item->getAssetUUID(),
00151 no_inform_server,
00152 deactivate_similar);
00153 }
00154
00155
00156 LLMessageSystem* msg = gMessageSystem;
00157
00158 BOOL start_message = TRUE;
00159
00160 for (it = items.begin(); it != items.end(); ++it)
00161 {
00162 LLViewerInventoryItem* item = *it;
00163
00164 if (isGestureActive(item->getUUID()))
00165 {
00166 continue;
00167 }
00168
00169 if (start_message)
00170 {
00171 msg->newMessage("ActivateGestures");
00172 msg->nextBlock("AgentData");
00173 msg->addUUID("AgentID", gAgent.getID());
00174 msg->addUUID("SessionID", gAgent.getSessionID());
00175 msg->addU32("Flags", 0x0);
00176 start_message = FALSE;
00177 }
00178
00179 msg->nextBlock("Data");
00180 msg->addUUID("ItemID", item->getUUID());
00181 msg->addUUID("AssetID", item->getAssetUUID());
00182 msg->addU32("GestureFlags", 0x0);
00183
00184 if (msg->getCurrentSendTotal() > MTUBYTES)
00185 {
00186 gAgent.sendReliableMessage();
00187 start_message = TRUE;
00188 }
00189 }
00190
00191 if (!start_message)
00192 {
00193 gAgent.sendReliableMessage();
00194 }
00195 }
00196
00197
00198 struct LLLoadInfo
00199 {
00200 LLUUID mItemID;
00201 BOOL mInformServer;
00202 BOOL mDeactivateSimilar;
00203 };
00204
00205
00206
00207 void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
00208 const LLUUID& asset_id,
00209 BOOL inform_server,
00210 BOOL deactivate_similar)
00211 {
00212 if( !gAssetStorage )
00213 {
00214 llwarns << "LLGestureManager::activateGestureWithAsset without valid gAssetStorage" << llendl;
00215 return;
00216 }
00217
00218 if (isGestureActive(item_id))
00219 {
00220 llwarns << "Tried to loadGesture twice " << item_id << llendl;
00221 return;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 mActive[item_id] = NULL;
00233
00234
00235 if (asset_id.notNull())
00236 {
00237 LLLoadInfo* info = new LLLoadInfo;
00238 info->mItemID = item_id;
00239 info->mInformServer = inform_server;
00240 info->mDeactivateSimilar = deactivate_similar;
00241
00242 const BOOL high_priority = TRUE;
00243 gAssetStorage->getAssetData(asset_id,
00244 LLAssetType::AT_GESTURE,
00245 onLoadComplete,
00246 (void*)info,
00247 high_priority);
00248 }
00249 else
00250 {
00251 notifyObservers();
00252 }
00253 }
00254
00255
00256 void LLGestureManager::deactivateGesture(const LLUUID& item_id)
00257 {
00258 item_map_t::iterator it = mActive.find(item_id);
00259 if (it == mActive.end())
00260 {
00261 llwarns << "deactivateGesture for inactive gesture " << item_id << llendl;
00262 return;
00263 }
00264
00265
00266 LLMultiGesture* gesture = (*it).second;
00267
00268
00269 if (gesture)
00270 {
00271 stopGesture(gesture);
00272
00273 delete gesture;
00274 gesture = NULL;
00275 }
00276
00277 mActive.erase(it);
00278 gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
00279
00280
00281 LLMessageSystem* msg = gMessageSystem;
00282 msg->newMessage("DeactivateGestures");
00283 msg->nextBlock("AgentData");
00284 msg->addUUID("AgentID", gAgent.getID());
00285 msg->addUUID("SessionID", gAgent.getSessionID());
00286 msg->addU32("Flags", 0x0);
00287
00288 msg->nextBlock("Data");
00289 msg->addUUID("ItemID", item_id);
00290 msg->addU32("GestureFlags", 0x0);
00291
00292 gAgent.sendReliableMessage();
00293
00294 notifyObservers();
00295 }
00296
00297
00298 void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id)
00299 {
00300 std::vector<LLUUID> gest_item_ids;
00301
00302
00303 item_map_t::iterator it;
00304 for (it = mActive.begin(); it != mActive.end(); )
00305 {
00306 const LLUUID& item_id = (*it).first;
00307 LLMultiGesture* gest = (*it).second;
00308
00309
00310
00311 if (!gest || item_id == in_item_id)
00312 {
00313
00314 ++it;
00315 }
00316 else if ((!gest->mTrigger.empty() && gest->mTrigger == in->mTrigger)
00317 || (gest->mKey != KEY_NONE && gest->mKey == in->mKey && gest->mMask == in->mMask))
00318 {
00319 gest_item_ids.push_back(item_id);
00320
00321 stopGesture(gest);
00322
00323 delete gest;
00324 gest = NULL;
00325
00326 mActive.erase(it++);
00327 gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
00328
00329 }
00330 else
00331 {
00332 ++it;
00333 }
00334 }
00335
00336
00337 LLMessageSystem* msg = gMessageSystem;
00338 BOOL start_message = TRUE;
00339 std::vector<LLUUID>::const_iterator vit = gest_item_ids.begin();
00340 while (vit != gest_item_ids.end())
00341 {
00342 if (start_message)
00343 {
00344 msg->newMessage("DeactivateGestures");
00345 msg->nextBlock("AgentData");
00346 msg->addUUID("AgentID", gAgent.getID());
00347 msg->addUUID("SessionID", gAgent.getSessionID());
00348 msg->addU32("Flags", 0x0);
00349 start_message = FALSE;
00350 }
00351
00352 msg->nextBlock("Data");
00353 msg->addUUID("ItemID", *vit);
00354 msg->addU32("GestureFlags", 0x0);
00355
00356 if (msg->getCurrentSendTotal() > MTUBYTES)
00357 {
00358 gAgent.sendReliableMessage();
00359 start_message = TRUE;
00360 }
00361
00362 ++vit;
00363 }
00364
00365 if (!start_message)
00366 {
00367 gAgent.sendReliableMessage();
00368 }
00369
00370
00371 for (vit = gest_item_ids.begin(); vit != gest_item_ids.end(); ++vit)
00372 {
00373 LLViewerInventoryItem* item = gInventory.getItem(*vit);
00374 if (!item) continue;
00375
00376 mDeactivateSimilarNames.append(item->getName());
00377 mDeactivateSimilarNames.append("\n");
00378 }
00379
00380 notifyObservers();
00381 }
00382
00383
00384 BOOL LLGestureManager::isGestureActive(const LLUUID& item_id)
00385 {
00386 item_map_t::iterator it = mActive.find(item_id);
00387 return (it != mActive.end());
00388 }
00389
00390
00391 BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id)
00392 {
00393 item_map_t::iterator it = mActive.find(item_id);
00394 if (it == mActive.end()) return FALSE;
00395
00396 LLMultiGesture* gesture = (*it).second;
00397 if (!gesture) return FALSE;
00398
00399 return gesture->mPlaying;
00400 }
00401
00402 void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id)
00403 {
00404 item_map_t::iterator it = mActive.find(item_id);
00405 if (it == mActive.end())
00406 {
00407 llwarns << "replaceGesture for inactive gesture " << item_id << llendl;
00408 return;
00409 }
00410
00411 LLMultiGesture* old_gesture = (*it).second;
00412 stopGesture(old_gesture);
00413
00414 mActive.erase(item_id);
00415
00416 mActive[item_id] = new_gesture;
00417
00418 delete old_gesture;
00419 old_gesture = NULL;
00420
00421 if (asset_id.notNull())
00422 {
00423 mLoadingCount = 1;
00424 mDeactivateSimilarNames.clear();
00425
00426 LLLoadInfo* info = new LLLoadInfo;
00427 info->mItemID = item_id;
00428 info->mInformServer = TRUE;
00429 info->mDeactivateSimilar = FALSE;
00430
00431 const BOOL high_priority = TRUE;
00432 gAssetStorage->getAssetData(asset_id,
00433 LLAssetType::AT_GESTURE,
00434 onLoadComplete,
00435 (void*)info,
00436 high_priority);
00437 }
00438
00439 notifyObservers();
00440 }
00441
00442 void LLGestureManager::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)
00443 {
00444 item_map_t::iterator it = gGestureManager.mActive.find(item_id);
00445 if (it == mActive.end())
00446 {
00447 llwarns << "replaceGesture for inactive gesture " << item_id << llendl;
00448 return;
00449 }
00450
00451
00452 LLMultiGesture* gesture = (*it).second;
00453 gGestureManager.replaceGesture(item_id, gesture, new_asset_id);
00454 }
00455
00456 void LLGestureManager::playGesture(LLMultiGesture* gesture)
00457 {
00458 if (!gesture) return;
00459
00460
00461 gesture->mCurrentStep = 0;
00462
00463
00464 gesture->mPlaying = TRUE;
00465 mPlaying.push_back(gesture);
00466
00467
00468 stepGesture(gesture);
00469
00470 notifyObservers();
00471 }
00472
00473
00474
00475 void LLGestureManager::playGesture(const LLUUID& item_id)
00476 {
00477 item_map_t::iterator it = mActive.find(item_id);
00478 if (it == mActive.end()) return;
00479
00480 LLMultiGesture* gesture = (*it).second;
00481 if (!gesture) return;
00482
00483 playGesture(gesture);
00484 }
00485
00486
00487
00488
00489
00490 BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::string* revised_string)
00491 {
00492 LLString tokenized = LLString(utf8str.c_str());
00493
00494 BOOL found_gestures = FALSE;
00495 BOOL first_token = TRUE;
00496
00497 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00498 boost::char_separator<char> sep(" ");
00499 tokenizer tokens(tokenized, sep);
00500 tokenizer::iterator token_iter;
00501
00502 for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
00503 {
00504 const char* cur_token = token_iter->c_str();
00505 LLMultiGesture* gesture = NULL;
00506
00507
00508 if( !found_gestures )
00509 {
00510 LLString cur_token_lower = cur_token;
00511 LLString::toLower(cur_token_lower);
00512
00513
00514 std::vector <LLMultiGesture *> matching;
00515 item_map_t::iterator it;
00516 for (it = mActive.begin(); it != mActive.end(); ++it)
00517 {
00518 gesture = (*it).second;
00519
00520
00521 if (!gesture) continue;
00522
00523 if (!stricmp(gesture->mTrigger.c_str(), cur_token_lower.c_str()))
00524 {
00525 matching.push_back(gesture);
00526 }
00527
00528 gesture = NULL;
00529 }
00530
00531
00532 if (matching.size() > 0)
00533 {
00534
00535 {
00536 S32 random = ll_rand(matching.size());
00537
00538 gesture = matching[random];
00539
00540 playGesture(gesture);
00541
00542 if (!gesture->mReplaceText.empty())
00543 {
00544 if( !first_token )
00545 {
00546 if (revised_string)
00547 revised_string->append( " " );
00548 }
00549
00550
00551 LLString output = gesture->mReplaceText.c_str();
00552 LLString output_lower = output;
00553 LLString::toLower(output_lower);
00554 if( cur_token_lower == output_lower )
00555 {
00556 if (revised_string)
00557 revised_string->append( cur_token );
00558 }
00559 else
00560 {
00561 if (revised_string)
00562 revised_string->append( output );
00563 }
00564 }
00565 found_gestures = TRUE;
00566 }
00567 }
00568 }
00569
00570 if(!gesture)
00571 {
00572
00573 if( !first_token )
00574 {
00575 if (revised_string)
00576 revised_string->append( " " );
00577 }
00578 if (revised_string)
00579 revised_string->append( cur_token );
00580 }
00581
00582 first_token = FALSE;
00583 gesture = NULL;
00584 }
00585 return found_gestures;
00586 }
00587
00588
00589 BOOL LLGestureManager::triggerGesture(KEY key, MASK mask)
00590 {
00591 std::vector <LLMultiGesture *> matching;
00592 item_map_t::iterator it;
00593
00594
00595 for (it = mActive.begin(); it != mActive.end(); ++it)
00596 {
00597 LLMultiGesture* gesture = (*it).second;
00598
00599
00600 if (!gesture) continue;
00601
00602 if (gesture->mKey == key
00603 && gesture->mMask == mask)
00604 {
00605 matching.push_back(gesture);
00606 }
00607 }
00608
00609
00610 if (matching.size() > 0)
00611 {
00612 U32 random = ll_rand(matching.size());
00613
00614 LLMultiGesture* gesture = matching[random];
00615
00616 playGesture(gesture);
00617 return TRUE;
00618 }
00619 return FALSE;
00620 }
00621
00622
00623 S32 LLGestureManager::getPlayingCount() const
00624 {
00625 return mPlaying.size();
00626 }
00627
00628
00629 struct IsGesturePlaying : public std::unary_function<LLMultiGesture*, bool>
00630 {
00631 bool operator()(const LLMultiGesture* gesture) const
00632 {
00633 return gesture->mPlaying ? true : false;
00634 }
00635 };
00636
00637 void LLGestureManager::update()
00638 {
00639 S32 i;
00640 for (i = 0; i < (S32)mPlaying.size(); ++i)
00641 {
00642 stepGesture(mPlaying[i]);
00643 }
00644
00645
00646
00647 std::vector<LLMultiGesture*>::iterator new_end;
00648 new_end = std::partition(mPlaying.begin(),
00649 mPlaying.end(),
00650 IsGesturePlaying());
00651
00652
00653 if (new_end != mPlaying.end())
00654 {
00655
00656 std::vector<LLMultiGesture*>::iterator it;
00657 for (it = new_end; it != mPlaying.end(); ++it)
00658 {
00659 LLMultiGesture* gesture = *it;
00660
00661 if (gesture->mDoneCallback)
00662 {
00663 gesture->mDoneCallback(gesture, gesture->mCallbackData);
00664
00665
00666
00667 gesture = NULL;
00668 }
00669 }
00670
00671
00672 mPlaying.erase(new_end, mPlaying.end());
00673
00674 notifyObservers();
00675 }
00676 }
00677
00678
00679
00680 void LLGestureManager::stepGesture(LLMultiGesture* gesture)
00681 {
00682 if (!gesture)
00683 {
00684 return;
00685 }
00686 LLVOAvatar* avatar = gAgent.getAvatarObject();
00687 if (!avatar) return;
00688
00689
00690
00691 std::set<LLUUID>::iterator gest_it;
00692 for (gest_it = gesture->mPlayingAnimIDs.begin();
00693 gest_it != gesture->mPlayingAnimIDs.end();
00694 )
00695 {
00696
00697
00698 LLVOAvatar::AnimIterator play_it = avatar->mSignaledAnimations.find(*gest_it);
00699 if (play_it != avatar->mSignaledAnimations.end())
00700 {
00701 ++gest_it;
00702 }
00703 else
00704 {
00705
00706
00707 gesture->mPlayingAnimIDs.erase(gest_it++);
00708 }
00709 }
00710
00711
00712
00713 for (gest_it = gesture->mRequestedAnimIDs.begin();
00714 gest_it != gesture->mRequestedAnimIDs.end();
00715 )
00716 {
00717 LLVOAvatar::AnimIterator play_it = avatar->mSignaledAnimations.find(*gest_it);
00718 if (play_it != avatar->mSignaledAnimations.end())
00719 {
00720
00721
00722 gesture->mPlayingAnimIDs.insert(*gest_it);
00723 gesture->mRequestedAnimIDs.erase(gest_it++);
00724 }
00725 else
00726 {
00727
00728 ++gest_it;
00729 }
00730 }
00731
00732
00733 BOOL waiting = FALSE;
00734 while (!waiting && gesture->mPlaying)
00735 {
00736
00737
00738 LLGestureStep* step = NULL;
00739 if (gesture->mCurrentStep < (S32)gesture->mSteps.size())
00740 {
00741 step = gesture->mSteps[gesture->mCurrentStep];
00742 llassert(step != NULL);
00743 }
00744 else
00745 {
00746
00747 gesture->mWaitingAtEnd = TRUE;
00748 }
00749
00750
00751
00752
00753
00754 if (gesture->mWaitingAtEnd)
00755 {
00756
00757
00758 if ((gesture->mRequestedAnimIDs.empty()
00759 && gesture->mPlayingAnimIDs.empty()))
00760 {
00761
00762 gesture->mWaitingAtEnd = FALSE;
00763 gesture->mPlaying = FALSE;
00764 }
00765 else
00766 {
00767 waiting = TRUE;
00768 }
00769 continue;
00770 }
00771
00772
00773
00774 if (gesture->mWaitingAnimations)
00775 {
00776
00777
00778 if ((gesture->mRequestedAnimIDs.empty()
00779 && gesture->mPlayingAnimIDs.empty()))
00780 {
00781
00782 gesture->mWaitingAnimations = FALSE;
00783 gesture->mCurrentStep++;
00784 }
00785 else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS)
00786 {
00787
00788 llinfos << "Waited too long for animations to stop, continuing gesture."
00789 << llendl;
00790 gesture->mWaitingAnimations = FALSE;
00791 gesture->mCurrentStep++;
00792 }
00793 else
00794 {
00795 waiting = TRUE;
00796 }
00797 continue;
00798 }
00799
00800
00801
00802 if (gesture->mWaitingTimer)
00803 {
00804
00805 LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
00806
00807 F32 elapsed = gesture->mWaitTimer.getElapsedTimeF32();
00808 if (elapsed > wait_step->mWaitSeconds)
00809 {
00810
00811 gesture->mWaitingTimer = FALSE;
00812 gesture->mCurrentStep++;
00813 }
00814 else
00815 {
00816
00817 waiting = TRUE;
00818 }
00819 continue;
00820 }
00821
00822
00823 runStep(gesture, step);
00824 }
00825 }
00826
00827
00828 void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step)
00829 {
00830 switch(step->getType())
00831 {
00832 case STEP_ANIMATION:
00833 {
00834 LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
00835 if (anim_step->mAnimAssetID.isNull())
00836 {
00837 gesture->mCurrentStep++;
00838 }
00839
00840 if (anim_step->mFlags & ANIM_FLAG_STOP)
00841 {
00842 gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_STOP);
00843
00844 std::set<LLUUID>::iterator set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID);
00845 if (set_it != gesture->mRequestedAnimIDs.end())
00846 {
00847 gesture->mRequestedAnimIDs.erase(set_it);
00848 }
00849 }
00850 else
00851 {
00852 gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_START);
00853
00854
00855
00856 gesture->mRequestedAnimIDs.insert(anim_step->mAnimAssetID);
00857 }
00858 gesture->mCurrentStep++;
00859 break;
00860 }
00861 case STEP_SOUND:
00862 {
00863 LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
00864 const LLUUID& sound_id = sound_step->mSoundAssetID;
00865 const F32 volume = 1.f;
00866 send_sound_trigger(sound_id, volume);
00867 gesture->mCurrentStep++;
00868 break;
00869 }
00870 case STEP_CHAT:
00871 {
00872 LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
00873 std::string chat_text = chat_step->mChatText;
00874
00875
00876 const BOOL animate = FALSE;
00877
00878 gChatBar->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
00879 gesture->mCurrentStep++;
00880 break;
00881 }
00882 case STEP_WAIT:
00883 {
00884 LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
00885 if (wait_step->mFlags & WAIT_FLAG_TIME)
00886 {
00887 gesture->mWaitingTimer = TRUE;
00888 gesture->mWaitTimer.reset();
00889 }
00890 else if (wait_step->mFlags & WAIT_FLAG_ALL_ANIM)
00891 {
00892 gesture->mWaitingAnimations = TRUE;
00893
00894
00895 gesture->mWaitTimer.reset();
00896 }
00897 else
00898 {
00899 gesture->mCurrentStep++;
00900 }
00901
00902 break;
00903 }
00904 default:
00905 {
00906 break;
00907 }
00908 }
00909 }
00910
00911
00912
00913 void LLGestureManager::onLoadComplete(LLVFS *vfs,
00914 const LLUUID& asset_uuid,
00915 LLAssetType::EType type,
00916 void* user_data, S32 status, LLExtStat ext_status)
00917 {
00918 LLLoadInfo* info = (LLLoadInfo*)user_data;
00919
00920 LLUUID item_id = info->mItemID;
00921 BOOL inform_server = info->mInformServer;
00922 BOOL deactivate_similar = info->mDeactivateSimilar;
00923
00924 delete info;
00925 info = NULL;
00926
00927 gGestureManager.mLoadingCount--;
00928
00929 if (0 == status)
00930 {
00931 LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
00932 S32 size = file.getSize();
00933
00934 char* buffer = new char[size+1];
00935 if (buffer == NULL)
00936 {
00937 llerrs << "Memory Allocation Failed" << llendl;
00938 return;
00939 }
00940
00941 file.read((U8*)buffer, size);
00942
00943 buffer[size] = '\0';
00944
00945 LLMultiGesture* gesture = new LLMultiGesture();
00946
00947 LLDataPackerAsciiBuffer dp(buffer, size+1);
00948 BOOL ok = gesture->deserialize(dp);
00949
00950 if (ok)
00951 {
00952 if (deactivate_similar)
00953 {
00954 gGestureManager.deactivateSimilarGestures(gesture, item_id);
00955
00956
00957 if (gGestureManager.mLoadingCount == 0
00958 && gGestureManager.mDeactivateSimilarNames.length() > 0)
00959 {
00960
00961 LLString::format_map_t args;
00962 args["[NAMES]"] = gGestureManager.mDeactivateSimilarNames;
00963 LLNotifyBox::showXml("DeactivatedGesturesTrigger", args);
00964 }
00965 }
00966
00967
00968 gGestureManager.mActive[item_id] = gesture;
00969 gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
00970 if (inform_server)
00971 {
00972
00973 LLMessageSystem* msg = gMessageSystem;
00974 msg->newMessage("ActivateGestures");
00975 msg->nextBlock("AgentData");
00976 msg->addUUID("AgentID", gAgent.getID());
00977 msg->addUUID("SessionID", gAgent.getSessionID());
00978 msg->addU32("Flags", 0x0);
00979
00980 msg->nextBlock("Data");
00981 msg->addUUID("ItemID", item_id);
00982 msg->addUUID("AssetID", asset_uuid);
00983 msg->addU32("GestureFlags", 0x0);
00984
00985 gAgent.sendReliableMessage();
00986 }
00987
00988 gGestureManager.notifyObservers();
00989 }
00990 else
00991 {
00992 llwarns << "Unable to load gesture" << llendl;
00993
00994 gGestureManager.mActive.erase(item_id);
00995
00996 delete gesture;
00997 gesture = NULL;
00998 }
00999
01000 delete [] buffer;
01001 buffer = NULL;
01002 }
01003 else
01004 {
01005 if( gViewerStats )
01006 {
01007 gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
01008 }
01009
01010 if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
01011 LL_ERR_FILE_EMPTY == status)
01012 {
01013 LLNotifyBox::showXml("GestureMissing");
01014 }
01015 else
01016 {
01017 LLNotifyBox::showXml("UnableToLoadGesture");
01018 }
01019
01020 llwarns << "Problem loading gesture: " << status << llendl;
01021
01022 gGestureManager.mActive.erase(item_id);
01023 }
01024 }
01025
01026
01027 void LLGestureManager::stopGesture(LLMultiGesture* gesture)
01028 {
01029 if (!gesture) return;
01030
01031
01032 std::set<LLUUID>::const_iterator set_it;
01033 for (set_it = gesture->mRequestedAnimIDs.begin(); set_it != gesture->mRequestedAnimIDs.end(); ++set_it)
01034 {
01035 const LLUUID& anim_id = *set_it;
01036 gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP);
01037 }
01038 for (set_it = gesture->mPlayingAnimIDs.begin(); set_it != gesture->mPlayingAnimIDs.end(); ++set_it)
01039 {
01040 const LLUUID& anim_id = *set_it;
01041 gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP);
01042 }
01043
01044 std::vector<LLMultiGesture*>::iterator it;
01045 it = std::find(mPlaying.begin(), mPlaying.end(), gesture);
01046 while (it != mPlaying.end())
01047 {
01048 mPlaying.erase(it);
01049 it = std::find(mPlaying.begin(), mPlaying.end(), gesture);
01050 }
01051
01052 gesture->reset();
01053
01054 if (gesture->mDoneCallback)
01055 {
01056 gesture->mDoneCallback(gesture, gesture->mCallbackData);
01057
01058
01059
01060 gesture = NULL;
01061 }
01062
01063 notifyObservers();
01064 }
01065
01066
01067 void LLGestureManager::stopGesture(const LLUUID& item_id)
01068 {
01069 item_map_t::iterator it = mActive.find(item_id);
01070 if (it == mActive.end()) return;
01071
01072 LLMultiGesture* gesture = (*it).second;
01073 if (!gesture) return;
01074
01075 stopGesture(gesture);
01076 }
01077
01078
01079 void LLGestureManager::addObserver(LLGestureManagerObserver* observer)
01080 {
01081 mObservers.push_back(observer);
01082 }
01083
01084 void LLGestureManager::removeObserver(LLGestureManagerObserver* observer)
01085 {
01086 std::vector<LLGestureManagerObserver*>::iterator it;
01087 it = std::find(mObservers.begin(), mObservers.end(), observer);
01088 if (it != mObservers.end())
01089 {
01090 mObservers.erase(it);
01091 }
01092 }
01093
01094
01095
01096
01097 void LLGestureManager::notifyObservers()
01098 {
01099 lldebugs << "LLGestureManager::notifyObservers" << llendl;
01100
01101 std::vector<LLGestureManagerObserver*> observers = mObservers;
01102
01103 std::vector<LLGestureManagerObserver*>::iterator it;
01104 for (it = observers.begin(); it != observers.end(); ++it)
01105 {
01106 LLGestureManagerObserver* observer = *it;
01107 observer->changed();
01108 }
01109 }
01110
01111 BOOL LLGestureManager::matchPrefix(const std::string& in_str, std::string* out_str)
01112 {
01113 S32 in_len = in_str.length();
01114
01115 item_map_t::iterator it;
01116 for (it = mActive.begin(); it != mActive.end(); ++it)
01117 {
01118 LLMultiGesture* gesture = (*it).second;
01119 if (gesture)
01120 {
01121 const std::string& trigger = gesture->getTrigger();
01122
01123 if (in_len > (S32)trigger.length())
01124 {
01125
01126 continue;
01127 }
01128
01129 LLString trigger_trunc = trigger;
01130 LLString::truncate(trigger_trunc, in_len);
01131 if (!LLString::compareInsensitive(in_str.c_str(), trigger_trunc.c_str()))
01132 {
01133 *out_str = trigger;
01134 return TRUE;
01135 }
01136 }
01137 }
01138 return FALSE;
01139 }
01140
01141
01142 void LLGestureManager::getItemIDs(std::vector<LLUUID>* ids)
01143 {
01144 item_map_t::const_iterator it;
01145 for (it = mActive.begin(); it != mActive.end(); ++it)
01146 {
01147 ids->push_back(it->first);
01148 }
01149 }