llpreviewgesture.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include <algorithm>
00035 
00036 #include "llpreviewgesture.h"
00037 
00038 // libraries
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 // newview
00047 #include "llagent.h"            // todo: remove
00048 #include "llassetuploadresponders.h"
00049 #include "llbutton.h"
00050 #include "llcheckboxctrl.h"
00051 #include "llcombobox.h"
00052 #include "lldelayedgestureerror.h"
00053 #include "llfloatergesture.h" // for some label constants
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"             // busycount
00069 #include "llappviewer.h"                        // gVFS
00070 #include "llanimstatelabels.h"
00071 #include "llresmgr.h"
00072 
00073 
00074 // *TODO: Translate?
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 // used for getting
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 // Used for sorting
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 // static
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();   /*Flawfinder: ignore*/
00125                 if (take_focus)
00126                 {
00127                         previewp->setFocus(TRUE);
00128                 }
00129                 return previewp;
00130         }
00131 
00132         LLPreviewGesture* self = new LLPreviewGesture();
00133 
00134         // Finish internal construction
00135         self->init(item_id, object_id);
00136 
00137         // Builds and adds to gFloaterView
00138         LLUICtrlFactory::getInstance()->buildFloater(self, "floater_preview_gesture.xml");
00139         self->setTitle(title);
00140 
00141         // Move window to top-left of screen
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                 // re-add to host to update title
00153                 hostp->addFloater(self, TRUE);
00154         }
00155 
00156         // Start speculative download of sounds and animations
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         // this will call refresh when we have everything.
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                 // not sure this is necessary.
00176                 self->refresh();
00177         }
00178 
00179         if (take_focus)
00180         {
00181                 self->setFocus(TRUE);
00182         }
00183 
00184         return self;
00185 }
00186 
00187 
00188 // virtual
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 // virtual
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                         // TODO: Don't allow this if you can't transfer the sound/animation
00215 
00216                         // make a script step
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                                 // Not in user's inventory means it was in object inventory
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 // virtual
00277 BOOL LLPreviewGesture::canClose()
00278 {
00279 
00280         if(!mDirty || mForceClose)
00281         {
00282                 return TRUE;
00283         }
00284         else
00285         {
00286                 // Bring up view-modal dialog: Save changes? Yes, No, Cancel
00287                 gViewerWindow->alertXml("SaveChanges",
00288                                                                   handleSaveChangesDialog,
00289                                                                   this );
00290                 return FALSE;
00291         }
00292 }
00293 
00294 // virtual
00295 void LLPreviewGesture::onClose(bool app_quitting)
00296 {
00297         gGestureManager.stopGesture(mPreviewGesture);
00298         LLPreview::onClose(app_quitting);
00299 }
00300 
00301 // virtual
00302 void LLPreviewGesture::onUpdateSucceeded()
00303 {
00304         refresh();
00305 }
00306 
00307 // virtual
00308 void LLPreviewGesture::setMinimized(BOOL minimize)
00309 {
00310         if (minimize != isMinimized())
00311         {
00312                 LLFloater::setMinimized(minimize);
00313 
00314                 // We're being restored
00315                 if (!minimize)
00316                 {
00317                         refresh();
00318                 }
00319         }
00320 }
00321 
00322 
00323 // static
00324 void LLPreviewGesture::handleSaveChangesDialog(S32 option, void* data)
00325 {
00326         LLPreviewGesture* self = (LLPreviewGesture*)data;
00327         switch(option)
00328         {
00329         case 0:  // "Yes"
00330                 gGestureManager.stopGesture(self->mPreviewGesture);
00331                 self->mCloseAfterSave = TRUE;
00332                 onClickSave(data);
00333                 break;
00334 
00335         case 1:  // "No"
00336                 gGestureManager.stopGesture(self->mPreviewGesture);
00337                 self->mDirty = FALSE; // Force the dirty flag because user has clicked NO on confirm save dialog...
00338                 self->close();
00339                 break;
00340 
00341         case 2: // "Cancel"
00342         default:
00343                 // If we were quitting, we didn't really mean it.
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         // Userdata for all steps is a LLGestureStep we need to clean up
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         // Options
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         //edit->setKeystrokeCallback(onKeystrokeCommit);
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 //      edit->setKeystrokeCallback(onKeystrokeCommit);
00514         edit->setCommitOnFocusLost(TRUE);
00515         edit->setCommitCallback(onCommitWaitTime);
00516         edit->setCallbackUserData(this);
00517         edit->setIgnoreTab(TRUE);
00518         mWaitTimeEditor = edit;
00519 
00520         // Buttons at the bottom
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         // Populate the comboboxes
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 // TODO: Sort the legacy and non-legacy together?
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         // Add all the default (legacy) animations
00592         S32 i;
00593         for (i = 0; i < gUserAnimStatesCount; ++i)
00594         {
00595                 // Use the user-readable name
00596                 std::string label = LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName );
00597                 const LLUUID& id = gUserAnimStates[i].mID;
00598                 combo->add(label, id);
00599         }
00600 
00601         // Get all inventory items that are animations
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         // Copy into something we can sort
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         // Do the sort
00624         std::sort(animations.begin(), animations.end(), SortItemPtrsByName());
00625 
00626         // And load up the combobox
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         // Get all inventory items that are sounds
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         // Copy sounds into something we can sort
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         // Do the sort
00670         std::sort(sounds.begin(), sounds.end(), SortItemPtrsByName());
00671 
00672         // And load up the combobox
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         // Sets ID and adds to instance list
00686         setItemID(item_id);
00687         setObjectID(object_id);
00688 }
00689 
00690 
00691 void LLPreviewGesture::refresh()
00692 {
00693         // If previewing or item is incomplete, all controls are disabled
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                 //mDescEditor->setEnabled(FALSE);
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                 // Make sure preview button is enabled, so we can stop it
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         // Assume all not visible
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                 // figure out the type, show proper options, update text
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         // Can only preview if there are steps
00838         mPreviewBtn->setEnabled(step_count > 0);
00839 
00840         // And can only save if changes have been made
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         // Start with item list selected
00867         mStepList->selectFirstItem();
00868 
00869         // this is *new* content, so we are dirty
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                 // Freshly created gesture, don't need to load asset.
00883                 // Blank gesture will be fine.
00884                 initDefaultGesture();
00885                 refresh();
00886                 return;
00887         }
00888 
00889         // TODO: Based on item->getPermissions().allow*
00890         // could enable/disable UI.
00891 
00892         // Copy the UUID, because the user might close the preview
00893         // window if the download gets stalled.
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 // static
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);           /*Flawfinder: ignore*/
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                                 // Everything has been successful.  Load up the UI.
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         /*LLInventoryItem* item = getItem();
00981 
00982 
00983         
00984         if (item)
00985         {
00986                 LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
00987                 descEditor->setText(item->getDescription());
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         // Make UI steps for each gesture step
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                 // Create an enabled item with this step
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 // Helpful structure so we can look up the inventory item
01075 // after the save finishes.
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         // Copy the UI into a gesture
01105         LLMultiGesture* gesture = createGesture();
01106 
01107         // Serialize the gesture
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                 // Every save gets a new UUID.  Yup.
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                 // Upload that asset to the database
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                                 //need to disable the preview floater so item
01153                                 //isn't re-saved before new asset arrives
01154                                 //fake out refresh.
01155                                 item->setComplete(FALSE);
01156                                 refresh();                              
01157                                 item->setComplete(TRUE);
01158 
01159                                 // Saving into agent inventory
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                                 // Saving into task inventory
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                 // If this gesture is active, then we need to update the in-memory
01184                 // active map with the new pointer.
01185                 if (!delayedUpload && gGestureManager.isGestureActive(mItemUUID))
01186                 {
01187                         // gesture manager now owns the pointer
01188                         gGestureManager.replaceGesture(mItemUUID, gesture, asset_id);
01189 
01190                         // replaceGesture may deactivate other gestures so let the
01191                         // inventory know.
01192                         gInventory.notifyObservers();
01193                 }
01194                 else
01195                 {
01196                         // we're done with this gesture
01197                         delete gesture;
01198                         gesture = NULL;
01199                 }
01200 
01201                 mDirty = FALSE;
01202                 // refresh will be called when callback
01203                 // if triggered when delayedUpload
01204                 if(!delayedUpload)
01205                 {
01206                         refresh();
01207                 }
01208         }
01209 
01210         delete [] buffer;
01211         buffer = NULL;
01212 }
01213 
01214 
01215 // TODO: This is very similar to LLPreviewNotecard::onSaveComplete.
01216 // Could merge code.
01217 // static
01218 void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)
01219 {
01220         LLSaveInfo* info = (LLSaveInfo*)user_data;
01221         if (info && (status == 0))
01222         {
01223                 if(info->mObjectUUID.isNull())
01224                 {
01225                         // Saving into user inventory
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                         // Saving into in-world object inventory
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                 // Find our window and close it if requested.
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                                 // Copy UI-generated step into actual gesture step
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                                 // Copy UI-generated step into actual gesture step
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                                 // Copy UI-generated step into actual gesture step
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                                 // Copy UI-generated step into actual gesture step
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 // static
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 // static
01385 void LLPreviewGesture::onCommitSetDirty(LLUICtrl* ctrl, void* data)
01386 {
01387         LLPreviewGesture* self = (LLPreviewGesture*)data;
01388         self->mDirty = TRUE;
01389         self->refresh();
01390 }
01391 
01392 // static
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 // static
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 // static
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                         // Assign the animation name
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                         //anim_step->mFlags = 0x0;
01443 
01444                         // Update the UI label in the list
01445                         updateLabel(step_item);
01446 
01447                         self->mDirty = TRUE;
01448                         self->refresh();
01449                 }
01450         }
01451 }
01452 
01453 // static
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                                 // start
01468                                 anim_step->mFlags &= ~ANIM_FLAG_STOP;
01469                         }
01470                         else
01471                         {
01472                                 // stop
01473                                 anim_step->mFlags |= ANIM_FLAG_STOP;
01474                         }
01475                         // Update the UI label in the list
01476                         updateLabel(step_item);
01477 
01478                         self->mDirty = TRUE;
01479                         self->refresh();
01480                 }
01481         }
01482 }
01483 
01484 // static
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                         // Assign the sound name
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                         // Update the UI label in the list
01502                         updateLabel(step_item);
01503 
01504                         self->mDirty = TRUE;
01505                         self->refresh();
01506                 }
01507         }
01508 }
01509 
01510 // static
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         // Update the UI label in the list
01526         updateLabel(step_item);
01527 
01528         self->mDirty = TRUE;
01529         self->refresh();
01530 }
01531 
01532 // static
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         // Enable the input area if necessary
01559         self->mWaitTimeEditor->setEnabled(self->mWaitTimeCheck->get());
01560 
01561         // Update the UI label in the list
01562         updateLabel(step_item);
01563 
01564         self->mDirty = TRUE;
01565         self->refresh();
01566 }
01567 
01568 // static
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 // static
01585 void LLPreviewGesture::onKeystrokeCommit(LLLineEditor* caller,
01586                                                                                  void* data)
01587 {
01588         // Just commit every keystroke
01589         onCommitSetDirty(caller, data);
01590 }
01591 
01592 // static
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         // Create an enabled item with this step
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         // And move selection to the list on the right
01642         mLibraryList->deselectAllItems();
01643         mStepList->deselectAllItems();
01644 
01645         step_item->setSelected(TRUE);
01646 
01647         return step_item;
01648 }
01649 
01650 // static
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 // static
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 // static
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 // static
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         // Make sure the (active) label in the inventory gets updated.
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 // static
01726 void LLPreviewGesture::onClickSave(void* data)
01727 {
01728         LLPreviewGesture* self = (LLPreviewGesture*)data;
01729         self->saveIfNeeded();
01730 }
01731 
01732 // static
01733 void LLPreviewGesture::onClickPreview(void* data)
01734 {
01735         LLPreviewGesture* self = (LLPreviewGesture*)data;
01736 
01737         if (!self->mPreviewGesture)
01738         {
01739                 // make temporary gesture
01740                 self->mPreviewGesture = self->createGesture();
01741 
01742                 // add a callback
01743                 self->mPreviewGesture->mDoneCallback = onDonePreview;
01744                 self->mPreviewGesture->mCallbackData = self;
01745 
01746                 // set the button title
01747                 self->mPreviewBtn->setLabel(self->getString("stop_txt"));
01748 
01749                 // play it, and delete when done
01750                 gGestureManager.playGesture(self->mPreviewGesture);
01751 
01752                 self->refresh();
01753         }
01754         else
01755         {
01756                 // Will call onDonePreview() below
01757                 gGestureManager.stopGesture(self->mPreviewGesture);
01758 
01759                 self->refresh();
01760         }
01761 }
01762 
01763 
01764 // static
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 }

Generated on Fri May 16 08:33:57 2008 for SecondLife by  doxygen 1.5.5