00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include <algorithm>
00035
00036 #include "llpreviewgesture.h"
00037
00038
00039 #include "lldatapacker.h"
00040 #include "lldarray.h"
00041 #include "llstring.h"
00042 #include "lldir.h"
00043 #include "llmultigesture.h"
00044 #include "llvfile.h"
00045
00046
00047 #include "llagent.h"
00048 #include "llassetuploadresponders.h"
00049 #include "llbutton.h"
00050 #include "llcheckboxctrl.h"
00051 #include "llcombobox.h"
00052 #include "lldelayedgestureerror.h"
00053 #include "llfloatergesture.h"
00054 #include "llgesturemgr.h"
00055 #include "llinventorymodel.h"
00056 #include "llkeyboard.h"
00057 #include "lllineeditor.h"
00058 #include "llnotify.h"
00059 #include "llradiogroup.h"
00060 #include "llscrolllistctrl.h"
00061 #include "lltextbox.h"
00062 #include "lluictrlfactory.h"
00063 #include "llviewerinventory.h"
00064 #include "llviewerobject.h"
00065 #include "llviewerobjectlist.h"
00066 #include "llviewerregion.h"
00067 #include "llviewerstats.h"
00068 #include "llviewerwindow.h"
00069 #include "llappviewer.h"
00070 #include "llanimstatelabels.h"
00071 #include "llresmgr.h"
00072
00073
00074
00075 const char NONE_LABEL[] = "---";
00076 const char SHIFT_LABEL[] = "Shift";
00077 const char CTRL_LABEL[] = "Ctrl";
00078
00079 void dialog_refresh_all();
00080
00081
00082
00083 class LLInventoryGestureAvailable : public LLInventoryCompletionObserver
00084 {
00085 public:
00086 LLInventoryGestureAvailable() {}
00087
00088 protected:
00089 virtual void done();
00090 };
00091
00092 void LLInventoryGestureAvailable::done()
00093 {
00094 LLPreview* preview = NULL;
00095 item_ref_t::iterator it = mComplete.begin();
00096 item_ref_t::iterator end = mComplete.end();
00097 for(; it < end; ++it)
00098 {
00099 preview = LLPreview::find((*it));
00100 if(preview)
00101 {
00102 preview->refresh();
00103 }
00104 }
00105 gInventory.removeObserver(this);
00106 delete this;
00107 }
00108
00109
00110 struct SortItemPtrsByName
00111 {
00112 bool operator()(const LLInventoryItem* i1, const LLInventoryItem* i2)
00113 {
00114 return (LLString::compareDict(i1->getName(), i2->getName()) < 0);
00115 }
00116 };
00117
00118
00119 LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& item_id, const LLUUID& object_id, BOOL take_focus)
00120 {
00121 LLPreviewGesture* previewp = (LLPreviewGesture*)LLPreview::find(item_id);
00122 if (previewp)
00123 {
00124 previewp->open();
00125 if (take_focus)
00126 {
00127 previewp->setFocus(TRUE);
00128 }
00129 return previewp;
00130 }
00131
00132 LLPreviewGesture* self = new LLPreviewGesture();
00133
00134
00135 self->init(item_id, object_id);
00136
00137
00138 LLUICtrlFactory::getInstance()->buildFloater(self, "floater_preview_gesture.xml");
00139 self->setTitle(title);
00140
00141
00142 LLMultiFloater* hostp = self->getHost();
00143 if (hostp == NULL)
00144 {
00145 LLRect r = self->getRect();
00146 LLRect screen = gFloaterView->getRect();
00147 r.setLeftTopAndSize(0, screen.getHeight(), r.getWidth(), r.getHeight());
00148 self->setRect(r);
00149 }
00150 else
00151 {
00152
00153 hostp->addFloater(self, TRUE);
00154 }
00155
00156
00157 LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_ANIMATION);
00158 gInventory.startBackgroundFetch(animation_folder_id);
00159
00160 LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_SOUND);
00161 gInventory.startBackgroundFetch(sound_folder_id);
00162
00163
00164 LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
00165 if(item && !item->isComplete())
00166 {
00167 LLInventoryGestureAvailable* observer;
00168 observer = new LLInventoryGestureAvailable();
00169 observer->watchItem(item_id);
00170 gInventory.addObserver(observer);
00171 item->fetchFromServer();
00172 }
00173 else
00174 {
00175
00176 self->refresh();
00177 }
00178
00179 if (take_focus)
00180 {
00181 self->setFocus(TRUE);
00182 }
00183
00184 return self;
00185 }
00186
00187
00188
00189 BOOL LLPreviewGesture::handleKeyHere(KEY key, MASK mask)
00190 {
00191 if(('S' == key) && (MASK_CONTROL == (mask & MASK_CONTROL)))
00192 {
00193 saveIfNeeded();
00194 return TRUE;
00195 }
00196
00197 return LLPreview::handleKeyHere(key, mask);
00198 }
00199
00200
00201
00202 BOOL LLPreviewGesture::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
00203 EDragAndDropType cargo_type,
00204 void* cargo_data,
00205 EAcceptance* accept,
00206 LLString& tooltip_msg)
00207 {
00208 BOOL handled = TRUE;
00209 switch(cargo_type)
00210 {
00211 case DAD_ANIMATION:
00212 case DAD_SOUND:
00213 {
00214
00215
00216
00217 LLInventoryItem* item = (LLInventoryItem*)cargo_data;
00218 if (item
00219 && gInventory.getItem(item->getUUID()))
00220 {
00221 LLPermissions perm = item->getPermissions();
00222 if (!((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED))
00223 {
00224 *accept = ACCEPT_NO;
00225 if (tooltip_msg.empty())
00226 {
00227 tooltip_msg.assign("Only animations and sounds\n"
00228 "with unrestricted permissions\n"
00229 "can be added to a gesture.");
00230 }
00231 break;
00232 }
00233 else if (drop)
00234 {
00235 LLScrollListItem* line = NULL;
00236 if (cargo_type == DAD_ANIMATION)
00237 {
00238 line = addStep("Animation");
00239 LLGestureStepAnimation* anim = (LLGestureStepAnimation*)line->getUserdata();
00240 anim->mAnimAssetID = item->getAssetUUID();
00241 anim->mAnimName = item->getName();
00242 }
00243 else if (cargo_type == DAD_SOUND)
00244 {
00245 line = addStep("Sound");
00246 LLGestureStepSound* sound = (LLGestureStepSound*)line->getUserdata();
00247 sound->mSoundAssetID = item->getAssetUUID();
00248 sound->mSoundName = item->getName();
00249 }
00250 updateLabel(line);
00251 mDirty = TRUE;
00252 refresh();
00253 }
00254 *accept = ACCEPT_YES_COPY_MULTI;
00255 }
00256 else
00257 {
00258
00259 *accept = ACCEPT_NO;
00260 }
00261 break;
00262 }
00263 default:
00264 *accept = ACCEPT_NO;
00265 if (tooltip_msg.empty())
00266 {
00267 tooltip_msg.assign("Only animations and sounds\n"
00268 "can be added to a gesture.");
00269 }
00270 break;
00271 }
00272 return handled;
00273 }
00274
00275
00276
00277 BOOL LLPreviewGesture::canClose()
00278 {
00279
00280 if(!mDirty || mForceClose)
00281 {
00282 return TRUE;
00283 }
00284 else
00285 {
00286
00287 gViewerWindow->alertXml("SaveChanges",
00288 handleSaveChangesDialog,
00289 this );
00290 return FALSE;
00291 }
00292 }
00293
00294
00295 void LLPreviewGesture::onClose(bool app_quitting)
00296 {
00297 gGestureManager.stopGesture(mPreviewGesture);
00298 LLPreview::onClose(app_quitting);
00299 }
00300
00301
00302 void LLPreviewGesture::onUpdateSucceeded()
00303 {
00304 refresh();
00305 }
00306
00307
00308 void LLPreviewGesture::setMinimized(BOOL minimize)
00309 {
00310 if (minimize != isMinimized())
00311 {
00312 LLFloater::setMinimized(minimize);
00313
00314
00315 if (!minimize)
00316 {
00317 refresh();
00318 }
00319 }
00320 }
00321
00322
00323
00324 void LLPreviewGesture::handleSaveChangesDialog(S32 option, void* data)
00325 {
00326 LLPreviewGesture* self = (LLPreviewGesture*)data;
00327 switch(option)
00328 {
00329 case 0:
00330 gGestureManager.stopGesture(self->mPreviewGesture);
00331 self->mCloseAfterSave = TRUE;
00332 onClickSave(data);
00333 break;
00334
00335 case 1:
00336 gGestureManager.stopGesture(self->mPreviewGesture);
00337 self->mDirty = FALSE;
00338 self->close();
00339 break;
00340
00341 case 2:
00342 default:
00343
00344 LLAppViewer::instance()->abortQuit();
00345 break;
00346 }
00347 }
00348
00349
00350 LLPreviewGesture::LLPreviewGesture()
00351 : LLPreview("Gesture Preview"),
00352 mTriggerEditor(NULL),
00353 mModifierCombo(NULL),
00354 mKeyCombo(NULL),
00355 mLibraryList(NULL),
00356 mAddBtn(NULL),
00357 mUpBtn(NULL),
00358 mDownBtn(NULL),
00359 mDeleteBtn(NULL),
00360 mStepList(NULL),
00361 mOptionsText(NULL),
00362 mAnimationRadio(NULL),
00363 mAnimationCombo(NULL),
00364 mSoundCombo(NULL),
00365 mChatEditor(NULL),
00366 mSaveBtn(NULL),
00367 mPreviewBtn(NULL),
00368 mPreviewGesture(NULL),
00369 mDirty(FALSE)
00370 {
00371 }
00372
00373
00374 LLPreviewGesture::~LLPreviewGesture()
00375 {
00376
00377 std::vector<LLScrollListItem*> data_list = mStepList->getAllData();
00378 std::vector<LLScrollListItem*>::iterator data_itor;
00379 for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor)
00380 {
00381 LLScrollListItem* item = *data_itor;
00382 LLGestureStep* step = (LLGestureStep*)item->getUserdata();
00383 delete step;
00384 step = NULL;
00385 }
00386 }
00387
00388
00389 BOOL LLPreviewGesture::postBuild()
00390 {
00391 LLLineEditor* edit;
00392 LLComboBox* combo;
00393 LLButton* btn;
00394 LLScrollListCtrl* list;
00395 LLTextBox* text;
00396 LLCheckBoxCtrl* check;
00397
00398 edit = getChild<LLLineEditor>("trigger_editor");
00399 edit->setKeystrokeCallback(onKeystrokeCommit);
00400 edit->setCommitCallback(onCommitSetDirty);
00401 edit->setCommitOnFocusLost(TRUE);
00402 edit->setCallbackUserData(this);
00403 edit->setIgnoreTab(TRUE);
00404 mTriggerEditor = edit;
00405
00406 text = getChild<LLTextBox>("replace_text");
00407 text->setEnabled(FALSE);
00408 mReplaceText = text;
00409
00410 edit = getChild<LLLineEditor>("replace_editor");
00411 edit->setEnabled(FALSE);
00412 edit->setKeystrokeCallback(onKeystrokeCommit);
00413 edit->setCommitCallback(onCommitSetDirty);
00414 edit->setCommitOnFocusLost(TRUE);
00415 edit->setCallbackUserData(this);
00416 edit->setIgnoreTab(TRUE);
00417 mReplaceEditor = edit;
00418
00419 combo = getChild<LLComboBox>( "modifier_combo");
00420 combo->setCommitCallback(onCommitSetDirty);
00421 combo->setCallbackUserData(this);
00422 mModifierCombo = combo;
00423
00424 combo = getChild<LLComboBox>( "key_combo");
00425 combo->setCommitCallback(onCommitSetDirty);
00426 combo->setCallbackUserData(this);
00427 mKeyCombo = combo;
00428
00429 list = getChild<LLScrollListCtrl>("library_list");
00430 list->setCommitCallback(onCommitLibrary);
00431 list->setDoubleClickCallback(onClickAdd);
00432 list->setCallbackUserData(this);
00433 mLibraryList = list;
00434
00435 btn = getChild<LLButton>( "add_btn");
00436 btn->setClickedCallback(onClickAdd);
00437 btn->setCallbackUserData(this);
00438 btn->setEnabled(FALSE);
00439 mAddBtn = btn;
00440
00441 btn = getChild<LLButton>( "up_btn");
00442 btn->setClickedCallback(onClickUp);
00443 btn->setCallbackUserData(this);
00444 btn->setEnabled(FALSE);
00445 mUpBtn = btn;
00446
00447 btn = getChild<LLButton>( "down_btn");
00448 btn->setClickedCallback(onClickDown);
00449 btn->setCallbackUserData(this);
00450 btn->setEnabled(FALSE);
00451 mDownBtn = btn;
00452
00453 btn = getChild<LLButton>( "delete_btn");
00454 btn->setClickedCallback(onClickDelete);
00455 btn->setCallbackUserData(this);
00456 btn->setEnabled(FALSE);
00457 mDeleteBtn = btn;
00458
00459 list = getChild<LLScrollListCtrl>("step_list");
00460 list->setCommitCallback(onCommitStep);
00461 list->setCallbackUserData(this);
00462 mStepList = list;
00463
00464
00465 text = getChild<LLTextBox>("options_text");
00466 text->setBorderVisible(TRUE);
00467 mOptionsText = text;
00468
00469 combo = getChild<LLComboBox>( "animation_list");
00470 combo->setVisible(FALSE);
00471 combo->setCommitCallback(onCommitAnimation);
00472 combo->setCallbackUserData(this);
00473 mAnimationCombo = combo;
00474
00475 LLRadioGroup* group;
00476 group = getChild<LLRadioGroup>("animation_trigger_type");
00477 group->setVisible(FALSE);
00478 group->setCommitCallback(onCommitAnimationTrigger);
00479 group->setCallbackUserData(this);
00480 mAnimationRadio = group;
00481
00482 combo = getChild<LLComboBox>( "sound_list");
00483 combo->setVisible(FALSE);
00484 combo->setCommitCallback(onCommitSound);
00485 combo->setCallbackUserData(this);
00486 mSoundCombo = combo;
00487
00488 edit = getChild<LLLineEditor>("chat_editor");
00489 edit->setVisible(FALSE);
00490 edit->setCommitCallback(onCommitChat);
00491
00492 edit->setCommitOnFocusLost(TRUE);
00493 edit->setCallbackUserData(this);
00494 edit->setIgnoreTab(TRUE);
00495 mChatEditor = edit;
00496
00497 check = getChild<LLCheckBoxCtrl>( "wait_anim_check");
00498 check->setVisible(FALSE);
00499 check->setCommitCallback(onCommitWait);
00500 check->setCallbackUserData(this);
00501 mWaitAnimCheck = check;
00502
00503 check = getChild<LLCheckBoxCtrl>( "wait_time_check");
00504 check->setVisible(FALSE);
00505 check->setCommitCallback(onCommitWait);
00506 check->setCallbackUserData(this);
00507 mWaitTimeCheck = check;
00508
00509 edit = getChild<LLLineEditor>("wait_time_editor");
00510 edit->setEnabled(FALSE);
00511 edit->setVisible(FALSE);
00512 edit->setPrevalidate(LLLineEditor::prevalidateFloat);
00513
00514 edit->setCommitOnFocusLost(TRUE);
00515 edit->setCommitCallback(onCommitWaitTime);
00516 edit->setCallbackUserData(this);
00517 edit->setIgnoreTab(TRUE);
00518 mWaitTimeEditor = edit;
00519
00520
00521 check = getChild<LLCheckBoxCtrl>( "active_check");
00522 check->setCommitCallback(onCommitActive);
00523 check->setCallbackUserData(this);
00524 mActiveCheck = check;
00525
00526 btn = getChild<LLButton>( "save_btn");
00527 btn->setClickedCallback(onClickSave);
00528 btn->setCallbackUserData(this);
00529 mSaveBtn = btn;
00530
00531 btn = getChild<LLButton>( "preview_btn");
00532 btn->setClickedCallback(onClickPreview);
00533 btn->setCallbackUserData(this);
00534 mPreviewBtn = btn;
00535
00536
00537
00538 addModifiers();
00539 addKeys();
00540 addAnimations();
00541 addSounds();
00542
00543
00544 const LLInventoryItem* item = getItem();
00545
00546 if (item)
00547 {
00548 childSetCommitCallback("desc", LLPreview::onText, this);
00549 childSetText("desc", item->getDescription());
00550 childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
00551 }
00552
00553 return TRUE;
00554 }
00555
00556
00557 void LLPreviewGesture::addModifiers()
00558 {
00559 LLComboBox* combo = mModifierCombo;
00560
00561 combo->add( NONE_LABEL, ADD_BOTTOM );
00562 combo->add( SHIFT_LABEL, ADD_BOTTOM );
00563 combo->add( CTRL_LABEL, ADD_BOTTOM );
00564 combo->setCurrentByIndex(0);
00565 }
00566
00567 void LLPreviewGesture::addKeys()
00568 {
00569 LLComboBox* combo = mKeyCombo;
00570
00571 combo->add( NONE_LABEL );
00572 for (KEY key = KEY_F2; key <= KEY_F12; key++)
00573 {
00574 combo->add( LLKeyboard::stringFromKey(key), ADD_BOTTOM );
00575 }
00576 combo->setCurrentByIndex(0);
00577 }
00578
00579
00580
00581 void LLPreviewGesture::addAnimations()
00582 {
00583 LLComboBox* combo = mAnimationCombo;
00584
00585 combo->removeall();
00586
00587 LLString none_text = getString("none_text");
00588
00589 combo->add(none_text, LLUUID::null);
00590
00591
00592 S32 i;
00593 for (i = 0; i < gUserAnimStatesCount; ++i)
00594 {
00595
00596 std::string label = LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName );
00597 const LLUUID& id = gUserAnimStates[i].mID;
00598 combo->add(label, id);
00599 }
00600
00601
00602 LLViewerInventoryCategory::cat_array_t cats;
00603 LLViewerInventoryItem::item_array_t items;
00604 LLIsTypeWithPermissions is_copyable_animation(LLAssetType::AT_ANIMATION,
00605 PERM_ITEM_UNRESTRICTED,
00606 gAgent.getID(),
00607 gAgent.getGroupID());
00608 gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
00609 cats,
00610 items,
00611 LLInventoryModel::EXCLUDE_TRASH,
00612 is_copyable_animation);
00613
00614
00615 std::vector<LLInventoryItem*> animations;
00616
00617 S32 count = items.count();
00618 for(i = 0; i < count; ++i)
00619 {
00620 animations.push_back( items.get(i) );
00621 }
00622
00623
00624 std::sort(animations.begin(), animations.end(), SortItemPtrsByName());
00625
00626
00627 std::vector<LLInventoryItem*>::iterator it;
00628 for (it = animations.begin(); it != animations.end(); ++it)
00629 {
00630 LLInventoryItem* item = *it;
00631
00632 combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM);
00633 }
00634 }
00635
00636
00637 void LLPreviewGesture::addSounds()
00638 {
00639 LLComboBox* combo = mSoundCombo;
00640 combo->removeall();
00641
00642 LLString none_text = getString("none_text");
00643
00644 combo->add(none_text, LLUUID::null);
00645
00646
00647 LLViewerInventoryCategory::cat_array_t cats;
00648 LLViewerInventoryItem::item_array_t items;
00649 LLIsTypeWithPermissions is_copyable_sound(LLAssetType::AT_SOUND,
00650 PERM_ITEM_UNRESTRICTED,
00651 gAgent.getID(),
00652 gAgent.getGroupID());
00653 gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
00654 cats,
00655 items,
00656 LLInventoryModel::EXCLUDE_TRASH,
00657 is_copyable_sound);
00658
00659
00660 std::vector<LLInventoryItem*> sounds;
00661
00662 S32 i;
00663 S32 count = items.count();
00664 for(i = 0; i < count; ++i)
00665 {
00666 sounds.push_back( items.get(i) );
00667 }
00668
00669
00670 std::sort(sounds.begin(), sounds.end(), SortItemPtrsByName());
00671
00672
00673 std::vector<LLInventoryItem*>::iterator it;
00674 for (it = sounds.begin(); it != sounds.end(); ++it)
00675 {
00676 LLInventoryItem* item = *it;
00677
00678 combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM);
00679 }
00680 }
00681
00682
00683 void LLPreviewGesture::init(const LLUUID& item_id, const LLUUID& object_id)
00684 {
00685
00686 setItemID(item_id);
00687 setObjectID(object_id);
00688 }
00689
00690
00691 void LLPreviewGesture::refresh()
00692 {
00693
00694 LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
00695 bool is_complete = (item && item->isComplete()) ? true : false;
00696 if (mPreviewGesture || !is_complete)
00697 {
00698
00699 childSetEnabled("desc", FALSE);
00700
00701 mTriggerEditor->setEnabled(FALSE);
00702 mReplaceText->setEnabled(FALSE);
00703 mReplaceEditor->setEnabled(FALSE);
00704 mModifierCombo->setEnabled(FALSE);
00705 mKeyCombo->setEnabled(FALSE);
00706 mLibraryList->setEnabled(FALSE);
00707 mAddBtn->setEnabled(FALSE);
00708 mUpBtn->setEnabled(FALSE);
00709 mDownBtn->setEnabled(FALSE);
00710 mDeleteBtn->setEnabled(FALSE);
00711 mStepList->setEnabled(FALSE);
00712 mOptionsText->setEnabled(FALSE);
00713 mAnimationCombo->setEnabled(FALSE);
00714 mAnimationRadio->setEnabled(FALSE);
00715 mSoundCombo->setEnabled(FALSE);
00716 mChatEditor->setEnabled(FALSE);
00717 mWaitAnimCheck->setEnabled(FALSE);
00718 mWaitTimeCheck->setEnabled(FALSE);
00719 mWaitTimeEditor->setEnabled(FALSE);
00720 mActiveCheck->setEnabled(FALSE);
00721 mSaveBtn->setEnabled(FALSE);
00722
00723
00724 mPreviewBtn->setEnabled(TRUE);
00725 return;
00726 }
00727
00728 BOOL modifiable = item->getPermissions().allowModifyBy(gAgent.getID());
00729
00730 childSetEnabled("desc", modifiable);
00731 mTriggerEditor->setEnabled(TRUE);
00732 mLibraryList->setEnabled(modifiable);
00733 mStepList->setEnabled(modifiable);
00734 mOptionsText->setEnabled(modifiable);
00735 mAnimationCombo->setEnabled(modifiable);
00736 mAnimationRadio->setEnabled(modifiable);
00737 mSoundCombo->setEnabled(modifiable);
00738 mChatEditor->setEnabled(modifiable);
00739 mWaitAnimCheck->setEnabled(modifiable);
00740 mWaitTimeCheck->setEnabled(modifiable);
00741 mWaitTimeEditor->setEnabled(modifiable);
00742 mActiveCheck->setEnabled(TRUE);
00743
00744 const std::string& trigger = mTriggerEditor->getText();
00745 BOOL have_trigger = !trigger.empty();
00746
00747 const std::string& replace = mReplaceEditor->getText();
00748 BOOL have_replace = !replace.empty();
00749
00750 LLScrollListItem* library_item = mLibraryList->getFirstSelected();
00751 BOOL have_library = (library_item != NULL);
00752
00753 LLScrollListItem* step_item = mStepList->getFirstSelected();
00754 S32 step_index = mStepList->getFirstSelectedIndex();
00755 S32 step_count = mStepList->getItemCount();
00756 BOOL have_step = (step_item != NULL);
00757
00758 mReplaceText->setEnabled(have_trigger || have_replace);
00759 mReplaceEditor->setEnabled(have_trigger || have_replace);
00760
00761 mModifierCombo->setEnabled(TRUE);
00762 mKeyCombo->setEnabled(TRUE);
00763
00764 mAddBtn->setEnabled(modifiable && have_library);
00765 mUpBtn->setEnabled(modifiable && have_step && step_index > 0);
00766 mDownBtn->setEnabled(modifiable && have_step && step_index < step_count-1);
00767 mDeleteBtn->setEnabled(modifiable && have_step);
00768
00769
00770 mAnimationCombo->setVisible(FALSE);
00771 mAnimationRadio->setVisible(FALSE);
00772 mSoundCombo->setVisible(FALSE);
00773 mChatEditor->setVisible(FALSE);
00774 mWaitAnimCheck->setVisible(FALSE);
00775 mWaitTimeCheck->setVisible(FALSE);
00776 mWaitTimeEditor->setVisible(FALSE);
00777
00778 LLString optionstext;
00779
00780 if (have_step)
00781 {
00782
00783 LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
00784 EStepType type = step->getType();
00785
00786 switch(type)
00787 {
00788 case STEP_ANIMATION:
00789 {
00790 LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
00791 optionstext = getString("step_anim");
00792 mAnimationCombo->setVisible(TRUE);
00793 mAnimationRadio->setVisible(TRUE);
00794 mAnimationRadio->setSelectedIndex((anim_step->mFlags & ANIM_FLAG_STOP) ? 1 : 0);
00795 mAnimationCombo->setCurrentByID(anim_step->mAnimAssetID);
00796 break;
00797 }
00798 case STEP_SOUND:
00799 {
00800 LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
00801 optionstext = getString("step_sound");
00802 mSoundCombo->setVisible(TRUE);
00803 mSoundCombo->setCurrentByID(sound_step->mSoundAssetID);
00804 break;
00805 }
00806 case STEP_CHAT:
00807 {
00808 LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
00809 optionstext = getString("step_chat");
00810 mChatEditor->setVisible(TRUE);
00811 mChatEditor->setText(chat_step->mChatText);
00812 break;
00813 }
00814 case STEP_WAIT:
00815 {
00816 LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
00817 optionstext = getString("step_wait");
00818 mWaitAnimCheck->setVisible(TRUE);
00819 mWaitAnimCheck->set(wait_step->mFlags & WAIT_FLAG_ALL_ANIM);
00820 mWaitTimeCheck->setVisible(TRUE);
00821 mWaitTimeCheck->set(wait_step->mFlags & WAIT_FLAG_TIME);
00822 mWaitTimeEditor->setVisible(TRUE);
00823 std::string buffer = llformat("%.1f", (double)wait_step->mWaitSeconds);
00824 mWaitTimeEditor->setText(buffer);
00825 break;
00826 }
00827 default:
00828 break;
00829 }
00830 }
00831
00832 mOptionsText->setText(optionstext);
00833
00834 BOOL active = gGestureManager.isGestureActive(mItemUUID);
00835 mActiveCheck->set(active);
00836
00837
00838 mPreviewBtn->setEnabled(step_count > 0);
00839
00840
00841 mSaveBtn->setEnabled(mDirty);
00842 addAnimations();
00843 addSounds();
00844 }
00845
00846
00847 void LLPreviewGesture::initDefaultGesture()
00848 {
00849 LLScrollListItem* item;
00850 item = addStep("Animation");
00851 LLGestureStepAnimation* anim = (LLGestureStepAnimation*)item->getUserdata();
00852 anim->mAnimAssetID = ANIM_AGENT_HELLO;
00853 anim->mAnimName = "Wave";
00854 updateLabel(item);
00855
00856 item = addStep("Wait");
00857 LLGestureStepWait* wait = (LLGestureStepWait*)item->getUserdata();
00858 wait->mFlags = WAIT_FLAG_ALL_ANIM;
00859 updateLabel(item);
00860
00861 item = addStep("Chat");
00862 LLGestureStepChat* chat_step = (LLGestureStepChat*)item->getUserdata();
00863 chat_step->mChatText = "Hello, avatar!";
00864 updateLabel(item);
00865
00866
00867 mStepList->selectFirstItem();
00868
00869
00870 mDirty = TRUE;
00871 }
00872
00873
00874 void LLPreviewGesture::loadAsset()
00875 {
00876 const LLInventoryItem* item = getItem();
00877 if (!item) return;
00878
00879 LLUUID asset_id = item->getAssetUUID();
00880 if (asset_id.isNull())
00881 {
00882
00883
00884 initDefaultGesture();
00885 refresh();
00886 return;
00887 }
00888
00889
00890
00891
00892
00893
00894 LLUUID* item_idp = new LLUUID(mItemUUID);
00895
00896 const BOOL high_priority = TRUE;
00897 gAssetStorage->getAssetData(asset_id,
00898 LLAssetType::AT_GESTURE,
00899 onLoadComplete,
00900 (void**)item_idp,
00901 high_priority);
00902 mAssetStatus = PREVIEW_ASSET_LOADING;
00903 }
00904
00905
00906
00907 void LLPreviewGesture::onLoadComplete(LLVFS *vfs,
00908 const LLUUID& asset_uuid,
00909 LLAssetType::EType type,
00910 void* user_data, S32 status, LLExtStat ext_status)
00911 {
00912 LLUUID* item_idp = (LLUUID*)user_data;
00913 LLPreview* preview = LLPreview::find(*item_idp);
00914 if (preview)
00915 {
00916 LLPreviewGesture* self = (LLPreviewGesture*)preview;
00917
00918 if (0 == status)
00919 {
00920 LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
00921 S32 size = file.getSize();
00922
00923 char* buffer = new char[size+1];
00924 file.read((U8*)buffer, size);
00925 buffer[size] = '\0';
00926
00927 LLMultiGesture* gesture = new LLMultiGesture();
00928
00929 LLDataPackerAsciiBuffer dp(buffer, size+1);
00930 BOOL ok = gesture->deserialize(dp);
00931
00932 if (ok)
00933 {
00934
00935 self->loadUIFromGesture(gesture);
00936
00937 self->mStepList->selectFirstItem();
00938
00939 self->mDirty = FALSE;
00940 self->refresh();
00941 }
00942 else
00943 {
00944 llwarns << "Unable to load gesture" << llendl;
00945 }
00946
00947 delete gesture;
00948 gesture = NULL;
00949
00950 delete [] buffer;
00951 buffer = NULL;
00952
00953 self->mAssetStatus = PREVIEW_ASSET_LOADED;
00954 }
00955 else
00956 {
00957 LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
00958
00959 if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
00960 LL_ERR_FILE_EMPTY == status)
00961 {
00962 LLDelayedGestureError::gestureMissing( *item_idp );
00963 }
00964 else
00965 {
00966 LLDelayedGestureError::gestureFailedToLoad( *item_idp );
00967 }
00968
00969 llwarns << "Problem loading gesture: " << status << llendl;
00970 self->mAssetStatus = PREVIEW_ASSET_ERROR;
00971 }
00972 }
00973 delete item_idp;
00974 item_idp = NULL;
00975 }
00976
00977
00978 void LLPreviewGesture::loadUIFromGesture(LLMultiGesture* gesture)
00979 {
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 mTriggerEditor->setText(gesture->mTrigger);
00991
00992 mReplaceEditor->setText(gesture->mReplaceText);
00993
00994 switch (gesture->mMask)
00995 {
00996 default:
00997 case MASK_NONE:
00998 mModifierCombo->setSimple( LLString(NONE_LABEL) );
00999 break;
01000 case MASK_SHIFT:
01001 mModifierCombo->setSimple( LLString(SHIFT_LABEL) );
01002 break;
01003 case MASK_CONTROL:
01004 mModifierCombo->setSimple( LLString(CTRL_LABEL) );
01005 break;
01006 }
01007
01008 mKeyCombo->setCurrentByIndex(0);
01009 if (gesture->mKey != KEY_NONE)
01010 {
01011 mKeyCombo->setSimple(LLKeyboard::stringFromKey(gesture->mKey));
01012 }
01013
01014
01015 S32 i;
01016 S32 count = gesture->mSteps.size();
01017 for (i = 0; i < count; ++i)
01018 {
01019 LLGestureStep* step = gesture->mSteps[i];
01020
01021 LLGestureStep* new_step = NULL;
01022
01023 switch(step->getType())
01024 {
01025 case STEP_ANIMATION:
01026 {
01027 LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
01028 LLGestureStepAnimation* new_anim_step =
01029 new LLGestureStepAnimation(*anim_step);
01030 new_step = new_anim_step;
01031 break;
01032 }
01033 case STEP_SOUND:
01034 {
01035 LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
01036 LLGestureStepSound* new_sound_step =
01037 new LLGestureStepSound(*sound_step);
01038 new_step = new_sound_step;
01039 break;
01040 }
01041 case STEP_CHAT:
01042 {
01043 LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
01044 LLGestureStepChat* new_chat_step =
01045 new LLGestureStepChat(*chat_step);
01046 new_step = new_chat_step;
01047 break;
01048 }
01049 case STEP_WAIT:
01050 {
01051 LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
01052 LLGestureStepWait* new_wait_step =
01053 new LLGestureStepWait(*wait_step);
01054 new_step = new_wait_step;
01055 break;
01056 }
01057 default:
01058 {
01059 break;
01060 }
01061 }
01062
01063 if (!new_step) continue;
01064
01065
01066 LLSD row;
01067 row["columns"][0]["value"] = new_step->getLabel();
01068 row["columns"][0]["font"] = "SANSSERIF_SMALL";
01069 LLScrollListItem* item = mStepList->addElement(row);
01070 item->setUserdata(new_step);
01071 }
01072 }
01073
01074
01075
01076 struct LLSaveInfo
01077 {
01078 LLSaveInfo(const LLUUID& item_id, const LLUUID& object_id, const LLString& desc,
01079 const LLTransactionID tid)
01080 : mItemUUID(item_id), mObjectUUID(object_id), mDesc(desc), mTransactionID(tid)
01081 {
01082 }
01083
01084 LLUUID mItemUUID;
01085 LLUUID mObjectUUID;
01086 LLString mDesc;
01087 LLTransactionID mTransactionID;
01088 };
01089
01090
01091 void LLPreviewGesture::saveIfNeeded()
01092 {
01093 if (!gAssetStorage)
01094 {
01095 llwarns << "Can't save gesture, no asset storage system." << llendl;
01096 return;
01097 }
01098
01099 if (!mDirty)
01100 {
01101 return;
01102 }
01103
01104
01105 LLMultiGesture* gesture = createGesture();
01106
01107
01108 S32 max_size = gesture->getMaxSerialSize();
01109 char* buffer = new char[max_size];
01110
01111 LLDataPackerAsciiBuffer dp(buffer, max_size);
01112
01113 BOOL ok = gesture->serialize(dp);
01114
01115 if (dp.getCurrentSize() > 1000)
01116 {
01117 gViewerWindow->alertXml("GestureSaveFailedTooManySteps");
01118
01119 delete gesture;
01120 gesture = NULL;
01121 }
01122 else if (!ok)
01123 {
01124 gViewerWindow->alertXml("GestureSaveFailedTryAgain");
01125 delete gesture;
01126 gesture = NULL;
01127 }
01128 else
01129 {
01130
01131 LLTransactionID tid;
01132 LLAssetID asset_id;
01133 tid.generate();
01134 asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
01135
01136 LLVFile file(gVFS, asset_id, LLAssetType::AT_GESTURE, LLVFile::APPEND);
01137
01138 S32 size = dp.getCurrentSize();
01139 file.setMaxSize(size);
01140 file.write((U8*)buffer, size);
01141
01142 BOOL delayedUpload = FALSE;
01143
01144
01145 LLViewerInventoryItem* item = (LLViewerInventoryItem*) getItem();
01146 if (item)
01147 {
01148 std::string agent_url = gAgent.getRegion()->getCapability("UpdateGestureAgentInventory");
01149 std::string task_url = gAgent.getRegion()->getCapability("UpdateGestureTaskInventory");
01150 if (mObjectUUID.isNull() && !agent_url.empty())
01151 {
01152
01153
01154
01155 item->setComplete(FALSE);
01156 refresh();
01157 item->setComplete(TRUE);
01158
01159
01160 LLSD body;
01161 body["item_id"] = mItemUUID;
01162 LLHTTPClient::post(agent_url, body,
01163 new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE));
01164 delayedUpload = TRUE;
01165 }
01166 else if (!mObjectUUID.isNull() && !task_url.empty())
01167 {
01168
01169 LLSD body;
01170 body["task_id"] = mObjectUUID;
01171 body["item_id"] = mItemUUID;
01172 LLHTTPClient::post(task_url, body,
01173 new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE));
01174 }
01175 else if (gAssetStorage)
01176 {
01177 LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
01178 LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid);
01179 gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, FALSE);
01180 }
01181 }
01182
01183
01184
01185 if (!delayedUpload && gGestureManager.isGestureActive(mItemUUID))
01186 {
01187
01188 gGestureManager.replaceGesture(mItemUUID, gesture, asset_id);
01189
01190
01191
01192 gInventory.notifyObservers();
01193 }
01194 else
01195 {
01196
01197 delete gesture;
01198 gesture = NULL;
01199 }
01200
01201 mDirty = FALSE;
01202
01203
01204 if(!delayedUpload)
01205 {
01206 refresh();
01207 }
01208 }
01209
01210 delete [] buffer;
01211 buffer = NULL;
01212 }
01213
01214
01215
01216
01217
01218 void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status)
01219 {
01220 LLSaveInfo* info = (LLSaveInfo*)user_data;
01221 if (info && (status == 0))
01222 {
01223 if(info->mObjectUUID.isNull())
01224 {
01225
01226 LLViewerInventoryItem* item;
01227 item = (LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID);
01228 if(item)
01229 {
01230 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
01231 new_item->setDescription(info->mDesc);
01232 new_item->setTransactionID(info->mTransactionID);
01233 new_item->setAssetUUID(asset_uuid);
01234 new_item->updateServer(FALSE);
01235 gInventory.updateItem(new_item);
01236 gInventory.notifyObservers();
01237 }
01238 else
01239 {
01240 llwarns << "Inventory item for gesture " << info->mItemUUID
01241 << " is no longer in agent inventory." << llendl
01242 }
01243 }
01244 else
01245 {
01246
01247 LLViewerObject* object = gObjectList.findObject(info->mObjectUUID);
01248 LLViewerInventoryItem* item = NULL;
01249 if(object)
01250 {
01251 item = (LLViewerInventoryItem*)object->getInventoryObject(info->mItemUUID);
01252 }
01253 if(object && item)
01254 {
01255 item->setDescription(info->mDesc);
01256 item->setAssetUUID(asset_uuid);
01257 item->setTransactionID(info->mTransactionID);
01258 object->updateInventory(item, TASK_INVENTORY_ITEM_KEY, false);
01259 dialog_refresh_all();
01260 }
01261 else
01262 {
01263 gViewerWindow->alertXml("GestureSaveFailedObjectNotFound");
01264 }
01265 }
01266
01267
01268 LLPreviewGesture* previewp = (LLPreviewGesture*)LLPreview::find(info->mItemUUID);
01269 if (previewp && previewp->mCloseAfterSave)
01270 {
01271 previewp->close();
01272 }
01273 }
01274 else
01275 {
01276 llwarns << "Problem saving gesture: " << status << llendl;
01277 LLStringBase<char>::format_map_t args;
01278 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
01279 gViewerWindow->alertXml("GestureSaveFailedReason",args);
01280 }
01281 delete info;
01282 info = NULL;
01283 }
01284
01285
01286 LLMultiGesture* LLPreviewGesture::createGesture()
01287 {
01288 LLMultiGesture* gesture = new LLMultiGesture();
01289
01290 gesture->mTrigger = mTriggerEditor->getText();
01291 gesture->mReplaceText = mReplaceEditor->getText();
01292
01293 const LLString& modifier = mModifierCombo->getSimple();
01294 if (modifier == CTRL_LABEL)
01295 {
01296 gesture->mMask = MASK_CONTROL;
01297 }
01298 else if (modifier == SHIFT_LABEL)
01299 {
01300 gesture->mMask = MASK_SHIFT;
01301 }
01302 else
01303 {
01304 gesture->mMask = MASK_NONE;
01305 }
01306
01307 if (mKeyCombo->getCurrentIndex() == 0)
01308 {
01309 gesture->mKey = KEY_NONE;
01310 }
01311 else
01312 {
01313 const LLString& key_string = mKeyCombo->getSimple();
01314 LLKeyboard::keyFromString(key_string.c_str(), &(gesture->mKey));
01315 }
01316
01317 std::vector<LLScrollListItem*> data_list = mStepList->getAllData();
01318 std::vector<LLScrollListItem*>::iterator data_itor;
01319 for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor)
01320 {
01321 LLScrollListItem* item = *data_itor;
01322 LLGestureStep* step = (LLGestureStep*)item->getUserdata();
01323
01324 switch(step->getType())
01325 {
01326 case STEP_ANIMATION:
01327 {
01328
01329 LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
01330 LLGestureStepAnimation* new_anim_step =
01331 new LLGestureStepAnimation(*anim_step);
01332 gesture->mSteps.push_back(new_anim_step);
01333 break;
01334 }
01335 case STEP_SOUND:
01336 {
01337
01338 LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
01339 LLGestureStepSound* new_sound_step =
01340 new LLGestureStepSound(*sound_step);
01341 gesture->mSteps.push_back(new_sound_step);
01342 break;
01343 }
01344 case STEP_CHAT:
01345 {
01346
01347 LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
01348 LLGestureStepChat* new_chat_step =
01349 new LLGestureStepChat(*chat_step);
01350 gesture->mSteps.push_back(new_chat_step);
01351 break;
01352 }
01353 case STEP_WAIT:
01354 {
01355
01356 LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
01357 LLGestureStepWait* new_wait_step =
01358 new LLGestureStepWait(*wait_step);
01359 gesture->mSteps.push_back(new_wait_step);
01360 break;
01361 }
01362 default:
01363 {
01364 break;
01365 }
01366 }
01367 }
01368
01369 return gesture;
01370 }
01371
01372
01373
01374 void LLPreviewGesture::updateLabel(LLScrollListItem* item)
01375 {
01376 LLGestureStep* step = (LLGestureStep*)item->getUserdata();
01377
01378 LLScrollListCell* cell = item->getColumn(0);
01379 LLScrollListText* text_cell = (LLScrollListText*)cell;
01380 std::string label = step->getLabel();
01381 text_cell->setText(label);
01382 }
01383
01384
01385 void LLPreviewGesture::onCommitSetDirty(LLUICtrl* ctrl, void* data)
01386 {
01387 LLPreviewGesture* self = (LLPreviewGesture*)data;
01388 self->mDirty = TRUE;
01389 self->refresh();
01390 }
01391
01392
01393 void LLPreviewGesture::onCommitLibrary(LLUICtrl* ctrl, void* data)
01394 {
01395 LLPreviewGesture* self = (LLPreviewGesture*)data;
01396
01397 LLScrollListItem* library_item = self->mLibraryList->getFirstSelected();
01398 if (library_item)
01399 {
01400 self->mStepList->deselectAllItems();
01401 self->refresh();
01402 }
01403 }
01404
01405
01406
01407 void LLPreviewGesture::onCommitStep(LLUICtrl* ctrl, void* data)
01408 {
01409 LLPreviewGesture* self = (LLPreviewGesture*)data;
01410
01411 LLScrollListItem* step_item = self->mStepList->getFirstSelected();
01412 if (!step_item) return;
01413
01414 self->mLibraryList->deselectAllItems();
01415 self->refresh();
01416 }
01417
01418
01419
01420 void LLPreviewGesture::onCommitAnimation(LLUICtrl* ctrl, void* data)
01421 {
01422 LLPreviewGesture* self = (LLPreviewGesture*)data;
01423
01424 LLScrollListItem* step_item = self->mStepList->getFirstSelected();
01425 if (step_item)
01426 {
01427 LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
01428 if (step->getType() == STEP_ANIMATION)
01429 {
01430
01431 LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
01432 if (self->mAnimationCombo->getCurrentIndex() == 0)
01433 {
01434 anim_step->mAnimName.clear();
01435 anim_step->mAnimAssetID.setNull();
01436 }
01437 else
01438 {
01439 anim_step->mAnimName = self->mAnimationCombo->getSimple();
01440 anim_step->mAnimAssetID = self->mAnimationCombo->getCurrentID();
01441 }
01442
01443
01444
01445 updateLabel(step_item);
01446
01447 self->mDirty = TRUE;
01448 self->refresh();
01449 }
01450 }
01451 }
01452
01453
01454 void LLPreviewGesture::onCommitAnimationTrigger(LLUICtrl* ctrl, void *data)
01455 {
01456 LLPreviewGesture* self = (LLPreviewGesture*)data;
01457
01458 LLScrollListItem* step_item = self->mStepList->getFirstSelected();
01459 if (step_item)
01460 {
01461 LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
01462 if (step->getType() == STEP_ANIMATION)
01463 {
01464 LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
01465 if (self->mAnimationRadio->getSelectedIndex() == 0)
01466 {
01467
01468 anim_step->mFlags &= ~ANIM_FLAG_STOP;
01469 }
01470 else
01471 {
01472
01473 anim_step->mFlags |= ANIM_FLAG_STOP;
01474 }
01475
01476 updateLabel(step_item);
01477
01478 self->mDirty = TRUE;
01479 self->refresh();
01480 }
01481 }
01482 }
01483
01484
01485 void LLPreviewGesture::onCommitSound(LLUICtrl* ctrl, void* data)
01486 {
01487 LLPreviewGesture* self = (LLPreviewGesture*)data;
01488
01489 LLScrollListItem* step_item = self->mStepList->getFirstSelected();
01490 if (step_item)
01491 {
01492 LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
01493 if (step->getType() == STEP_SOUND)
01494 {
01495
01496 LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
01497 sound_step->mSoundName = self->mSoundCombo->getSimple();
01498 sound_step->mSoundAssetID = self->mSoundCombo->getCurrentID();
01499 sound_step->mFlags = 0x0;
01500
01501
01502 updateLabel(step_item);
01503
01504 self->mDirty = TRUE;
01505 self->refresh();
01506 }
01507 }
01508 }
01509
01510
01511 void LLPreviewGesture::onCommitChat(LLUICtrl* ctrl, void* data)
01512 {
01513 LLPreviewGesture* self = (LLPreviewGesture*)data;
01514
01515 LLScrollListItem* step_item = self->mStepList->getFirstSelected();
01516 if (!step_item) return;
01517
01518 LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
01519 if (step->getType() != STEP_CHAT) return;
01520
01521 LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
01522 chat_step->mChatText = self->mChatEditor->getText();
01523 chat_step->mFlags = 0x0;
01524
01525
01526 updateLabel(step_item);
01527
01528 self->mDirty = TRUE;
01529 self->refresh();
01530 }
01531
01532
01533 void LLPreviewGesture::onCommitWait(LLUICtrl* ctrl, void* data)
01534 {
01535 LLPreviewGesture* self = (LLPreviewGesture*)data;
01536
01537 LLScrollListItem* step_item = self->mStepList->getFirstSelected();
01538 if (!step_item) return;
01539
01540 LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
01541 if (step->getType() != STEP_WAIT) return;
01542
01543 LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
01544 U32 flags = 0x0;
01545 if (self->mWaitAnimCheck->get()) flags |= WAIT_FLAG_ALL_ANIM;
01546 if (self->mWaitTimeCheck->get()) flags |= WAIT_FLAG_TIME;
01547 wait_step->mFlags = flags;
01548
01549 {
01550 LLLocale locale(LLLocale::USER_LOCALE);
01551
01552 F32 wait_seconds = (F32)atof(self->mWaitTimeEditor->getText().c_str());
01553 if (wait_seconds < 0.f) wait_seconds = 0.f;
01554 if (wait_seconds > 3600.f) wait_seconds = 3600.f;
01555 wait_step->mWaitSeconds = wait_seconds;
01556 }
01557
01558
01559 self->mWaitTimeEditor->setEnabled(self->mWaitTimeCheck->get());
01560
01561
01562 updateLabel(step_item);
01563
01564 self->mDirty = TRUE;
01565 self->refresh();
01566 }
01567
01568
01569 void LLPreviewGesture::onCommitWaitTime(LLUICtrl* ctrl, void* data)
01570 {
01571 LLPreviewGesture* self = (LLPreviewGesture*)data;
01572
01573 LLScrollListItem* step_item = self->mStepList->getFirstSelected();
01574 if (!step_item) return;
01575
01576 LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
01577 if (step->getType() != STEP_WAIT) return;
01578
01579 self->mWaitTimeCheck->set(TRUE);
01580 onCommitWait(ctrl, data);
01581 }
01582
01583
01584
01585 void LLPreviewGesture::onKeystrokeCommit(LLLineEditor* caller,
01586 void* data)
01587 {
01588
01589 onCommitSetDirty(caller, data);
01590 }
01591
01592
01593 void LLPreviewGesture::onClickAdd(void* data)
01594 {
01595 LLPreviewGesture* self = (LLPreviewGesture*)data;
01596
01597 LLScrollListItem* library_item = self->mLibraryList->getFirstSelected();
01598 if (!library_item) return;
01599
01600 const LLScrollListCell* library_cell = library_item->getColumn(0);
01601 const std::string& library_text = library_cell->getValue().asString();
01602
01603 self->addStep(library_text);
01604
01605 self->mDirty = TRUE;
01606 self->refresh();
01607 }
01608
01609 LLScrollListItem* LLPreviewGesture::addStep(const std::string& library_text)
01610 {
01611 LLGestureStep* step = NULL;
01612 if (!LLString::compareInsensitive(library_text.c_str(), "Animation"))
01613 {
01614 step = new LLGestureStepAnimation();
01615 }
01616 else if (!LLString::compareInsensitive(library_text.c_str(), "Sound"))
01617 {
01618 step = new LLGestureStepSound();
01619 }
01620 else if (!LLString::compareInsensitive(library_text.c_str(), "Chat"))
01621 {
01622 step = new LLGestureStepChat();
01623 }
01624 else if (!LLString::compareInsensitive(library_text.c_str(), "Wait"))
01625 {
01626 step = new LLGestureStepWait();
01627 }
01628 else
01629 {
01630 llerrs << "Unknown step type: " << library_text << llendl;;
01631 return NULL;
01632 }
01633
01634
01635 LLSD row;
01636 row["columns"][0]["value"] = step->getLabel();
01637 row["columns"][0]["font"] = "SANSSERIF_SMALL";
01638 LLScrollListItem* step_item = mStepList->addElement(row);
01639 step_item->setUserdata(step);
01640
01641
01642 mLibraryList->deselectAllItems();
01643 mStepList->deselectAllItems();
01644
01645 step_item->setSelected(TRUE);
01646
01647 return step_item;
01648 }
01649
01650
01651 void LLPreviewGesture::onClickUp(void* data)
01652 {
01653 LLPreviewGesture* self = (LLPreviewGesture*)data;
01654
01655 S32 selected_index = self->mStepList->getFirstSelectedIndex();
01656 if (selected_index > 0)
01657 {
01658 self->mStepList->swapWithPrevious(selected_index);
01659 self->mDirty = TRUE;
01660 self->refresh();
01661 }
01662 }
01663
01664
01665 void LLPreviewGesture::onClickDown(void* data)
01666 {
01667 LLPreviewGesture* self = (LLPreviewGesture*)data;
01668
01669 S32 selected_index = self->mStepList->getFirstSelectedIndex();
01670 if (selected_index < 0) return;
01671
01672 S32 count = self->mStepList->getItemCount();
01673 if (selected_index < count-1)
01674 {
01675 self->mStepList->swapWithNext(selected_index);
01676 self->mDirty = TRUE;
01677 self->refresh();
01678 }
01679 }
01680
01681
01682 void LLPreviewGesture::onClickDelete(void* data)
01683 {
01684 LLPreviewGesture* self = (LLPreviewGesture*)data;
01685
01686 LLScrollListItem* item = self->mStepList->getFirstSelected();
01687 S32 selected_index = self->mStepList->getFirstSelectedIndex();
01688 if (item && selected_index >= 0)
01689 {
01690 LLGestureStep* step = (LLGestureStep*)item->getUserdata();
01691 delete step;
01692 step = NULL;
01693
01694 self->mStepList->deleteSingleItem(selected_index);
01695
01696 self->mDirty = TRUE;
01697 self->refresh();
01698 }
01699 }
01700
01701
01702 void LLPreviewGesture::onCommitActive(LLUICtrl* ctrl, void* data)
01703 {
01704 LLPreviewGesture* self = (LLPreviewGesture*)data;
01705 if (!gGestureManager.isGestureActive(self->mItemUUID))
01706 {
01707 gGestureManager.activateGesture(self->mItemUUID);
01708 }
01709 else
01710 {
01711 gGestureManager.deactivateGesture(self->mItemUUID);
01712 }
01713
01714
01715 LLViewerInventoryItem* item = gInventory.getItem(self->mItemUUID);
01716 if (item)
01717 {
01718 gInventory.updateItem(item);
01719 gInventory.notifyObservers();
01720 }
01721
01722 self->refresh();
01723 }
01724
01725
01726 void LLPreviewGesture::onClickSave(void* data)
01727 {
01728 LLPreviewGesture* self = (LLPreviewGesture*)data;
01729 self->saveIfNeeded();
01730 }
01731
01732
01733 void LLPreviewGesture::onClickPreview(void* data)
01734 {
01735 LLPreviewGesture* self = (LLPreviewGesture*)data;
01736
01737 if (!self->mPreviewGesture)
01738 {
01739
01740 self->mPreviewGesture = self->createGesture();
01741
01742
01743 self->mPreviewGesture->mDoneCallback = onDonePreview;
01744 self->mPreviewGesture->mCallbackData = self;
01745
01746
01747 self->mPreviewBtn->setLabel(self->getString("stop_txt"));
01748
01749
01750 gGestureManager.playGesture(self->mPreviewGesture);
01751
01752 self->refresh();
01753 }
01754 else
01755 {
01756
01757 gGestureManager.stopGesture(self->mPreviewGesture);
01758
01759 self->refresh();
01760 }
01761 }
01762
01763
01764
01765 void LLPreviewGesture::onDonePreview(LLMultiGesture* gesture, void* data)
01766 {
01767 LLPreviewGesture* self = (LLPreviewGesture*)data;
01768
01769 self->mPreviewBtn->setLabel(self->getString("preview_txt"));
01770
01771 delete self->mPreviewGesture;
01772 self->mPreviewGesture = NULL;
01773
01774 self->refresh();
01775 }