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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfloateranimpreview.cpp
  3.  * @brief LLFloaterAnimPreview class implementation
  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 "llfloateranimpreview.h"
  34. #include "llbvhloader.h"
  35. #include "lldatapacker.h"
  36. #include "lldir.h"
  37. #include "lleconomy.h"
  38. #include "llnotificationsutil.h"
  39. #include "llvfile.h"
  40. #include "llapr.h"
  41. #include "llstring.h"
  42. #include "llagent.h"
  43. #include "llanimationstates.h"
  44. #include "llbbox.h"
  45. #include "llbutton.h"
  46. #include "llcheckboxctrl.h"
  47. #include "llcombobox.h"
  48. #include "lldrawable.h"
  49. #include "lldrawpoolavatar.h"
  50. #include "llrender.h"
  51. #include "llface.h"
  52. #include "llfocusmgr.h"
  53. #include "llkeyframemotion.h"
  54. #include "lllineeditor.h"
  55. #include "llfloaterperms.h"
  56. #include "llsliderctrl.h"
  57. #include "llspinctrl.h"
  58. #include "lltextbox.h"
  59. #include "lltoolmgr.h"
  60. #include "llui.h"
  61. #include "llviewercamera.h"
  62. #include "llviewerobjectlist.h"
  63. #include "llviewerwindow.h"
  64. #include "llviewermenufile.h" // upload_new_resource()
  65. #include "llvoavatar.h"
  66. #include "pipeline.h"
  67. #include "lluictrlfactory.h"
  68. #include "lltrans.h"
  69. const S32 PREVIEW_BORDER_WIDTH = 2;
  70. const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
  71. const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
  72. const S32 PREF_BUTTON_HEIGHT = 16;
  73. const S32 PREVIEW_TEXTURE_HEIGHT = 300;
  74. const F32 PREVIEW_CAMERA_DISTANCE = 4.f;
  75. const F32 MIN_CAMERA_ZOOM = 0.5f;
  76. const F32 MAX_CAMERA_ZOOM = 10.f;
  77. const F32 BASE_ANIM_TIME_OFFSET = 5.f;
  78. std::string STATUS[] =
  79. {
  80. "E_ST_OK",
  81. "E_ST_EOF",
  82. "E_ST_NO_CONSTRAINT",
  83. "E_ST_NO_FILE",
  84. "E_ST_NO_HIER",
  85. "E_ST_NO_JOINT",
  86. "E_ST_NO_NAME",
  87. "E_ST_NO_OFFSET",
  88. "E_ST_NO_CHANNELS",
  89. "E_ST_NO_ROTATION",
  90. "E_ST_NO_AXIS",
  91. "E_ST_NO_MOTION",
  92. "E_ST_NO_FRAMES",
  93. "E_ST_NO_FRAME_TIME",
  94. "E_ST_NO_POS",
  95. "E_ST_NO_ROT",
  96. "E_ST_NO_XLT_FILE",
  97. "E_ST_NO_XLT_HEADER",
  98. "E_ST_NO_XLT_NAME",
  99. "E_ST_NO_XLT_IGNORE",
  100. "E_ST_NO_XLT_RELATIVE",
  101. "E_ST_NO_XLT_OUTNAME",
  102. "E_ST_NO_XLT_MATRIX",
  103. "E_ST_NO_XLT_MERGECHILD",
  104. "E_ST_NO_XLT_MERGEPARENT",
  105. "E_ST_NO_XLT_PRIORITY",
  106. "E_ST_NO_XLT_LOOP",
  107. "E_ST_NO_XLT_EASEIN",
  108. "E_ST_NO_XLT_EASEOUT",
  109. "E_ST_NO_XLT_HAND",
  110. "E_ST_NO_XLT_EMOTE",
  111. "E_ST_BAD_ROOT"
  112. };
  113. //-----------------------------------------------------------------------------
  114. // LLFloaterAnimPreview()
  115. //-----------------------------------------------------------------------------
  116. LLFloaterAnimPreview::LLFloaterAnimPreview(const std::string& filename) : 
  117. LLFloaterNameDesc(filename)
  118. {
  119. mLastMouseX = 0;
  120. mLastMouseY = 0;
  121. mIDList["Standing"] = ANIM_AGENT_STAND;
  122. mIDList["Walking"] = ANIM_AGENT_FEMALE_WALK;
  123. mIDList["Sitting"] = ANIM_AGENT_SIT_FEMALE;
  124. mIDList["Flying"] = ANIM_AGENT_HOVER;
  125. mIDList["[None]"] = LLUUID::null;
  126. mIDList["Aaaaah"] = ANIM_AGENT_EXPRESS_OPEN_MOUTH;
  127. mIDList["Afraid"] = ANIM_AGENT_EXPRESS_AFRAID;
  128. mIDList["Angry"] = ANIM_AGENT_EXPRESS_ANGER;
  129. mIDList["Big Smile"] = ANIM_AGENT_EXPRESS_TOOTHSMILE;
  130. mIDList["Bored"] = ANIM_AGENT_EXPRESS_BORED;
  131. mIDList["Cry"] = ANIM_AGENT_EXPRESS_CRY;
  132. mIDList["Disdain"] = ANIM_AGENT_EXPRESS_DISDAIN;
  133. mIDList["Embarrassed"] = ANIM_AGENT_EXPRESS_EMBARRASSED;
  134. mIDList["Frown"] = ANIM_AGENT_EXPRESS_FROWN;
  135. mIDList["Kiss"] = ANIM_AGENT_EXPRESS_KISS;
  136. mIDList["Laugh"] = ANIM_AGENT_EXPRESS_LAUGH;
  137. mIDList["Plllppt"] = ANIM_AGENT_EXPRESS_TONGUE_OUT;
  138. mIDList["Repulsed"] = ANIM_AGENT_EXPRESS_REPULSED;
  139. mIDList["Sad"] = ANIM_AGENT_EXPRESS_SAD;
  140. mIDList["Shrug"] = ANIM_AGENT_EXPRESS_SHRUG;
  141. mIDList["Smile"] = ANIM_AGENT_EXPRESS_SMILE;
  142. mIDList["Surprise"] = ANIM_AGENT_EXPRESS_SURPRISE;
  143. mIDList["Wink"] = ANIM_AGENT_EXPRESS_WINK;
  144. mIDList["Worry"] = ANIM_AGENT_EXPRESS_WORRY;
  145. }
  146. //-----------------------------------------------------------------------------
  147. // setAnimCallbacks()
  148. //-----------------------------------------------------------------------------
  149. void LLFloaterAnimPreview::setAnimCallbacks()
  150. {
  151. childSetCommitCallback("playback_slider", onSliderMove, this);
  152. childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this);
  153. childSetValue("preview_base_anim", "Standing");
  154. childSetCommitCallback("priority", onCommitPriority, this);
  155. childSetCommitCallback("loop_check", onCommitLoop, this);
  156. childSetCommitCallback("loop_in_point", onCommitLoopIn, this);
  157. childSetValidate("loop_in_point", boost::bind(&LLFloaterAnimPreview::validateLoopIn, this, _1));
  158. childSetCommitCallback("loop_out_point", onCommitLoopOut, this);
  159. childSetValidate("loop_out_point", boost::bind(&LLFloaterAnimPreview::validateLoopOut, this, _1));
  160. childSetCommitCallback("hand_pose_combo", onCommitHandPose, this);
  161. childSetCommitCallback("emote_combo", onCommitEmote, this);
  162. childSetValue("emote_combo", "[None]");
  163. childSetCommitCallback("ease_in_time", onCommitEaseIn, this);
  164. childSetValidate("ease_in_time", boost::bind(&LLFloaterAnimPreview::validateEaseIn, this, _1));
  165. childSetCommitCallback("ease_out_time", onCommitEaseOut, this);
  166. childSetValidate("ease_out_time", boost::bind(&LLFloaterAnimPreview::validateEaseOut, this, _1));
  167. }
  168. //-----------------------------------------------------------------------------
  169. // postBuild()
  170. //-----------------------------------------------------------------------------
  171. BOOL LLFloaterAnimPreview::postBuild()
  172. {
  173. LLKeyframeMotion* motionp = NULL;
  174. LLBVHLoader* loaderp = NULL;
  175. if (!LLFloaterNameDesc::postBuild())
  176. {
  177. return FALSE;
  178. }
  179. childSetCommitCallback("name_form", onCommitName, this);
  180. childSetAction("ok_btn", onBtnOK, this);
  181. setDefaultBtn();
  182. mPreviewRect.set(PREVIEW_HPAD, 
  183. PREVIEW_TEXTURE_HEIGHT,
  184. getRect().getWidth() - PREVIEW_HPAD, 
  185. PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
  186. mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f);
  187. mPlayButton = getChild<LLButton>( "play_btn");
  188. mPlayButton->setClickedCallback(onBtnPlay, this);
  189. mPlayButton->setVisible(true);
  190. mPauseButton = getChild<LLButton>( "pause_btn");
  191. mPauseButton->setClickedCallback(onBtnPause, this);
  192. mPauseButton->setVisible(false);
  193. mStopButton = getChild<LLButton>( "stop_btn");
  194. mStopButton->setClickedCallback(onBtnStop, this);
  195. childHide("bad_animation_text");
  196. std::string exten = gDirUtilp->getExtension(mFilename);
  197. if (exten == "bvh")
  198. {
  199. // loading a bvh file
  200. // now load bvh file
  201. S32 file_size;
  202. LLAPRFile infile ;
  203. infile.open(mFilenameAndPath, LL_APR_RB, NULL, &file_size);
  204. if (!infile.getFileHandle())
  205. {
  206. llwarns << "Can't open BVH file:" << mFilename << llendl;
  207. }
  208. else
  209. {
  210. char* file_buffer;
  211. file_buffer = new char[file_size + 1];
  212. if (file_size == infile.read(file_buffer, file_size))
  213. {
  214. file_buffer[file_size] = '';
  215. llinfos << "Loading BVH file " << mFilename << llendl;
  216. ELoadStatus load_status = E_ST_OK;
  217. S32 line_number = 0; 
  218. loaderp = new LLBVHLoader(file_buffer, load_status, line_number);
  219. std::string status = getString(STATUS[load_status]);
  220. if(load_status == E_ST_NO_XLT_FILE)
  221. {
  222. llwarns << "NOTE: No translation table found." << llendl;
  223. }
  224. else
  225. {
  226. llwarns << "ERROR: [line: " << line_number << "] " << status << llendl;
  227. }
  228. }
  229. infile.close() ;
  230. delete[] file_buffer;
  231. }
  232. }
  233. if (loaderp && loaderp->isInitialized() && loaderp->getDuration() <= MAX_ANIM_DURATION)
  234. {
  235. // generate unique id for this motion
  236. mTransactionID.generate();
  237. mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
  238. mAnimPreview = new LLPreviewAnimation(256, 256);
  239. // motion will be returned, but it will be in a load-pending state, as this is a new motion
  240. // this motion will not request an asset transfer until next update, so we have a chance to 
  241. // load the keyframe data locally
  242. motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID);
  243. // create data buffer for keyframe initialization
  244. S32 buffer_size = loaderp->getOutputSize();
  245. U8* buffer = new U8[buffer_size];
  246. LLDataPackerBinaryBuffer dp(buffer, buffer_size);
  247. // pass animation data through memory buffer
  248. loaderp->serialize(dp);
  249. dp.reset();
  250. BOOL success = motionp && motionp->deserialize(dp);
  251. delete []buffer;
  252. if (success)
  253. {
  254. setAnimCallbacks() ;
  255. const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox();
  256. LLVector3 temp = pelvis_bbox.getCenter();
  257. // only consider XY?
  258. //temp.mV[VZ] = 0.f;
  259. F32 pelvis_offset = temp.magVec();
  260. temp = pelvis_bbox.getExtent();
  261. //temp.mV[VZ] = 0.f;
  262. F32 pelvis_max_displacement = pelvis_offset + (temp.magVec() * 0.5f) + 1.f;
  263. F32 camera_zoom = LLViewerCamera::getInstance()->getDefaultFOV() / (2.f * atan(pelvis_max_displacement / PREVIEW_CAMERA_DISTANCE));
  264. mAnimPreview->setZoom(camera_zoom);
  265. motionp->setName(childGetValue("name_form").asString());
  266. mAnimPreview->getDummyAvatar()->startMotion(mMotionID);
  267. getChild<LLSlider>("playback_slider")->setMinValue(0.0);
  268. getChild<LLSlider>("playback_slider")->setMaxValue(1.0);
  269. childSetValue("loop_check", LLSD(motionp->getLoop()));
  270. childSetValue("loop_in_point", LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f));
  271. childSetValue("loop_out_point", LLSD(motionp->getLoopOut() / motionp->getDuration() * 100.f));
  272. childSetValue("priority", LLSD((F32)motionp->getPriority()));
  273. childSetValue("hand_pose_combo", LLHandMotion::getHandPoseName(motionp->getHandPose()));
  274. childSetValue("ease_in_time", LLSD(motionp->getEaseInDuration()));
  275. childSetValue("ease_out_time", LLSD(motionp->getEaseOutDuration()));
  276. setEnabled(TRUE);
  277. std::string seconds_string;
  278. seconds_string = llformat(" - %.2f seconds", motionp->getDuration());
  279. setTitle(mFilename + std::string(seconds_string));
  280. }
  281. else
  282. {
  283. mAnimPreview = NULL;
  284. mMotionID.setNull();
  285. childSetValue("bad_animation_text", getString("failed_to_initialize"));
  286. }
  287. }
  288. else
  289. {
  290. if ( loaderp )
  291. {
  292. if (loaderp->getDuration() > MAX_ANIM_DURATION)
  293. {
  294. LLUIString out_str = getString("anim_too_long");
  295. out_str.setArg("[LENGTH]", llformat("%.1f", loaderp->getDuration()));
  296. out_str.setArg("[MAX_LENGTH]", llformat("%.1f", MAX_ANIM_DURATION));
  297. childSetValue("bad_animation_text", out_str.getString());
  298. }
  299. else
  300. {
  301. LLUIString out_str = getString("failed_file_read");
  302. out_str.setArg("[STATUS]", getString(STATUS[loaderp->getStatus()])); 
  303. childSetValue("bad_animation_text", out_str.getString());
  304. }
  305. }
  306. //setEnabled(FALSE);
  307. mMotionID.setNull();
  308. mAnimPreview = NULL;
  309. }
  310. refresh();
  311. delete loaderp;
  312. return TRUE;
  313. }
  314. //-----------------------------------------------------------------------------
  315. // LLFloaterAnimPreview()
  316. //-----------------------------------------------------------------------------
  317. LLFloaterAnimPreview::~LLFloaterAnimPreview()
  318. {
  319. mAnimPreview = NULL;
  320. setEnabled(FALSE);
  321. }
  322. //-----------------------------------------------------------------------------
  323. // draw()
  324. //-----------------------------------------------------------------------------
  325. void LLFloaterAnimPreview::draw()
  326. {
  327. LLFloater::draw();
  328. LLRect r = getRect();
  329. refresh();
  330. if (mMotionID.notNull() && mAnimPreview)
  331. {
  332. gGL.color3f(1.f, 1.f, 1.f);
  333. gGL.getTexUnit(0)->bind(mAnimPreview);
  334. gGL.begin( LLRender::QUADS );
  335. {
  336. gGL.texCoord2f(0.f, 1.f);
  337. gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
  338. gGL.texCoord2f(0.f, 0.f);
  339. gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
  340. gGL.texCoord2f(1.f, 0.f);
  341. gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
  342. gGL.texCoord2f(1.f, 1.f);
  343. gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
  344. }
  345. gGL.end();
  346. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  347. LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
  348. if (!avatarp->areAnimationsPaused())
  349. {
  350. mAnimPreview->requestUpdate();
  351. }
  352. }
  353. }
  354. //-----------------------------------------------------------------------------
  355. // resetMotion()
  356. //-----------------------------------------------------------------------------
  357. void LLFloaterAnimPreview::resetMotion()
  358. {
  359. LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
  360. BOOL paused = avatarp->areAnimationsPaused();
  361. // *TODO: Fix awful casting hack
  362. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
  363. // Set emotion
  364. std::string emote = childGetValue("emote_combo").asString();
  365. motionp->setEmote(mIDList[emote]);
  366. LLUUID base_id = mIDList[childGetValue("preview_base_anim").asString()];
  367. avatarp->deactivateAllMotions();
  368. avatarp->startMotion(mMotionID, 0.0f);
  369. avatarp->startMotion(base_id, BASE_ANIM_TIME_OFFSET);
  370. childSetValue("playback_slider", 0.0f);
  371. // Set pose
  372. std::string handpose = childGetValue("hand_pose_combo").asString();
  373. avatarp->startMotion( ANIM_AGENT_HAND_MOTION, 0.0f );
  374. motionp->setHandPose(LLHandMotion::getHandPose(handpose));
  375. if (paused)
  376. {
  377. mPauseRequest = avatarp->requestPause();
  378. }
  379. else
  380. {
  381. mPauseRequest = NULL;
  382. }
  383. }
  384. //-----------------------------------------------------------------------------
  385. // handleMouseDown()
  386. //-----------------------------------------------------------------------------
  387. BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask)
  388. {
  389. if (mPreviewRect.pointInRect(x, y))
  390. {
  391. bringToFront( x, y );
  392. gFocusMgr.setMouseCapture(this);
  393. gViewerWindow->hideCursor();
  394. mLastMouseX = x;
  395. mLastMouseY = y;
  396. return TRUE;
  397. }
  398. return LLFloater::handleMouseDown(x, y, mask);
  399. }
  400. //-----------------------------------------------------------------------------
  401. // handleMouseUp()
  402. //-----------------------------------------------------------------------------
  403. BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask)
  404. {
  405. gFocusMgr.setMouseCapture(FALSE);
  406. gViewerWindow->showCursor();
  407. return LLFloater::handleMouseUp(x, y, mask);
  408. }
  409. //-----------------------------------------------------------------------------
  410. // handleHover()
  411. //-----------------------------------------------------------------------------
  412. BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask)
  413. {
  414. MASK local_mask = mask & ~MASK_ALT;
  415. if (mAnimPreview && hasMouseCapture())
  416. {
  417. if (local_mask == MASK_PAN)
  418. {
  419. // pan here
  420. mAnimPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f);
  421. }
  422. else if (local_mask == MASK_ORBIT)
  423. {
  424. F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
  425. F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f;
  426. mAnimPreview->rotate(yaw_radians, pitch_radians);
  427. }
  428. else 
  429. {
  430. F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
  431. F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f;
  432. mAnimPreview->rotate(yaw_radians, 0.f);
  433. mAnimPreview->zoom(zoom_amt);
  434. }
  435. mAnimPreview->requestUpdate();
  436. LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
  437. }
  438. if (!mPreviewRect.pointInRect(x, y) || !mAnimPreview)
  439. {
  440. return LLFloater::handleHover(x, y, mask);
  441. }
  442. else if (local_mask == MASK_ORBIT)
  443. {
  444. gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA);
  445. }
  446. else if (local_mask == MASK_PAN)
  447. {
  448. gViewerWindow->setCursor(UI_CURSOR_TOOLPAN);
  449. }
  450. else
  451. {
  452. gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN);
  453. }
  454. return TRUE;
  455. }
  456. //-----------------------------------------------------------------------------
  457. // handleScrollWheel()
  458. //-----------------------------------------------------------------------------
  459. BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
  460. {
  461. mAnimPreview->zoom((F32)clicks * -0.2f);
  462. mAnimPreview->requestUpdate();
  463. return TRUE;
  464. }
  465. //-----------------------------------------------------------------------------
  466. // onMouseCaptureLost()
  467. //-----------------------------------------------------------------------------
  468. void LLFloaterAnimPreview::onMouseCaptureLost()
  469. {
  470. gViewerWindow->showCursor();
  471. }
  472. //-----------------------------------------------------------------------------
  473. // onBtnPlay()
  474. //-----------------------------------------------------------------------------
  475. void LLFloaterAnimPreview::onBtnPlay(void* user_data)
  476. {
  477. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data;
  478. if (!previewp->getEnabled())
  479. return;
  480. if (previewp->mMotionID.notNull() && previewp->mAnimPreview)
  481. {
  482. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  483. if(!avatarp->isMotionActive(previewp->mMotionID))
  484. {
  485. previewp->resetMotion();
  486. previewp->mPauseRequest = NULL;
  487. }
  488. else if (avatarp->areAnimationsPaused())
  489. {
  490. previewp->mPauseRequest = NULL;
  491. }
  492. }
  493. }
  494. //-----------------------------------------------------------------------------
  495. // onBtnPause()
  496. //-----------------------------------------------------------------------------
  497. void LLFloaterAnimPreview::onBtnPause(void* user_data)
  498. {
  499. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data;
  500. if (!previewp->getEnabled())
  501. return;
  502. if (previewp->mMotionID.notNull() && previewp->mAnimPreview)
  503. {
  504. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  505. if(avatarp->isMotionActive(previewp->mMotionID))
  506. {
  507. if (!avatarp->areAnimationsPaused())
  508. {
  509. previewp->mPauseRequest = avatarp->requestPause();
  510. }
  511. }
  512. }
  513. }
  514. //-----------------------------------------------------------------------------
  515. // onBtnStop()
  516. //-----------------------------------------------------------------------------
  517. void LLFloaterAnimPreview::onBtnStop(void* user_data)
  518. {
  519. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data;
  520. if (!previewp->getEnabled())
  521. return;
  522. if (previewp->mMotionID.notNull() && previewp->mAnimPreview)
  523. {
  524. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  525. previewp->resetMotion();
  526. previewp->mPauseRequest = avatarp->requestPause();
  527. }
  528. }
  529. //-----------------------------------------------------------------------------
  530. // onSliderMove()
  531. //-----------------------------------------------------------------------------
  532. void LLFloaterAnimPreview::onSliderMove(LLUICtrl* ctrl, void*user_data)
  533. {
  534. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data;
  535. if (!previewp->getEnabled())
  536. return;
  537. if (previewp->mAnimPreview)
  538. {
  539. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  540. F32 slider_value = (F32)previewp->childGetValue("playback_slider").asReal();
  541. LLUUID base_id = previewp->mIDList[previewp->childGetValue("preview_base_anim").asString()];
  542. LLMotion* motionp = avatarp->findMotion(previewp->mMotionID);
  543. F32 duration = motionp->getDuration();// + motionp->getEaseOutDuration();
  544. F32 delta_time = duration * slider_value;
  545. avatarp->deactivateAllMotions();
  546. avatarp->startMotion(base_id, delta_time + BASE_ANIM_TIME_OFFSET);
  547. avatarp->startMotion(previewp->mMotionID, delta_time);
  548. previewp->mPauseRequest = avatarp->requestPause();
  549. previewp->refresh();
  550. }
  551. }
  552. //-----------------------------------------------------------------------------
  553. // onCommitBaseAnim()
  554. //-----------------------------------------------------------------------------
  555. void LLFloaterAnimPreview::onCommitBaseAnim(LLUICtrl* ctrl, void* data)
  556. {
  557. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  558. if (!previewp->getEnabled())
  559. return;
  560. if (previewp->mAnimPreview)
  561. {
  562. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  563. BOOL paused = avatarp->areAnimationsPaused();
  564. // stop all other possible base motions
  565. avatarp->stopMotion(previewp->mIDList["Standing"], TRUE);
  566. avatarp->stopMotion(previewp->mIDList["Walking"], TRUE);
  567. avatarp->stopMotion(previewp->mIDList["Sitting"], TRUE);
  568. avatarp->stopMotion(previewp->mIDList["Flying"], TRUE);
  569. previewp->resetMotion();
  570. if (!paused)
  571. {
  572. previewp->mPauseRequest = NULL;
  573. }
  574. }
  575. }
  576. //-----------------------------------------------------------------------------
  577. // onCommitLoop()
  578. //-----------------------------------------------------------------------------
  579. void LLFloaterAnimPreview::onCommitLoop(LLUICtrl* ctrl, void* data)
  580. {
  581. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  582. if (!previewp->getEnabled())
  583. return;
  584. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  585. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
  586. if (motionp)
  587. {
  588. motionp->setLoop(previewp->childGetValue("loop_check").asBoolean());
  589. motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() * 0.01f * motionp->getDuration());
  590. motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration());
  591. }
  592. }
  593. //-----------------------------------------------------------------------------
  594. // onCommitLoopIn()
  595. //-----------------------------------------------------------------------------
  596. void LLFloaterAnimPreview::onCommitLoopIn(LLUICtrl* ctrl, void* data)
  597. {
  598. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  599. if (!previewp->getEnabled())
  600. return;
  601. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  602. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
  603. if (motionp)
  604. {
  605. motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() / 100.f);
  606. previewp->resetMotion();
  607. previewp->childSetValue("loop_check", LLSD(TRUE));
  608. onCommitLoop(ctrl, data);
  609. }
  610. }
  611. //-----------------------------------------------------------------------------
  612. // onCommitLoopOut()
  613. //-----------------------------------------------------------------------------
  614. void LLFloaterAnimPreview::onCommitLoopOut(LLUICtrl* ctrl, void* data)
  615. {
  616. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  617. if (!previewp->getEnabled())
  618. return;
  619. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  620. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
  621. if (motionp)
  622. {
  623. motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration());
  624. previewp->resetMotion();
  625. previewp->childSetValue("loop_check", LLSD(TRUE));
  626. onCommitLoop(ctrl, data);
  627. }
  628. }
  629. //-----------------------------------------------------------------------------
  630. // onCommitName()
  631. //-----------------------------------------------------------------------------
  632. void LLFloaterAnimPreview::onCommitName(LLUICtrl* ctrl, void* data)
  633. {
  634. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  635. if (!previewp->getEnabled())
  636. return;
  637. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  638. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
  639. if (motionp)
  640. {
  641. motionp->setName(previewp->childGetValue("name_form").asString());
  642. }
  643. previewp->doCommit();
  644. }
  645. //-----------------------------------------------------------------------------
  646. // onCommitHandPose()
  647. //-----------------------------------------------------------------------------
  648. void LLFloaterAnimPreview::onCommitHandPose(LLUICtrl* ctrl, void* data)
  649. {
  650. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  651. if (!previewp->getEnabled())
  652. return;
  653. previewp->resetMotion(); // sets hand pose
  654. }
  655. //-----------------------------------------------------------------------------
  656. // onCommitEmote()
  657. //-----------------------------------------------------------------------------
  658. void LLFloaterAnimPreview::onCommitEmote(LLUICtrl* ctrl, void* data)
  659. {
  660. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  661. if (!previewp->getEnabled())
  662. return;
  663. previewp->resetMotion(); // ssts emote
  664. }
  665. //-----------------------------------------------------------------------------
  666. // onCommitPriority()
  667. //-----------------------------------------------------------------------------
  668. void LLFloaterAnimPreview::onCommitPriority(LLUICtrl* ctrl, void* data)
  669. {
  670. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  671. if (!previewp->getEnabled())
  672. return;
  673. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  674. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
  675. motionp->setPriority(llfloor((F32)previewp->childGetValue("priority").asReal()));
  676. }
  677. //-----------------------------------------------------------------------------
  678. // onCommitEaseIn()
  679. //-----------------------------------------------------------------------------
  680. void LLFloaterAnimPreview::onCommitEaseIn(LLUICtrl* ctrl, void* data)
  681. {
  682. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  683. if (!previewp->getEnabled())
  684. return;
  685. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  686. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
  687. motionp->setEaseIn((F32)previewp->childGetValue("ease_in_time").asReal());
  688. previewp->resetMotion();
  689. }
  690. //-----------------------------------------------------------------------------
  691. // onCommitEaseOut()
  692. //-----------------------------------------------------------------------------
  693. void LLFloaterAnimPreview::onCommitEaseOut(LLUICtrl* ctrl, void* data)
  694. {
  695. LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
  696. if (!previewp->getEnabled())
  697. return;
  698. LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
  699. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
  700. motionp->setEaseOut((F32)previewp->childGetValue("ease_out_time").asReal());
  701. previewp->resetMotion();
  702. }
  703. //-----------------------------------------------------------------------------
  704. // validateEaseIn()
  705. //-----------------------------------------------------------------------------
  706. bool LLFloaterAnimPreview::validateEaseIn(const LLSD& data)
  707. {
  708. if (!getEnabled())
  709. return false;
  710. LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
  711. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
  712. if (!motionp->getLoop())
  713. {
  714. F32 new_ease_in = llclamp((F32)childGetValue("ease_in_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseOutDuration());
  715. childSetValue("ease_in_time", LLSD(new_ease_in));
  716. }
  717. return true;
  718. }
  719. //-----------------------------------------------------------------------------
  720. // validateEaseOut()
  721. //-----------------------------------------------------------------------------
  722. bool LLFloaterAnimPreview::validateEaseOut(const LLSD& data)
  723. {
  724. if (!getEnabled())
  725. return false;
  726. LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
  727. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
  728. if (!motionp->getLoop())
  729. {
  730. F32 new_ease_out = llclamp((F32)childGetValue("ease_out_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseInDuration());
  731. childSetValue("ease_out_time", LLSD(new_ease_out));
  732. }
  733. return true;
  734. }
  735. //-----------------------------------------------------------------------------
  736. // validateLoopIn()
  737. //-----------------------------------------------------------------------------
  738. bool LLFloaterAnimPreview::validateLoopIn(const LLSD& data)
  739. {
  740. if (!getEnabled())
  741. return false;
  742. F32 loop_in_value = (F32)childGetValue("loop_in_point").asReal();
  743. F32 loop_out_value = (F32)childGetValue("loop_out_point").asReal();
  744. if (loop_in_value < 0.f)
  745. {
  746. loop_in_value = 0.f;
  747. }
  748. else if (loop_in_value > 100.f)
  749. {
  750. loop_in_value = 100.f;
  751. }
  752. else if (loop_in_value > loop_out_value)
  753. {
  754. loop_in_value = loop_out_value;
  755. }
  756. childSetValue("loop_in_point", LLSD(loop_in_value));
  757. return true;
  758. }
  759. //-----------------------------------------------------------------------------
  760. // validateLoopOut()
  761. //-----------------------------------------------------------------------------
  762. bool LLFloaterAnimPreview::validateLoopOut(const LLSD& data)
  763. {
  764. if (!getEnabled())
  765. return false;
  766. F32 loop_out_value = (F32)childGetValue("loop_out_point").asReal();
  767. F32 loop_in_value = (F32)childGetValue("loop_in_point").asReal();
  768. if (loop_out_value < 0.f)
  769. {
  770. loop_out_value = 0.f;
  771. }
  772. else if (loop_out_value > 100.f)
  773. {
  774. loop_out_value = 100.f;
  775. }
  776. else if (loop_out_value < loop_in_value)
  777. {
  778. loop_out_value = loop_in_value;
  779. }
  780. childSetValue("loop_out_point", LLSD(loop_out_value));
  781. return true;
  782. }
  783. //-----------------------------------------------------------------------------
  784. // refresh()
  785. //-----------------------------------------------------------------------------
  786. void LLFloaterAnimPreview::refresh()
  787. {
  788. // Are we showing the play button (default) or the pause button?
  789. bool show_play = true;
  790. if (!mAnimPreview)
  791. {
  792. childShow("bad_animation_text");
  793. // play button visible but disabled
  794. mPlayButton->setEnabled(FALSE);
  795. mStopButton->setEnabled(FALSE);
  796. childDisable("ok_btn");
  797. }
  798. else
  799. {
  800. childHide("bad_animation_text");
  801. // re-enabled in case previous animation was bad
  802. mPlayButton->setEnabled(TRUE);
  803. mStopButton->setEnabled(TRUE);
  804. LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
  805. if (avatarp->isMotionActive(mMotionID))
  806. {
  807. mStopButton->setEnabled(TRUE);
  808. LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
  809. if (!avatarp->areAnimationsPaused())
  810. {
  811. // animation is playing
  812. if (motionp)
  813. {
  814. F32 fraction_complete = motionp->getLastUpdateTime() / motionp->getDuration();
  815. childSetValue("playback_slider", fraction_complete);
  816. }
  817. show_play = false;
  818. }
  819. }
  820. else
  821. {
  822. // Motion just finished playing
  823. mPauseRequest = avatarp->requestPause();
  824. }
  825. childEnable("ok_btn");
  826. mAnimPreview->requestUpdate();
  827. }
  828. mPlayButton->setVisible(show_play);
  829. mPauseButton->setVisible(!show_play);
  830. }
  831. //-----------------------------------------------------------------------------
  832. // onBtnOK()
  833. //-----------------------------------------------------------------------------
  834. void LLFloaterAnimPreview::onBtnOK(void* userdata)
  835. {
  836. LLFloaterAnimPreview* floaterp = (LLFloaterAnimPreview*)userdata;
  837. if (!floaterp->getEnabled()) return;
  838. if (floaterp->mAnimPreview)
  839. {
  840. LLKeyframeMotion* motionp = (LLKeyframeMotion*)floaterp->mAnimPreview->getDummyAvatar()->findMotion(floaterp->mMotionID);
  841. S32 file_size = motionp->getFileSize();
  842. U8* buffer = new U8[file_size];
  843. LLDataPackerBinaryBuffer dp(buffer, file_size);
  844. if (motionp->serialize(dp))
  845. {
  846. LLVFile file(gVFS, motionp->getID(), LLAssetType::AT_ANIMATION, LLVFile::APPEND);
  847. S32 size = dp.getCurrentSize();
  848. file.setMaxSize(size);
  849. if (file.write((U8*)buffer, size))
  850. {
  851. std::string name = floaterp->childGetValue("name_form").asString();
  852. std::string desc = floaterp->childGetValue("description_form").asString();
  853. LLAssetStorage::LLStoreAssetCallback callback = NULL;
  854. S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
  855. void *userdata = NULL;
  856. upload_new_resource(floaterp->mTransactionID, // tid
  857.     LLAssetType::AT_ANIMATION,
  858.     name,
  859.     desc,
  860.     0,
  861.     LLFolderType::FT_NONE,
  862.     LLInventoryType::IT_ANIMATION,
  863.     LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
  864.     name,
  865.     callback, expected_upload_cost, userdata);
  866. }
  867. else
  868. {
  869. llwarns << "Failure writing animation data." << llendl;
  870. LLNotificationsUtil::add("WriteAnimationFail");
  871. }
  872. }
  873. delete [] buffer;
  874. // clear out cache for motion data
  875. floaterp->mAnimPreview->getDummyAvatar()->removeMotion(floaterp->mMotionID);
  876. LLKeyframeDataCache::removeKeyframeData(floaterp->mMotionID);
  877. }
  878. floaterp->closeFloater(false);
  879. }
  880. //-----------------------------------------------------------------------------
  881. // LLPreviewAnimation
  882. //-----------------------------------------------------------------------------
  883. LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
  884. {
  885. mNeedsUpdate = TRUE;
  886. mCameraDistance = PREVIEW_CAMERA_DISTANCE;
  887. mCameraYaw = 0.f;
  888. mCameraPitch = 0.f;
  889. mCameraZoom = 1.f;
  890. mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion());
  891. mDummyAvatar->createDrawable(&gPipeline);
  892. mDummyAvatar->mIsDummy = TRUE;
  893. mDummyAvatar->mSpecialRenderMode = 1;
  894. mDummyAvatar->setPositionAgent(LLVector3::zero);
  895. mDummyAvatar->slamPosition();
  896. mDummyAvatar->updateJointLODs();
  897. mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
  898. mDummyAvatar->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET);
  899. mDummyAvatar->hideSkirt();
  900. gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance());
  901. // stop extraneous animations
  902. mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE );
  903. mDummyAvatar->stopMotion( ANIM_AGENT_EYE, TRUE );
  904. mDummyAvatar->stopMotion( ANIM_AGENT_BODY_NOISE, TRUE );
  905. mDummyAvatar->stopMotion( ANIM_AGENT_BREATHE_ROT, TRUE );
  906. }
  907. //-----------------------------------------------------------------------------
  908. // LLPreviewAnimation()
  909. //-----------------------------------------------------------------------------
  910. LLPreviewAnimation::~LLPreviewAnimation()
  911. {
  912. mDummyAvatar->markDead();
  913. }
  914. //-----------------------------------------------------------------------------
  915. // update()
  916. //-----------------------------------------------------------------------------
  917. BOOL LLPreviewAnimation::render()
  918. {
  919. mNeedsUpdate = FALSE;
  920. LLVOAvatar* avatarp = mDummyAvatar;
  921. glMatrixMode(GL_PROJECTION);
  922. gGL.pushMatrix();
  923. glLoadIdentity();
  924. glOrtho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
  925. glMatrixMode(GL_MODELVIEW);
  926. gGL.pushMatrix();
  927. glLoadIdentity();
  928. LLGLSUIDefault def;
  929. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  930. gGL.color4f(0.15f, 0.2f, 0.3f, 1.f);
  931. gl_rect_2d_simple( mFullWidth, mFullHeight );
  932. glMatrixMode(GL_PROJECTION);
  933. gGL.popMatrix();
  934. glMatrixMode(GL_MODELVIEW);
  935. gGL.popMatrix();
  936. gGL.flush();
  937. LLVector3 target_pos = avatarp->mRoot.getWorldPosition();
  938. LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * 
  939. LLQuaternion(mCameraYaw, LLVector3::z_axis);
  940. LLQuaternion av_rot = avatarp->mRoot.getWorldRotation() * camera_rot;
  941. LLViewerCamera::getInstance()->setOriginAndLookAt(
  942. target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera
  943. LLVector3::z_axis, // up
  944. target_pos + (mCameraOffset  * av_rot) ); // point of interest
  945. LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
  946. LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
  947. mCameraRelPos = LLViewerCamera::getInstance()->getOrigin() - avatarp->mHeadp->getWorldPosition();
  948. //avatarp->setAnimationData("LookAtPoint", (void *)&mCameraRelPos);
  949. //SJB: Animation is updated in LLVOAvatar::updateCharacter
  950. if (avatarp->mDrawable.notNull())
  951. {
  952. avatarp->updateLOD();
  953. LLVertexBuffer::unbind();
  954. LLGLDepthTest gls_depth(GL_TRUE);
  955. LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool();
  956. avatarp->dirtyMesh();
  957. avatarPoolp->renderAvatars(avatarp);  // renders only one avatar
  958. }
  959. gGL.color4f(1,1,1,1);
  960. return TRUE;
  961. }
  962. //-----------------------------------------------------------------------------
  963. // requestUpdate()
  964. //-----------------------------------------------------------------------------
  965. void LLPreviewAnimation::requestUpdate()
  966. mNeedsUpdate = TRUE; 
  967. }
  968. //-----------------------------------------------------------------------------
  969. // rotate()
  970. //-----------------------------------------------------------------------------
  971. void LLPreviewAnimation::rotate(F32 yaw_radians, F32 pitch_radians)
  972. {
  973. mCameraYaw = mCameraYaw + yaw_radians;
  974. mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f);
  975. }
  976. //-----------------------------------------------------------------------------
  977. // zoom()
  978. //-----------------------------------------------------------------------------
  979. void LLPreviewAnimation::zoom(F32 zoom_delta)
  980. {
  981. setZoom(mCameraZoom + zoom_delta);
  982. }
  983. //-----------------------------------------------------------------------------
  984. // setZoom()
  985. //-----------------------------------------------------------------------------
  986. void LLPreviewAnimation::setZoom(F32 zoom_amt)
  987. {
  988. mCameraZoom = llclamp(zoom_amt, MIN_CAMERA_ZOOM, MAX_CAMERA_ZOOM);
  989. }
  990. //-----------------------------------------------------------------------------
  991. // pan()
  992. //-----------------------------------------------------------------------------
  993. void LLPreviewAnimation::pan(F32 right, F32 up)
  994. {
  995. mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f);
  996. mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f);
  997. }