PageRenderTime 60ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llpreviewgesture.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1760 lines | 1329 code | 270 blank | 161 comment | 154 complexity | 353b1af643af857571a8c0252dc30f35 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llpreviewgesture.cpp
  3. * @brief Editing UI for inventory-based gestures.
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llpreviewgesture.h"
  28. #include "llagent.h"
  29. #include "llanimstatelabels.h"
  30. #include "llanimationstates.h"
  31. #include "llappviewer.h" // gVFS
  32. #include "llassetuploadresponders.h"
  33. #include "llcheckboxctrl.h"
  34. #include "llcombobox.h"
  35. #include "lldatapacker.h"
  36. #include "lldelayedgestureerror.h"
  37. #include "llfloaterreg.h"
  38. #include "llgesturemgr.h"
  39. #include "llinventorydefines.h"
  40. #include "llinventoryfunctions.h"
  41. #include "llinventorymodel.h"
  42. #include "llinventorymodelbackgroundfetch.h"
  43. #include "llkeyboard.h"
  44. #include "llmultigesture.h"
  45. #include "llnotificationsutil.h"
  46. #include "llradiogroup.h"
  47. #include "llresmgr.h"
  48. #include "lltrans.h"
  49. #include "llvfile.h"
  50. #include "llviewerobjectlist.h"
  51. #include "llviewerregion.h"
  52. #include "llviewerstats.h"
  53. std::string NONE_LABEL;
  54. std::string SHIFT_LABEL;
  55. std::string CTRL_LABEL;
  56. void dialog_refresh_all();
  57. // used for getting
  58. class LLInventoryGestureAvailable : public LLInventoryCompletionObserver
  59. {
  60. public:
  61. LLInventoryGestureAvailable() {}
  62. protected:
  63. virtual void done();
  64. };
  65. void LLInventoryGestureAvailable::done()
  66. {
  67. for(uuid_vec_t::iterator it = mComplete.begin(); it != mComplete.end(); ++it)
  68. {
  69. LLPreviewGesture* preview = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", *it);
  70. if(preview)
  71. {
  72. preview->refresh();
  73. }
  74. }
  75. gInventory.removeObserver(this);
  76. delete this;
  77. }
  78. // Used for sorting
  79. struct SortItemPtrsByName
  80. {
  81. bool operator()(const LLInventoryItem* i1, const LLInventoryItem* i2)
  82. {
  83. return (LLStringUtil::compareDict(i1->getName(), i2->getName()) < 0);
  84. }
  85. };
  86. // static
  87. LLPreviewGesture* LLPreviewGesture::show(const LLUUID& item_id, const LLUUID& object_id)
  88. {
  89. LLPreviewGesture* preview = LLFloaterReg::showTypedInstance<LLPreviewGesture>("preview_gesture", LLSD(item_id), TAKE_FOCUS_YES);
  90. if (!preview)
  91. {
  92. return NULL;
  93. }
  94. preview->setObjectID(object_id);
  95. // Start speculative download of sounds and animations
  96. const LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ANIMATION);
  97. LLInventoryModelBackgroundFetch::instance().start(animation_folder_id);
  98. const LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SOUND);
  99. LLInventoryModelBackgroundFetch::instance().start(sound_folder_id);
  100. // this will call refresh when we have everything.
  101. LLViewerInventoryItem* item = (LLViewerInventoryItem*)preview->getItem();
  102. if (item && !item->isFinished())
  103. {
  104. LLInventoryGestureAvailable* observer;
  105. observer = new LLInventoryGestureAvailable();
  106. observer->watchItem(item_id);
  107. gInventory.addObserver(observer);
  108. item->fetchFromServer();
  109. }
  110. else
  111. {
  112. // not sure this is necessary.
  113. preview->refresh();
  114. }
  115. return preview;
  116. }
  117. void LLPreviewGesture::draw()
  118. {
  119. // Skip LLPreview::draw() to avoid description update
  120. LLFloater::draw();
  121. }
  122. // virtual
  123. BOOL LLPreviewGesture::handleKeyHere(KEY key, MASK mask)
  124. {
  125. if(('S' == key) && (MASK_CONTROL == (mask & MASK_CONTROL)))
  126. {
  127. saveIfNeeded();
  128. return TRUE;
  129. }
  130. return LLPreview::handleKeyHere(key, mask);
  131. }
  132. // virtual
  133. BOOL LLPreviewGesture::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
  134. EDragAndDropType cargo_type,
  135. void* cargo_data,
  136. EAcceptance* accept,
  137. std::string& tooltip_msg)
  138. {
  139. BOOL handled = TRUE;
  140. switch(cargo_type)
  141. {
  142. case DAD_ANIMATION:
  143. case DAD_SOUND:
  144. {
  145. // TODO: Don't allow this if you can't transfer the sound/animation
  146. // make a script step
  147. LLInventoryItem* item = (LLInventoryItem*)cargo_data;
  148. if (item
  149. && gInventory.getItem(item->getUUID()))
  150. {
  151. LLPermissions perm = item->getPermissions();
  152. if (!((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED))
  153. {
  154. *accept = ACCEPT_NO;
  155. if (tooltip_msg.empty())
  156. {
  157. tooltip_msg.assign("Only animations and sounds\n"
  158. "with unrestricted permissions\n"
  159. "can be added to a gesture.");
  160. }
  161. break;
  162. }
  163. else if (drop)
  164. {
  165. LLScrollListItem* line = NULL;
  166. if (cargo_type == DAD_ANIMATION)
  167. {
  168. line = addStep( STEP_ANIMATION );
  169. LLGestureStepAnimation* anim = (LLGestureStepAnimation*)line->getUserdata();
  170. anim->mAnimAssetID = item->getAssetUUID();
  171. anim->mAnimName = item->getName();
  172. }
  173. else if (cargo_type == DAD_SOUND)
  174. {
  175. line = addStep( STEP_SOUND );
  176. LLGestureStepSound* sound = (LLGestureStepSound*)line->getUserdata();
  177. sound->mSoundAssetID = item->getAssetUUID();
  178. sound->mSoundName = item->getName();
  179. }
  180. updateLabel(line);
  181. mDirty = TRUE;
  182. refresh();
  183. }
  184. *accept = ACCEPT_YES_COPY_MULTI;
  185. }
  186. else
  187. {
  188. // Not in user's inventory means it was in object inventory
  189. *accept = ACCEPT_NO;
  190. }
  191. break;
  192. }
  193. default:
  194. *accept = ACCEPT_NO;
  195. if (tooltip_msg.empty())
  196. {
  197. tooltip_msg.assign("Only animations and sounds\n"
  198. "can be added to a gesture.");
  199. }
  200. break;
  201. }
  202. return handled;
  203. }
  204. // virtual
  205. BOOL LLPreviewGesture::canClose()
  206. {
  207. if(!mDirty || mForceClose)
  208. {
  209. return TRUE;
  210. }
  211. else
  212. {
  213. // Bring up view-modal dialog: Save changes? Yes, No, Cancel
  214. LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(),
  215. boost::bind(&LLPreviewGesture::handleSaveChangesDialog, this, _1, _2) );
  216. return FALSE;
  217. }
  218. }
  219. // virtual
  220. void LLPreviewGesture::onClose(bool app_quitting)
  221. {
  222. LLGestureMgr::instance().stopGesture(mPreviewGesture);
  223. }
  224. // virtual
  225. void LLPreviewGesture::onUpdateSucceeded()
  226. {
  227. refresh();
  228. }
  229. void LLPreviewGesture::onVisibilityChange ( const LLSD& new_visibility )
  230. {
  231. if (new_visibility.asBoolean())
  232. {
  233. refresh();
  234. }
  235. }
  236. bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const LLSD& response)
  237. {
  238. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  239. switch(option)
  240. {
  241. case 0: // "Yes"
  242. LLGestureMgr::instance().stopGesture(mPreviewGesture);
  243. mCloseAfterSave = TRUE;
  244. onClickSave(this);
  245. break;
  246. case 1: // "No"
  247. LLGestureMgr::instance().stopGesture(mPreviewGesture);
  248. mDirty = FALSE; // Force the dirty flag because user has clicked NO on confirm save dialog...
  249. closeFloater();
  250. break;
  251. case 2: // "Cancel"
  252. default:
  253. // If we were quitting, we didn't really mean it.
  254. LLAppViewer::instance()->abortQuit();
  255. break;
  256. }
  257. return false;
  258. }
  259. LLPreviewGesture::LLPreviewGesture(const LLSD& key)
  260. : LLPreview(key),
  261. mTriggerEditor(NULL),
  262. mModifierCombo(NULL),
  263. mKeyCombo(NULL),
  264. mLibraryList(NULL),
  265. mAddBtn(NULL),
  266. mUpBtn(NULL),
  267. mDownBtn(NULL),
  268. mDeleteBtn(NULL),
  269. mStepList(NULL),
  270. mOptionsText(NULL),
  271. mAnimationRadio(NULL),
  272. mAnimationCombo(NULL),
  273. mSoundCombo(NULL),
  274. mChatEditor(NULL),
  275. mSaveBtn(NULL),
  276. mPreviewBtn(NULL),
  277. mPreviewGesture(NULL),
  278. mDirty(FALSE)
  279. {
  280. NONE_LABEL = LLTrans::getString("---");
  281. SHIFT_LABEL = LLTrans::getString("KBShift");
  282. CTRL_LABEL = LLTrans::getString("KBCtrl");
  283. }
  284. LLPreviewGesture::~LLPreviewGesture()
  285. {
  286. // Userdata for all steps is a LLGestureStep we need to clean up
  287. std::vector<LLScrollListItem*> data_list = mStepList->getAllData();
  288. std::vector<LLScrollListItem*>::iterator data_itor;
  289. for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor)
  290. {
  291. LLScrollListItem* item = *data_itor;
  292. LLGestureStep* step = (LLGestureStep*)item->getUserdata();
  293. delete step;
  294. step = NULL;
  295. }
  296. }
  297. BOOL LLPreviewGesture::postBuild()
  298. {
  299. setVisibleCallback(boost::bind(&LLPreviewGesture::onVisibilityChange, this, _2));
  300. LLLineEditor* edit;
  301. LLComboBox* combo;
  302. LLButton* btn;
  303. LLScrollListCtrl* list;
  304. LLTextBox* text;
  305. LLCheckBoxCtrl* check;
  306. edit = getChild<LLLineEditor>("name");
  307. edit->setKeystrokeCallback(onKeystrokeCommit, this);
  308. edit = getChild<LLLineEditor>("desc");
  309. edit->setKeystrokeCallback(onKeystrokeCommit, this);
  310. edit = getChild<LLLineEditor>("trigger_editor");
  311. edit->setKeystrokeCallback(onKeystrokeCommit, this);
  312. edit->setCommitCallback(onCommitSetDirty, this);
  313. edit->setCommitOnFocusLost(TRUE);
  314. edit->setIgnoreTab(TRUE);
  315. mTriggerEditor = edit;
  316. text = getChild<LLTextBox>("replace_text");
  317. text->setEnabled(FALSE);
  318. mReplaceText = text;
  319. edit = getChild<LLLineEditor>("replace_editor");
  320. edit->setEnabled(FALSE);
  321. edit->setKeystrokeCallback(onKeystrokeCommit, this);
  322. edit->setCommitCallback(onCommitSetDirty, this);
  323. edit->setCommitOnFocusLost(TRUE);
  324. edit->setIgnoreTab(TRUE);
  325. mReplaceEditor = edit;
  326. combo = getChild<LLComboBox>( "modifier_combo");
  327. combo->setCommitCallback(onCommitSetDirty, this);
  328. mModifierCombo = combo;
  329. combo = getChild<LLComboBox>( "key_combo");
  330. combo->setCommitCallback(onCommitSetDirty, this);
  331. mKeyCombo = combo;
  332. list = getChild<LLScrollListCtrl>("library_list");
  333. list->setCommitCallback(onCommitLibrary, this);
  334. list->setDoubleClickCallback(onClickAdd, this);
  335. mLibraryList = list;
  336. btn = getChild<LLButton>( "add_btn");
  337. btn->setClickedCallback(onClickAdd, this);
  338. btn->setEnabled(FALSE);
  339. mAddBtn = btn;
  340. btn = getChild<LLButton>( "up_btn");
  341. btn->setClickedCallback(onClickUp, this);
  342. btn->setEnabled(FALSE);
  343. mUpBtn = btn;
  344. btn = getChild<LLButton>( "down_btn");
  345. btn->setClickedCallback(onClickDown, this);
  346. btn->setEnabled(FALSE);
  347. mDownBtn = btn;
  348. btn = getChild<LLButton>( "delete_btn");
  349. btn->setClickedCallback(onClickDelete, this);
  350. btn->setEnabled(FALSE);
  351. mDeleteBtn = btn;
  352. list = getChild<LLScrollListCtrl>("step_list");
  353. list->setCommitCallback(onCommitStep, this);
  354. mStepList = list;
  355. // Options
  356. mOptionsText = getChild<LLTextBox>("options_text");
  357. combo = getChild<LLComboBox>( "animation_list");
  358. combo->setVisible(FALSE);
  359. combo->setCommitCallback(onCommitAnimation, this);
  360. mAnimationCombo = combo;
  361. LLRadioGroup* group;
  362. group = getChild<LLRadioGroup>("animation_trigger_type");
  363. group->setVisible(FALSE);
  364. group->setCommitCallback(onCommitAnimationTrigger, this);
  365. mAnimationRadio = group;
  366. combo = getChild<LLComboBox>( "sound_list");
  367. combo->setVisible(FALSE);
  368. combo->setCommitCallback(onCommitSound, this);
  369. mSoundCombo = combo;
  370. edit = getChild<LLLineEditor>("chat_editor");
  371. edit->setVisible(FALSE);
  372. edit->setCommitCallback(onCommitChat, this);
  373. //edit->setKeystrokeCallback(onKeystrokeCommit, this);
  374. edit->setCommitOnFocusLost(TRUE);
  375. edit->setIgnoreTab(TRUE);
  376. mChatEditor = edit;
  377. check = getChild<LLCheckBoxCtrl>( "wait_anim_check");
  378. check->setVisible(FALSE);
  379. check->setCommitCallback(onCommitWait, this);
  380. mWaitAnimCheck = check;
  381. check = getChild<LLCheckBoxCtrl>( "wait_time_check");
  382. check->setVisible(FALSE);
  383. check->setCommitCallback(onCommitWait, this);
  384. mWaitTimeCheck = check;
  385. edit = getChild<LLLineEditor>("wait_time_editor");
  386. edit->setEnabled(FALSE);
  387. edit->setVisible(FALSE);
  388. edit->setPrevalidate(LLTextValidate::validateFloat);
  389. // edit->setKeystrokeCallback(onKeystrokeCommit, this);
  390. edit->setCommitOnFocusLost(TRUE);
  391. edit->setCommitCallback(onCommitWaitTime, this);
  392. edit->setIgnoreTab(TRUE);
  393. mWaitTimeEditor = edit;
  394. // Buttons at the bottom
  395. check = getChild<LLCheckBoxCtrl>( "active_check");
  396. check->setCommitCallback(onCommitActive, this);
  397. mActiveCheck = check;
  398. btn = getChild<LLButton>( "save_btn");
  399. btn->setClickedCallback(onClickSave, this);
  400. mSaveBtn = btn;
  401. btn = getChild<LLButton>( "preview_btn");
  402. btn->setClickedCallback(onClickPreview, this);
  403. mPreviewBtn = btn;
  404. // Populate the comboboxes
  405. addModifiers();
  406. addKeys();
  407. addAnimations();
  408. addSounds();
  409. const LLInventoryItem* item = getItem();
  410. if (item)
  411. {
  412. getChild<LLUICtrl>("desc")->setValue(item->getDescription());
  413. getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
  414. getChild<LLUICtrl>("name")->setValue(item->getName());
  415. getChild<LLLineEditor>("name")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
  416. }
  417. return LLPreview::postBuild();
  418. }
  419. void LLPreviewGesture::addModifiers()
  420. {
  421. LLComboBox* combo = mModifierCombo;
  422. combo->add( NONE_LABEL, ADD_BOTTOM );
  423. combo->add( SHIFT_LABEL, ADD_BOTTOM );
  424. combo->add( CTRL_LABEL, ADD_BOTTOM );
  425. combo->setCurrentByIndex(0);
  426. }
  427. void LLPreviewGesture::addKeys()
  428. {
  429. LLComboBox* combo = mKeyCombo;
  430. combo->add( NONE_LABEL );
  431. for (KEY key = KEY_F2; key <= KEY_F12; key++)
  432. {
  433. combo->add( LLKeyboard::stringFromKey(key), ADD_BOTTOM );
  434. }
  435. combo->setCurrentByIndex(0);
  436. }
  437. // TODO: Sort the legacy and non-legacy together?
  438. void LLPreviewGesture::addAnimations()
  439. {
  440. LLComboBox* combo = mAnimationCombo;
  441. combo->removeall();
  442. std::string none_text = getString("none_text");
  443. combo->add(none_text, LLUUID::null);
  444. // Add all the default (legacy) animations
  445. S32 i;
  446. for (i = 0; i < gUserAnimStatesCount; ++i)
  447. {
  448. // Use the user-readable name
  449. std::string label = LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName );
  450. const LLUUID& id = gUserAnimStates[i].mID;
  451. combo->add(label, id);
  452. }
  453. // Get all inventory items that are animations
  454. LLViewerInventoryCategory::cat_array_t cats;
  455. LLViewerInventoryItem::item_array_t items;
  456. LLIsTypeWithPermissions is_copyable_animation(LLAssetType::AT_ANIMATION,
  457. PERM_ITEM_UNRESTRICTED,
  458. gAgent.getID(),
  459. gAgent.getGroupID());
  460. gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
  461. cats,
  462. items,
  463. LLInventoryModel::EXCLUDE_TRASH,
  464. is_copyable_animation);
  465. // Copy into something we can sort
  466. std::vector<LLInventoryItem*> animations;
  467. S32 count = items.count();
  468. for(i = 0; i < count; ++i)
  469. {
  470. animations.push_back( items.get(i) );
  471. }
  472. // Do the sort
  473. std::sort(animations.begin(), animations.end(), SortItemPtrsByName());
  474. // And load up the combobox
  475. std::vector<LLInventoryItem*>::iterator it;
  476. for (it = animations.begin(); it != animations.end(); ++it)
  477. {
  478. LLInventoryItem* item = *it;
  479. combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM);
  480. }
  481. }
  482. void LLPreviewGesture::addSounds()
  483. {
  484. LLComboBox* combo = mSoundCombo;
  485. combo->removeall();
  486. std::string none_text = getString("none_text");
  487. combo->add(none_text, LLUUID::null);
  488. // Get all inventory items that are sounds
  489. LLViewerInventoryCategory::cat_array_t cats;
  490. LLViewerInventoryItem::item_array_t items;
  491. LLIsTypeWithPermissions is_copyable_sound(LLAssetType::AT_SOUND,
  492. PERM_ITEM_UNRESTRICTED,
  493. gAgent.getID(),
  494. gAgent.getGroupID());
  495. gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
  496. cats,
  497. items,
  498. LLInventoryModel::EXCLUDE_TRASH,
  499. is_copyable_sound);
  500. // Copy sounds into something we can sort
  501. std::vector<LLInventoryItem*> sounds;
  502. S32 i;
  503. S32 count = items.count();
  504. for(i = 0; i < count; ++i)
  505. {
  506. sounds.push_back( items.get(i) );
  507. }
  508. // Do the sort
  509. std::sort(sounds.begin(), sounds.end(), SortItemPtrsByName());
  510. // And load up the combobox
  511. std::vector<LLInventoryItem*>::iterator it;
  512. for (it = sounds.begin(); it != sounds.end(); ++it)
  513. {
  514. LLInventoryItem* item = *it;
  515. combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM);
  516. }
  517. }
  518. void LLPreviewGesture::refresh()
  519. {
  520. LLPreview::refresh();
  521. // If previewing or item is incomplete, all controls are disabled
  522. LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
  523. bool is_complete = (item && item->isFinished()) ? true : false;
  524. if (mPreviewGesture || !is_complete)
  525. {
  526. getChildView("desc")->setEnabled(FALSE);
  527. //mDescEditor->setEnabled(FALSE);
  528. mTriggerEditor->setEnabled(FALSE);
  529. mReplaceText->setEnabled(FALSE);
  530. mReplaceEditor->setEnabled(FALSE);
  531. mModifierCombo->setEnabled(FALSE);
  532. mKeyCombo->setEnabled(FALSE);
  533. mLibraryList->setEnabled(FALSE);
  534. mAddBtn->setEnabled(FALSE);
  535. mUpBtn->setEnabled(FALSE);
  536. mDownBtn->setEnabled(FALSE);
  537. mDeleteBtn->setEnabled(FALSE);
  538. mStepList->setEnabled(FALSE);
  539. mOptionsText->setEnabled(FALSE);
  540. mAnimationCombo->setEnabled(FALSE);
  541. mAnimationRadio->setEnabled(FALSE);
  542. mSoundCombo->setEnabled(FALSE);
  543. mChatEditor->setEnabled(FALSE);
  544. mWaitAnimCheck->setEnabled(FALSE);
  545. mWaitTimeCheck->setEnabled(FALSE);
  546. mWaitTimeEditor->setEnabled(FALSE);
  547. mActiveCheck->setEnabled(FALSE);
  548. mSaveBtn->setEnabled(FALSE);
  549. // Make sure preview button is enabled, so we can stop it
  550. mPreviewBtn->setEnabled(TRUE);
  551. return;
  552. }
  553. BOOL modifiable = item->getPermissions().allowModifyBy(gAgent.getID());
  554. getChildView("desc")->setEnabled(modifiable);
  555. mTriggerEditor->setEnabled(TRUE);
  556. mLibraryList->setEnabled(modifiable);
  557. mStepList->setEnabled(modifiable);
  558. mOptionsText->setEnabled(modifiable);
  559. mAnimationCombo->setEnabled(modifiable);
  560. mAnimationRadio->setEnabled(modifiable);
  561. mSoundCombo->setEnabled(modifiable);
  562. mChatEditor->setEnabled(modifiable);
  563. mWaitAnimCheck->setEnabled(modifiable);
  564. mWaitTimeCheck->setEnabled(modifiable);
  565. mWaitTimeEditor->setEnabled(modifiable);
  566. mActiveCheck->setEnabled(TRUE);
  567. const std::string& trigger = mTriggerEditor->getText();
  568. BOOL have_trigger = !trigger.empty();
  569. const std::string& replace = mReplaceEditor->getText();
  570. BOOL have_replace = !replace.empty();
  571. LLScrollListItem* library_item = mLibraryList->getFirstSelected();
  572. BOOL have_library = (library_item != NULL);
  573. LLScrollListItem* step_item = mStepList->getFirstSelected();
  574. S32 step_index = mStepList->getFirstSelectedIndex();
  575. S32 step_count = mStepList->getItemCount();
  576. BOOL have_step = (step_item != NULL);
  577. mReplaceText->setEnabled(have_trigger || have_replace);
  578. mReplaceEditor->setEnabled(have_trigger || have_replace);
  579. mModifierCombo->setEnabled(TRUE);
  580. mKeyCombo->setEnabled(TRUE);
  581. mAddBtn->setEnabled(modifiable && have_library);
  582. mUpBtn->setEnabled(modifiable && have_step && step_index > 0);
  583. mDownBtn->setEnabled(modifiable && have_step && step_index < step_count-1);
  584. mDeleteBtn->setEnabled(modifiable && have_step);
  585. // Assume all not visible
  586. mAnimationCombo->setVisible(FALSE);
  587. mAnimationRadio->setVisible(FALSE);
  588. mSoundCombo->setVisible(FALSE);
  589. mChatEditor->setVisible(FALSE);
  590. mWaitAnimCheck->setVisible(FALSE);
  591. mWaitTimeCheck->setVisible(FALSE);
  592. mWaitTimeEditor->setVisible(FALSE);
  593. std::string optionstext;
  594. if (have_step)
  595. {
  596. // figure out the type, show proper options, update text
  597. LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
  598. EStepType type = step->getType();
  599. switch(type)
  600. {
  601. case STEP_ANIMATION:
  602. {
  603. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  604. optionstext = getString("step_anim");
  605. mAnimationCombo->setVisible(TRUE);
  606. mAnimationRadio->setVisible(TRUE);
  607. mAnimationRadio->setSelectedIndex((anim_step->mFlags & ANIM_FLAG_STOP) ? 1 : 0);
  608. mAnimationCombo->setCurrentByID(anim_step->mAnimAssetID);
  609. break;
  610. }
  611. case STEP_SOUND:
  612. {
  613. LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
  614. optionstext = getString("step_sound");
  615. mSoundCombo->setVisible(TRUE);
  616. mSoundCombo->setCurrentByID(sound_step->mSoundAssetID);
  617. break;
  618. }
  619. case STEP_CHAT:
  620. {
  621. LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
  622. optionstext = getString("step_chat");
  623. mChatEditor->setVisible(TRUE);
  624. mChatEditor->setText(chat_step->mChatText);
  625. break;
  626. }
  627. case STEP_WAIT:
  628. {
  629. LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
  630. optionstext = getString("step_wait");
  631. mWaitAnimCheck->setVisible(TRUE);
  632. mWaitAnimCheck->set(wait_step->mFlags & WAIT_FLAG_ALL_ANIM);
  633. mWaitTimeCheck->setVisible(TRUE);
  634. mWaitTimeCheck->set(wait_step->mFlags & WAIT_FLAG_TIME);
  635. mWaitTimeEditor->setVisible(TRUE);
  636. std::string buffer = llformat("%.1f", (double)wait_step->mWaitSeconds);
  637. mWaitTimeEditor->setText(buffer);
  638. break;
  639. }
  640. default:
  641. break;
  642. }
  643. }
  644. mOptionsText->setText(optionstext);
  645. BOOL active = LLGestureMgr::instance().isGestureActive(mItemUUID);
  646. mActiveCheck->set(active);
  647. // Can only preview if there are steps
  648. mPreviewBtn->setEnabled(step_count > 0);
  649. // And can only save if changes have been made
  650. mSaveBtn->setEnabled(mDirty);
  651. addAnimations();
  652. addSounds();
  653. }
  654. void LLPreviewGesture::initDefaultGesture()
  655. {
  656. LLScrollListItem* item;
  657. item = addStep( STEP_ANIMATION );
  658. LLGestureStepAnimation* anim = (LLGestureStepAnimation*)item->getUserdata();
  659. anim->mAnimAssetID = ANIM_AGENT_HELLO;
  660. anim->mAnimName = LLTrans::getString("Wave");
  661. updateLabel(item);
  662. item = addStep( STEP_WAIT );
  663. LLGestureStepWait* wait = (LLGestureStepWait*)item->getUserdata();
  664. wait->mFlags = WAIT_FLAG_ALL_ANIM;
  665. updateLabel(item);
  666. item = addStep( STEP_CHAT );
  667. LLGestureStepChat* chat_step = (LLGestureStepChat*)item->getUserdata();
  668. chat_step->mChatText = LLTrans::getString("HelloAvatar");
  669. updateLabel(item);
  670. // Start with item list selected
  671. mStepList->selectFirstItem();
  672. // this is *new* content, so we are dirty
  673. mDirty = TRUE;
  674. }
  675. void LLPreviewGesture::loadAsset()
  676. {
  677. const LLInventoryItem* item = getItem();
  678. if (!item)
  679. {
  680. // Don't set asset status here; we may not have set the item id yet
  681. // (e.g. when this gets called initially)
  682. //mAssetStatus = PREVIEW_ASSET_ERROR;
  683. return;
  684. }
  685. LLUUID asset_id = item->getAssetUUID();
  686. if (asset_id.isNull())
  687. {
  688. // Freshly created gesture, don't need to load asset.
  689. // Blank gesture will be fine.
  690. initDefaultGesture();
  691. refresh();
  692. mAssetStatus = PREVIEW_ASSET_LOADED;
  693. return;
  694. }
  695. // TODO: Based on item->getPermissions().allow*
  696. // could enable/disable UI.
  697. // Copy the UUID, because the user might close the preview
  698. // window if the download gets stalled.
  699. LLUUID* item_idp = new LLUUID(mItemUUID);
  700. const BOOL high_priority = TRUE;
  701. gAssetStorage->getAssetData(asset_id,
  702. LLAssetType::AT_GESTURE,
  703. onLoadComplete,
  704. (void**)item_idp,
  705. high_priority);
  706. mAssetStatus = PREVIEW_ASSET_LOADING;
  707. }
  708. // static
  709. void LLPreviewGesture::onLoadComplete(LLVFS *vfs,
  710. const LLUUID& asset_uuid,
  711. LLAssetType::EType type,
  712. void* user_data, S32 status, LLExtStat ext_status)
  713. {
  714. LLUUID* item_idp = (LLUUID*)user_data;
  715. LLPreviewGesture* self = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", *item_idp);
  716. if (self)
  717. {
  718. if (0 == status)
  719. {
  720. LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
  721. S32 size = file.getSize();
  722. std::vector<char> buffer(size+1);
  723. file.read((U8*)&buffer[0], size);
  724. buffer[size] = '\0';
  725. LLMultiGesture* gesture = new LLMultiGesture();
  726. LLDataPackerAsciiBuffer dp(&buffer[0], size+1);
  727. BOOL ok = gesture->deserialize(dp);
  728. if (ok)
  729. {
  730. // Everything has been successful. Load up the UI.
  731. self->loadUIFromGesture(gesture);
  732. self->mStepList->selectFirstItem();
  733. self->mDirty = FALSE;
  734. self->refresh();
  735. self->refreshFromItem(); // to update description and title
  736. }
  737. else
  738. {
  739. llwarns << "Unable to load gesture" << llendl;
  740. }
  741. delete gesture;
  742. gesture = NULL;
  743. self->mAssetStatus = PREVIEW_ASSET_LOADED;
  744. }
  745. else
  746. {
  747. LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
  748. if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
  749. LL_ERR_FILE_EMPTY == status)
  750. {
  751. LLDelayedGestureError::gestureMissing( *item_idp );
  752. }
  753. else
  754. {
  755. LLDelayedGestureError::gestureFailedToLoad( *item_idp );
  756. }
  757. llwarns << "Problem loading gesture: " << status << llendl;
  758. self->mAssetStatus = PREVIEW_ASSET_ERROR;
  759. }
  760. }
  761. delete item_idp;
  762. item_idp = NULL;
  763. }
  764. void LLPreviewGesture::loadUIFromGesture(LLMultiGesture* gesture)
  765. {
  766. /*LLInventoryItem* item = getItem();
  767. if (item)
  768. {
  769. LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
  770. descEditor->setText(item->getDescription());
  771. }*/
  772. mTriggerEditor->setText(gesture->mTrigger);
  773. mReplaceEditor->setText(gesture->mReplaceText);
  774. switch (gesture->mMask)
  775. {
  776. default:
  777. case MASK_NONE:
  778. mModifierCombo->setSimple( NONE_LABEL );
  779. break;
  780. case MASK_SHIFT:
  781. mModifierCombo->setSimple( SHIFT_LABEL );
  782. break;
  783. case MASK_CONTROL:
  784. mModifierCombo->setSimple( CTRL_LABEL );
  785. break;
  786. }
  787. mKeyCombo->setCurrentByIndex(0);
  788. if (gesture->mKey != KEY_NONE)
  789. {
  790. mKeyCombo->setSimple(LLKeyboard::stringFromKey(gesture->mKey));
  791. }
  792. // Make UI steps for each gesture step
  793. S32 i;
  794. S32 count = gesture->mSteps.size();
  795. for (i = 0; i < count; ++i)
  796. {
  797. LLGestureStep* step = gesture->mSteps[i];
  798. LLGestureStep* new_step = NULL;
  799. switch(step->getType())
  800. {
  801. case STEP_ANIMATION:
  802. {
  803. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  804. LLGestureStepAnimation* new_anim_step =
  805. new LLGestureStepAnimation(*anim_step);
  806. new_step = new_anim_step;
  807. break;
  808. }
  809. case STEP_SOUND:
  810. {
  811. LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
  812. LLGestureStepSound* new_sound_step =
  813. new LLGestureStepSound(*sound_step);
  814. new_step = new_sound_step;
  815. break;
  816. }
  817. case STEP_CHAT:
  818. {
  819. LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
  820. LLGestureStepChat* new_chat_step =
  821. new LLGestureStepChat(*chat_step);
  822. new_step = new_chat_step;
  823. break;
  824. }
  825. case STEP_WAIT:
  826. {
  827. LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
  828. LLGestureStepWait* new_wait_step =
  829. new LLGestureStepWait(*wait_step);
  830. new_step = new_wait_step;
  831. break;
  832. }
  833. default:
  834. {
  835. break;
  836. }
  837. }
  838. if (!new_step) continue;
  839. // Create an enabled item with this step
  840. LLSD row;
  841. row["columns"][0]["value"] = getLabel( new_step->getLabel());
  842. row["columns"][0]["font"] = "SANSSERIF_SMALL";
  843. LLScrollListItem* item = mStepList->addElement(row);
  844. item->setUserdata(new_step);
  845. }
  846. }
  847. // Helpful structure so we can look up the inventory item
  848. // after the save finishes.
  849. struct LLSaveInfo
  850. {
  851. LLSaveInfo(const LLUUID& item_id, const LLUUID& object_id, const std::string& desc,
  852. const LLTransactionID tid)
  853. : mItemUUID(item_id), mObjectUUID(object_id), mDesc(desc), mTransactionID(tid)
  854. {
  855. }
  856. LLUUID mItemUUID;
  857. LLUUID mObjectUUID;
  858. std::string mDesc;
  859. LLTransactionID mTransactionID;
  860. };
  861. void LLPreviewGesture::saveIfNeeded()
  862. {
  863. if (!gAssetStorage)
  864. {
  865. llwarns << "Can't save gesture, no asset storage system." << llendl;
  866. return;
  867. }
  868. if (!mDirty)
  869. {
  870. return;
  871. }
  872. // Copy the UI into a gesture
  873. LLMultiGesture* gesture = createGesture();
  874. // Serialize the gesture
  875. S32 max_size = gesture->getMaxSerialSize();
  876. char* buffer = new char[max_size];
  877. LLDataPackerAsciiBuffer dp(buffer, max_size);
  878. BOOL ok = gesture->serialize(dp);
  879. if (dp.getCurrentSize() > 1000)
  880. {
  881. LLNotificationsUtil::add("GestureSaveFailedTooManySteps");
  882. delete gesture;
  883. gesture = NULL;
  884. }
  885. else if (!ok)
  886. {
  887. LLNotificationsUtil::add("GestureSaveFailedTryAgain");
  888. delete gesture;
  889. gesture = NULL;
  890. }
  891. else
  892. {
  893. LLPreview::onCommit();
  894. // Every save gets a new UUID. Yup.
  895. LLTransactionID tid;
  896. LLAssetID asset_id;
  897. tid.generate();
  898. asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
  899. LLVFile file(gVFS, asset_id, LLAssetType::AT_GESTURE, LLVFile::APPEND);
  900. S32 size = dp.getCurrentSize();
  901. file.setMaxSize(size);
  902. file.write((U8*)buffer, size);
  903. BOOL delayedUpload = FALSE;
  904. // Upload that asset to the database
  905. LLViewerInventoryItem* item = (LLViewerInventoryItem*) getItem();
  906. if (item)
  907. {
  908. std::string agent_url = gAgent.getRegion()->getCapability("UpdateGestureAgentInventory");
  909. std::string task_url = gAgent.getRegion()->getCapability("UpdateGestureTaskInventory");
  910. if (mObjectUUID.isNull() && !agent_url.empty())
  911. {
  912. //need to disable the preview floater so item
  913. //isn't re-saved before new asset arrives
  914. //fake out refresh.
  915. item->setComplete(FALSE);
  916. refresh();
  917. item->setComplete(TRUE);
  918. // Saving into agent inventory
  919. LLSD body;
  920. body["item_id"] = mItemUUID;
  921. LLHTTPClient::post(agent_url, body,
  922. new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE));
  923. delayedUpload = TRUE;
  924. }
  925. else if (!mObjectUUID.isNull() && !task_url.empty())
  926. {
  927. // Saving into task inventory
  928. LLSD body;
  929. body["task_id"] = mObjectUUID;
  930. body["item_id"] = mItemUUID;
  931. LLHTTPClient::post(task_url, body,
  932. new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE));
  933. }
  934. else if (gAssetStorage)
  935. {
  936. LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
  937. LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid);
  938. gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, FALSE);
  939. }
  940. }
  941. // If this gesture is active, then we need to update the in-memory
  942. // active map with the new pointer.
  943. if (!delayedUpload && LLGestureMgr::instance().isGestureActive(mItemUUID))
  944. {
  945. // gesture manager now owns the pointer
  946. LLGestureMgr::instance().replaceGesture(mItemUUID, gesture, asset_id);
  947. // replaceGesture may deactivate other gestures so let the
  948. // inventory know.
  949. gInventory.notifyObservers();
  950. }
  951. else
  952. {
  953. // we're done with this gesture
  954. delete gesture;
  955. gesture = NULL;
  956. }
  957. mDirty = FALSE;
  958. // refresh will be called when callback
  959. // if triggered when delayedUpload
  960. if(!delayedUpload)
  961. {
  962. refresh();
  963. }
  964. }
  965. delete [] buffer;
  966. buffer = NULL;
  967. }
  968. // TODO: This is very similar to LLPreviewNotecard::onSaveComplete.
  969. // Could merge code.
  970. // static
  971. void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)
  972. {
  973. LLSaveInfo* info = (LLSaveInfo*)user_data;
  974. if (info && (status == 0))
  975. {
  976. if(info->mObjectUUID.isNull())
  977. {
  978. // Saving into user inventory
  979. LLViewerInventoryItem* item;
  980. item = (LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID);
  981. if(item)
  982. {
  983. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  984. new_item->setDescription(info->mDesc);
  985. new_item->setTransactionID(info->mTransactionID);
  986. new_item->setAssetUUID(asset_uuid);
  987. new_item->updateServer(FALSE);
  988. gInventory.updateItem(new_item);
  989. gInventory.notifyObservers();
  990. }
  991. else
  992. {
  993. llwarns << "Inventory item for gesture " << info->mItemUUID
  994. << " is no longer in agent inventory." << llendl;
  995. }
  996. }
  997. else
  998. {
  999. // Saving into in-world object inventory
  1000. LLViewerObject* object = gObjectList.findObject(info->mObjectUUID);
  1001. LLViewerInventoryItem* item = NULL;
  1002. if(object)
  1003. {
  1004. item = (LLViewerInventoryItem*)object->getInventoryObject(info->mItemUUID);
  1005. }
  1006. if(object && item)
  1007. {
  1008. item->setDescription(info->mDesc);
  1009. item->setAssetUUID(asset_uuid);
  1010. item->setTransactionID(info->mTransactionID);
  1011. object->updateInventory(item, TASK_INVENTORY_ITEM_KEY, false);
  1012. dialog_refresh_all();
  1013. }
  1014. else
  1015. {
  1016. LLNotificationsUtil::add("GestureSaveFailedObjectNotFound");
  1017. }
  1018. }
  1019. // Find our window and close it if requested.
  1020. LLPreviewGesture* previewp = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", info->mItemUUID);
  1021. if (previewp && previewp->mCloseAfterSave)
  1022. {
  1023. previewp->closeFloater();
  1024. }
  1025. }
  1026. else
  1027. {
  1028. llwarns << "Problem saving gesture: " << status << llendl;
  1029. LLSD args;
  1030. args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
  1031. LLNotificationsUtil::add("GestureSaveFailedReason", args);
  1032. }
  1033. delete info;
  1034. info = NULL;
  1035. }
  1036. LLMultiGesture* LLPreviewGesture::createGesture()
  1037. {
  1038. LLMultiGesture* gesture = new LLMultiGesture();
  1039. gesture->mTrigger = mTriggerEditor->getText();
  1040. gesture->mReplaceText = mReplaceEditor->getText();
  1041. const std::string& modifier = mModifierCombo->getSimple();
  1042. if (modifier == CTRL_LABEL)
  1043. {
  1044. gesture->mMask = MASK_CONTROL;
  1045. }
  1046. else if (modifier == SHIFT_LABEL)
  1047. {
  1048. gesture->mMask = MASK_SHIFT;
  1049. }
  1050. else
  1051. {
  1052. gesture->mMask = MASK_NONE;
  1053. }
  1054. if (mKeyCombo->getCurrentIndex() == 0)
  1055. {
  1056. gesture->mKey = KEY_NONE;
  1057. }
  1058. else
  1059. {
  1060. const std::string& key_string = mKeyCombo->getSimple();
  1061. LLKeyboard::keyFromString(key_string, &(gesture->mKey));
  1062. }
  1063. std::vector<LLScrollListItem*> data_list = mStepList->getAllData();
  1064. std::vector<LLScrollListItem*>::iterator data_itor;
  1065. for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor)
  1066. {
  1067. LLScrollListItem* item = *data_itor;
  1068. LLGestureStep* step = (LLGestureStep*)item->getUserdata();
  1069. switch(step->getType())
  1070. {
  1071. case STEP_ANIMATION:
  1072. {
  1073. // Copy UI-generated step into actual gesture step
  1074. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  1075. LLGestureStepAnimation* new_anim_step =
  1076. new LLGestureStepAnimation(*anim_step);
  1077. gesture->mSteps.push_back(new_anim_step);
  1078. break;
  1079. }
  1080. case STEP_SOUND:
  1081. {
  1082. // Copy UI-generated step into actual gesture step
  1083. LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
  1084. LLGestureStepSound* new_sound_step =
  1085. new LLGestureStepSound(*sound_step);
  1086. gesture->mSteps.push_back(new_sound_step);
  1087. break;
  1088. }
  1089. case STEP_CHAT:
  1090. {
  1091. // Copy UI-generated step into actual gesture step
  1092. LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
  1093. LLGestureStepChat* new_chat_step =
  1094. new LLGestureStepChat(*chat_step);
  1095. gesture->mSteps.push_back(new_chat_step);
  1096. break;
  1097. }
  1098. case STEP_WAIT:
  1099. {
  1100. // Copy UI-generated step into actual gesture step
  1101. LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
  1102. LLGestureStepWait* new_wait_step =
  1103. new LLGestureStepWait(*wait_step);
  1104. gesture->mSteps.push_back(new_wait_step);
  1105. break;
  1106. }
  1107. default:
  1108. {
  1109. break;
  1110. }
  1111. }
  1112. }
  1113. return gesture;
  1114. }
  1115. // static
  1116. void LLPreviewGesture::updateLabel(LLScrollListItem* item)
  1117. {
  1118. LLGestureStep* step = (LLGestureStep*)item->getUserdata();
  1119. LLScrollListCell* cell = item->getColumn(0);
  1120. LLScrollListText* text_cell = (LLScrollListText*)cell;
  1121. std::string label = getLabel( step->getLabel());
  1122. text_cell->setText(label);
  1123. }
  1124. // static
  1125. void LLPreviewGesture::onCommitSetDirty(LLUICtrl* ctrl, void* data)
  1126. {
  1127. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1128. self->mDirty = TRUE;
  1129. self->refresh();
  1130. }
  1131. // static
  1132. void LLPreviewGesture::onCommitLibrary(LLUICtrl* ctrl, void* data)
  1133. {
  1134. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1135. LLScrollListItem* library_item = self->mLibraryList->getFirstSelected();
  1136. if (library_item)
  1137. {
  1138. self->mStepList->deselectAllItems();
  1139. self->refresh();
  1140. }
  1141. }
  1142. // static
  1143. void LLPreviewGesture::onCommitStep(LLUICtrl* ctrl, void* data)
  1144. {
  1145. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1146. LLScrollListItem* step_item = self->mStepList->getFirstSelected();
  1147. if (!step_item) return;
  1148. self->mLibraryList->deselectAllItems();
  1149. self->refresh();
  1150. }
  1151. // static
  1152. void LLPreviewGesture::onCommitAnimation(LLUICtrl* ctrl, void* data)
  1153. {
  1154. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1155. LLScrollListItem* step_item = self->mStepList->getFirstSelected();
  1156. if (step_item)
  1157. {
  1158. LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
  1159. if (step->getType() == STEP_ANIMATION)
  1160. {
  1161. // Assign the animation name
  1162. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  1163. if (self->mAnimationCombo->getCurrentIndex() == 0)
  1164. {
  1165. anim_step->mAnimName.clear();
  1166. anim_step->mAnimAssetID.setNull();
  1167. }
  1168. else
  1169. {
  1170. anim_step->mAnimName = self->mAnimationCombo->getSimple();
  1171. anim_step->mAnimAssetID = self->mAnimationCombo->getCurrentID();
  1172. }
  1173. //anim_step->mFlags = 0x0;
  1174. // Update the UI label in the list
  1175. updateLabel(step_item);
  1176. self->mDirty = TRUE;
  1177. self->refresh();
  1178. }
  1179. }
  1180. }
  1181. // static
  1182. void LLPreviewGesture::onCommitAnimationTrigger(LLUICtrl* ctrl, void *data)
  1183. {
  1184. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1185. LLScrollListItem* step_item = self->mStepList->getFirstSelected();
  1186. if (step_item)
  1187. {
  1188. LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
  1189. if (step->getType() == STEP_ANIMATION)
  1190. {
  1191. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  1192. if (self->mAnimationRadio->getSelectedIndex() == 0)
  1193. {
  1194. // start
  1195. anim_step->mFlags &= ~ANIM_FLAG_STOP;
  1196. }
  1197. else
  1198. {
  1199. // stop
  1200. anim_step->mFlags |= ANIM_FLAG_STOP;
  1201. }
  1202. // Update the UI label in the list
  1203. updateLabel(step_item);
  1204. self->mDirty = TRUE;
  1205. self->refresh();
  1206. }
  1207. }
  1208. }
  1209. // static
  1210. void LLPreviewGesture::onCommitSound(LLUICtrl* ctrl, void* data)
  1211. {
  1212. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1213. LLScrollListItem* step_item = self->mStepList->getFirstSelected();
  1214. if (step_item)
  1215. {
  1216. LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
  1217. if (step->getType() == STEP_SOUND)
  1218. {
  1219. // Assign the sound name
  1220. LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
  1221. sound_step->mSoundName = self->mSoundCombo->getSimple();
  1222. sound_step->mSoundAssetID = self->mSoundCombo->getCurrentID();
  1223. sound_step->mFlags = 0x0;
  1224. // Update the UI label in the list
  1225. updateLabel(step_item);
  1226. self->mDirty = TRUE;
  1227. self->refresh();
  1228. }
  1229. }
  1230. }
  1231. // static
  1232. void LLPreviewGesture::onCommitChat(LLUICtrl* ctrl, void* data)
  1233. {
  1234. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1235. LLScrollListItem* step_item = self->mStepList->getFirstSelected();
  1236. if (!step_item) return;
  1237. LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
  1238. if (step->getType() != STEP_CHAT) return;
  1239. LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
  1240. chat_step->mChatText = self->mChatEditor->getText();
  1241. chat_step->mFlags = 0x0;
  1242. // Update the UI label in the list
  1243. updateLabel(step_item);
  1244. self->mDirty = TRUE;
  1245. self->refresh();
  1246. }
  1247. // static
  1248. void LLPreviewGesture::onCommitWait(LLUICtrl* ctrl, void* data)
  1249. {
  1250. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1251. LLScrollListItem* step_item = self->mStepList->getFirstSelected();
  1252. if (!step_item) return;
  1253. LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
  1254. if (step->getType() != STEP_WAIT) return;
  1255. LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
  1256. U32 flags = 0x0;
  1257. if (self->mWaitAnimCheck->get()) flags |= WAIT_FLAG_ALL_ANIM;
  1258. if (self->mWaitTimeCheck->get()) flags |= WAIT_FLAG_TIME;
  1259. wait_step->mFlags = flags;
  1260. {
  1261. LLLocale locale(LLLocale::USER_LOCALE);
  1262. F32 wait_seconds = (F32)atof(self->mWaitTimeEditor->getText().c_str());
  1263. if (wait_seconds < 0.f) wait_seconds = 0.f;
  1264. if (wait_seconds > 3600.f) wait_seconds = 3600.f;
  1265. wait_step->mWaitSeconds = wait_seconds;
  1266. }
  1267. // Enable the input area if necessary
  1268. self->mWaitTimeEditor->setEnabled(self->mWaitTimeCheck->get());
  1269. // Update the UI label in the list
  1270. updateLabel(step_item);
  1271. self->mDirty = TRUE;
  1272. self->refresh();
  1273. }
  1274. // static
  1275. void LLPreviewGesture::onCommitWaitTime(LLUICtrl* ctrl, void* data)
  1276. {
  1277. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1278. LLScrollListItem* step_item = self->mStepList->getFirstSelected();
  1279. if (!step_item) return;
  1280. LLGestureStep* step = (LLGestureStep*)step_item->getUserdata();
  1281. if (step->getType() != STEP_WAIT) return;
  1282. self->mWaitTimeCheck->set(TRUE);
  1283. onCommitWait(ctrl, data);
  1284. }
  1285. // static
  1286. void LLPreviewGesture::onKeystrokeCommit(LLLineEditor* caller,
  1287. void* data)
  1288. {
  1289. // Just commit every keystroke
  1290. onCommitSetDirty(caller, data);
  1291. }
  1292. // static
  1293. void LLPreviewGesture::onClickAdd(void* data)
  1294. {
  1295. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1296. LLScrollListItem* library_item = self->mLibraryList->getFirstSelected();
  1297. if (!library_item) return;
  1298. S32 library_item_index = self->mLibraryList->getFirstSelectedIndex();
  1299. const LLScrollListCell* library_cell = library_item->getColumn(0);
  1300. const std::string& library_text = library_cell->getValue().asString();
  1301. if( library_item_index >= STEP_EOF )
  1302. {
  1303. llerrs << "Unknown step type: " << library_text << llendl;
  1304. return;
  1305. }
  1306. self->addStep( (EStepType)library_item_index );
  1307. self->mDirty = TRUE;
  1308. self->refresh();
  1309. }
  1310. LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type )
  1311. {
  1312. // Order of enum EStepType MUST match the library_list element in floater_preview_gesture.xml
  1313. LLGestureStep* step = NULL;
  1314. switch( step_type)
  1315. {
  1316. case STEP_ANIMATION:
  1317. step = new LLGestureStepAnimation();
  1318. break;
  1319. case STEP_SOUND:
  1320. step = new LLGestureStepSound();
  1321. break;
  1322. case STEP_CHAT:
  1323. step = new LLGestureStepChat();
  1324. break;
  1325. case STEP_WAIT:
  1326. step = new LLGestureStepWait();
  1327. break;
  1328. default:
  1329. llerrs << "Unknown step type: " << (S32)step_type << llendl;
  1330. return NULL;
  1331. }
  1332. // Create an enabled item with this step
  1333. LLSD row;
  1334. row["columns"][0]["value"] = getLabel(step->getLabel());
  1335. row["columns"][0]["font"] = "SANSSERIF_SMALL";
  1336. LLScrollListItem* step_item = mStepList->addElement(row);
  1337. step_item->setUserdata(step);
  1338. // And move selection to the list on the right
  1339. mLibraryList->deselectAllItems();
  1340. mStepList->deselectAllItems();
  1341. step_item->setSelected(TRUE);
  1342. return step_item;
  1343. }
  1344. // static
  1345. std::string LLPreviewGesture::getLabel(std::vector<std::string> labels)
  1346. {
  1347. std::vector<std::string> v_labels = labels ;
  1348. std::string result("");
  1349. if( v_labels.size() != 2)
  1350. {
  1351. return result;
  1352. }
  1353. if(v_labels[0]=="Chat")
  1354. {
  1355. result=LLTrans::getString("Chat Message");
  1356. }
  1357. else if(v_labels[0]=="Sound")
  1358. {
  1359. result=LLTrans::getString("Sound");
  1360. }
  1361. else if(v_labels[0]=="Wait")
  1362. {
  1363. result=LLTrans::getString("Wait");
  1364. }
  1365. else if(v_labels[0]=="AnimFlagStop")
  1366. {
  1367. result=LLTrans::getString("AnimFlagStop");
  1368. }
  1369. else if(v_labels[0]=="AnimFlagStart")
  1370. {
  1371. result=LLTrans::getString("AnimFlagStart");
  1372. }
  1373. // lets localize action value
  1374. std::string action = v_labels[1];
  1375. if ("None" == action)
  1376. {
  1377. action = LLTrans::getString("GestureActionNone");
  1378. }
  1379. else if ("until animations are done" == action)
  1380. {
  1381. action = LLFloaterReg::getInstance("preview_gesture")->getChild<LLCheckBoxCtrl>("wait_anim_check")->getLabel();
  1382. }
  1383. result.append(action);
  1384. return result;
  1385. }
  1386. // static
  1387. void LLPreviewGesture::onClickUp(void* data)
  1388. {
  1389. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1390. S32 selected_index = self->mStepList->getFirstSelectedIndex();
  1391. if (selected_index > 0)
  1392. {
  1393. self->mStepList->swapWithPrevious(selected_index);
  1394. self->mDirty = TRUE;
  1395. self->refresh();
  1396. }
  1397. }
  1398. // static
  1399. void LLPreviewGesture::onClickDown(void* data)
  1400. {
  1401. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1402. S32 selected_index = self->mStepList->getFirstSelectedIndex();
  1403. if (selected_index < 0) return;
  1404. S32 count = self->mStepList->getItemCount();
  1405. if (selected_index < count-1)
  1406. {
  1407. self->mStepList->swapWithNext(selected_index);
  1408. self->mDirty = TRUE;
  1409. self->refresh();
  1410. }
  1411. }
  1412. // static
  1413. void LLPreviewGesture::onClickDelete(void* data)
  1414. {
  1415. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1416. LLScrollListItem* item = self->mStepList->getFirstSelected();
  1417. S32 selected_index = self->mStepList->getFirstSelectedIndex();
  1418. if (item && selected_index >= 0)
  1419. {
  1420. LLGestureStep* step = (LLGestureStep*)item->getUserdata();
  1421. delete step;
  1422. step = NULL;
  1423. self->mStepList->deleteSingleItem(selected_index);
  1424. self->mDirty = TRUE;
  1425. self->refresh();
  1426. }
  1427. }
  1428. // static
  1429. void LLPreviewGesture::onCommitActive(LLUICtrl* ctrl, void* data)
  1430. {
  1431. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1432. if (!LLGestureMgr::instance().isGestureActive(self->mItemUUID))
  1433. {
  1434. LLGestureMgr::instance().activateGesture(self->mItemUUID);
  1435. }
  1436. else
  1437. {
  1438. LLGestureMgr::instance().deactivateGesture(self->mItemUUID);
  1439. }
  1440. // Make sure the (active) label in the inventory gets updated.
  1441. LLViewerInventoryItem* item = gInventory.getItem(self->mItemUUID);
  1442. if (item)
  1443. {
  1444. gInventory.updateItem(item);
  1445. gInventory.notifyObservers();
  1446. }
  1447. self->refresh();
  1448. }
  1449. // static
  1450. void LLPreviewGesture::onClickSave(void* data)
  1451. {
  1452. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1453. self->saveIfNeeded();
  1454. }
  1455. // static
  1456. void LLPreviewGesture::onClickPreview(void* data)
  1457. {
  1458. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1459. if (!self->mPreviewGesture)
  1460. {
  1461. // make temporary gesture
  1462. self->mPreviewGesture = self->createGesture();
  1463. // add a callback
  1464. self->mPreviewGesture->mDoneCallback = onDonePreview;
  1465. self->mPreviewGesture->mCallbackData = self;
  1466. // set the button title
  1467. self->mPreviewBtn->setLabel(self->getString("stop_txt"));
  1468. // play it, and delete when done
  1469. LLGestureMgr::instance().playGesture(self->mPreviewGesture);
  1470. self->refresh();
  1471. }
  1472. else
  1473. {
  1474. // Will call onDonePreview() below
  1475. LLGestureMgr::instance().stopGesture(self->mPreviewGesture);
  1476. self->refresh();
  1477. }
  1478. }
  1479. // static
  1480. void LLPreviewGesture::onDonePreview(LLMultiGesture* gesture, void* data)
  1481. {
  1482. LLPreviewGesture* self = (LLPreviewGesture*)data;
  1483. self->mPreviewBtn->setLabel(self->getString("preview_txt"));
  1484. delete self->mPreviewGesture;
  1485. self->mPreviewGesture = NULL;
  1486. self->refresh();
  1487. }