llpreviewgesture.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:44k
源码类别:

游戏引擎

开发平台:

C++ Builder

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