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

Generated on Thu Jul 1 06:09:02 2010 for Second Life Viewer by  doxygen 1.4.7