llagentpilot.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /**
  2. * @file llagentpilot.cpp
  3. * @brief LLAgentPilot class implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-2009, 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 "llagentpilot.h"
  34. #include "lldir.h"
  35. #include "llnotifications.h"
  36. #if 0 // For renderAutoPilotTarget(), which is not used
  37. #include "llrender.h"
  38. #endif
  39. #include "llagent.h"
  40. #include "llappviewer.h"
  41. #include "llstartup.h"
  42. #include "hbviewerautomation.h"
  43. #include "llviewercontrol.h"
  44. #include "llviewerobjectlist.h"
  45. #include "llvoavatarself.h"
  46. #include "llworld.h"
  47. // Autopilot constants
  48. constexpr F32 AUTOPILOT_HEIGHT_ADJUST_DISTANCE = 8.f; // meters
  49. constexpr F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f; // meters
  50. constexpr F32 AUTOPILOT_MAX_TIME_NO_PROGRESS_WALK = 1.5f; // seconds
  51. constexpr F32 AUTOPILOT_MAX_TIME_NO_PROGRESS_FLY = 2.5f; // seconds
  52. LLAgentPilot gAgentPilot;
  53. bool LLAgentPilot::sLoop = true;
  54. bool LLAgentPilot::sAllowFlying = false;
  55. LLAgentPilot::LLAgentPilot()
  56. : mAutoPilotFinishedCallback(NULL),
  57. mAutoPilotCallbackData(NULL),
  58. mAutoPilotStopDistance(1.f),
  59. mAutoPilotTargetDist(0.f),
  60. mAutoPilotRotationThreshold(0.f),
  61. mAutoPilotNoProgressFrameCount(0),
  62. mAutoPilot(false),
  63. mAutoPilotUseRotation(false),
  64. mAutoPilotAllowFlying(false),
  65. mAutoPilotFlyOnStop(false),
  66. mNumRuns(-1),
  67. mCurrentAction(0),
  68. mLastRecordTime(0.f),
  69. mRecording(false),
  70. mStarted(false),
  71. mPlaying(false),
  72. mAllowFlying(false)
  73. {
  74. }
  75. void LLAgentPilot::startAutoPilotGlobal(const LLVector3d& target_global,
  76. const std::string& behavior_name,
  77. const LLQuaternion* target_rotation,
  78. void (*finish_callback)(bool, void*),
  79. void* callback_data, F32 stop_distance,
  80. F32 rot_threshold, bool allow_flying)
  81. {
  82. if (!isAgentAvatarValid())
  83. {
  84. return;
  85. }
  86. if (target_global.isExactlyZero())
  87. {
  88. llwarns << "Cancelling attempt to start autopilot towards invalid position"
  89. << llendl;
  90. return;
  91. }
  92. mAutoPilotFinishedCallback = finish_callback;
  93. mAutoPilotCallbackData = callback_data;
  94. mAutoPilotRotationThreshold = rot_threshold;
  95. mAutoPilotBehaviorName = behavior_name;
  96. mAutoPilotAllowFlying = allow_flying;
  97. LLVector3d delta_pos(target_global);
  98. delta_pos -= gAgent.getPositionGlobal();
  99. F64 distance = delta_pos.length();
  100. if (stop_distance > 0.f)
  101. {
  102. mAutoPilotStopDistance = stop_distance;
  103. }
  104. else
  105. {
  106. // Guess at a reasonable stop distance.
  107. mAutoPilotStopDistance = sqrtf(distance);
  108. if (mAutoPilotStopDistance < 0.5f)
  109. {
  110. mAutoPilotStopDistance = 0.5f;
  111. }
  112. }
  113. LLVector3d trace_target = target_global;
  114. trace_target.mdV[VZ] -= 10.f;
  115. LLVector3d intersection;
  116. LLVector3 normal;
  117. LLViewerObject* hit_obj;
  118. F32 height_delta = gWorld.resolveStepHeightGlobal(NULL, target_global,
  119. trace_target,
  120. intersection,
  121. normal, &hit_obj);
  122. mAutoPilotFlyOnStop = mAutoPilotAllowFlying && gAgent.getFlying();
  123. if (distance > 30.f && mAutoPilotAllowFlying)
  124. {
  125. gAgent.setFlying(true);
  126. }
  127. if (distance > 2.f && mAutoPilotAllowFlying &&
  128. height_delta > sqrtf(mAutoPilotStopDistance) + 2.f)
  129. {
  130. gAgent.setFlying(true);
  131. // Do not force flying for "Sit" behaviour to prevent flying after
  132. // pressing "Stand" from an object.
  133. if (mAutoPilotBehaviorName != "Sit")
  134. {
  135. mAutoPilotFlyOnStop = true;
  136. }
  137. }
  138. mAutoPilot = true;
  139. mAutoPilotTargetGlobal = target_global;
  140. // Trace ray down to find height of destination from ground
  141. LLVector3d trace_end_pt = target_global;
  142. trace_end_pt.mdV[VZ] -= 20.f;
  143. LLVector3d target_on_gnd;
  144. LLVector3 gnd_norm;
  145. LLViewerObject* obj;
  146. gWorld.resolveStepHeightGlobal(NULL, target_global, trace_end_pt,
  147. target_on_gnd, gnd_norm, &obj);
  148. F64 target_height = llmax((F64)gAgentAvatarp->getPelvisToFoot(),
  149. target_global.mdV[VZ] - target_on_gnd.mdV[VZ]);
  150. // Clamp z value of target to minimum height above ground
  151. mAutoPilotTargetGlobal.mdV[VZ] = target_on_gnd.mdV[VZ] + target_height;
  152. mAutoPilotTargetDist = (F32)dist_vec(gAgent.getPositionGlobal(),
  153. mAutoPilotTargetGlobal);
  154. if (target_rotation)
  155. {
  156. mAutoPilotUseRotation = true;
  157. mAutoPilotTargetFacing = LLVector3::x_axis * *target_rotation;
  158. mAutoPilotTargetFacing.mV[VZ] = 0.f;
  159. mAutoPilotTargetFacing.normalize();
  160. }
  161. else
  162. {
  163. mAutoPilotUseRotation = false;
  164. }
  165. mAutoPilotNoProgressFrameCount = 0;
  166. }
  167. bool LLAgentPilot::startFollowPilot(const LLUUID& leader_id, bool allow_flying,
  168. F32 stop_distance)
  169. {
  170. if (mAutoPilot || leader_id.isNull() || !isAgentAvatarValid())
  171. {
  172. return false;
  173. }
  174. LLViewerObject* object = gObjectList.findObject(leader_id);
  175. if (!object)
  176. {
  177. mLeaderID.setNull();
  178. return false;
  179. }
  180. mLeaderID = leader_id;
  181. startAutoPilotGlobal(object->getPositionGlobal(), mLeaderID.asString(),
  182. NULL, NULL, NULL, stop_distance, 0.03f,
  183. allow_flying);
  184. return true;
  185. }
  186. void LLAgentPilot::stopAutoPilot(bool user_cancel)
  187. {
  188. if (!mAutoPilot || !isAgentAvatarValid())
  189. {
  190. return;
  191. }
  192. mAutoPilot = false;
  193. if (mAutoPilotUseRotation && !user_cancel)
  194. {
  195. gAgent.resetAxes(mAutoPilotTargetFacing);
  196. }
  197. // Note: auto pilot can terminate for a reason other than reaching the
  198. // destination
  199. bool reached = dist_vec(gAgent.getPositionGlobal(),
  200. mAutoPilotTargetGlobal) < mAutoPilotStopDistance;
  201. if (gAutomationp)
  202. {
  203. gAutomationp->onAutoPilotFinished(mAutoPilotBehaviorName, user_cancel,
  204. reached);
  205. }
  206. if (mAutoPilotFinishedCallback)
  207. {
  208. mAutoPilotFinishedCallback(!user_cancel && reached,
  209. mAutoPilotCallbackData);
  210. }
  211. mLeaderID.setNull();
  212. // If the user cancelled, do not change the fly state
  213. if (!user_cancel)
  214. {
  215. gAgent.setFlying(mAutoPilotFlyOnStop);
  216. }
  217. gAgent.setControlFlags(AGENT_CONTROL_STOP);
  218. if (user_cancel && mAutoPilotBehaviorName == "Attach")
  219. {
  220. gNotifications.add("CancelledAttach");
  221. }
  222. else if (!mAutoPilotBehaviorName.empty())
  223. {
  224. llinfos << "Auto-pilot "<< mAutoPilotBehaviorName
  225. << " was canceled by user action." << llendl;
  226. }
  227. else
  228. {
  229. LL_DEBUGS("AutoPilot") << "Auto-pilot was canceled by user action."
  230. << LL_ENDL;
  231. }
  232. }
  233. // Returns necessary agent pitch and yaw changes, radians.
  234. void LLAgentPilot::autoPilot(F32* delta_yaw)
  235. {
  236. if (!mAutoPilot || !isAgentAvatarValid())
  237. {
  238. return;
  239. }
  240. if (mLeaderID.notNull())
  241. {
  242. LLViewerObject* object = gObjectList.findObject(mLeaderID);
  243. if (!object)
  244. {
  245. stopAutoPilot();
  246. return;
  247. }
  248. mAutoPilotTargetGlobal = object->getPositionGlobal();
  249. }
  250. if (mAutoPilotAllowFlying && gAgentAvatarp->mInAir)
  251. {
  252. gAgent.setFlying(true);
  253. }
  254. LLVector3 at = gAgent.getAtAxis();
  255. LLVector3 agent_tgt = gAgent.getPosAgentFromGlobal(mAutoPilotTargetGlobal);
  256. LLVector3 direction = agent_tgt - gAgent.getPositionAgent();
  257. F32 target_dist = direction.length();
  258. if (target_dist >= mAutoPilotTargetDist)
  259. {
  260. ++mAutoPilotNoProgressFrameCount;
  261. }
  262. bool flying = gAgent.getFlying();
  263. S32 frame_delta;
  264. if (flying)
  265. {
  266. frame_delta = AUTOPILOT_MAX_TIME_NO_PROGRESS_FLY * gFPSClamped;
  267. }
  268. else
  269. {
  270. frame_delta = AUTOPILOT_MAX_TIME_NO_PROGRESS_WALK * gFPSClamped;
  271. }
  272. if (mAutoPilotNoProgressFrameCount > frame_delta)
  273. {
  274. stopAutoPilot();
  275. return;
  276. }
  277. mAutoPilotTargetDist = target_dist;
  278. // Make this a two-dimensional solution
  279. at.mV[VZ] = 0.f;
  280. at.normalize();
  281. direction.mV[VZ] = 0.f;
  282. F32 xy_distance = direction.normalize();
  283. F32 yaw = 0.f;
  284. if (mAutoPilotTargetDist > mAutoPilotStopDistance)
  285. {
  286. yaw = angle_between(gAgent.getAtAxis(), direction);
  287. }
  288. else if (mAutoPilotUseRotation)
  289. {
  290. // We are close now just aim at target facing
  291. yaw = angle_between(at, mAutoPilotTargetFacing);
  292. direction = mAutoPilotTargetFacing;
  293. }
  294. yaw = 4.f * yaw / gFPSClamped;
  295. // Figure out which direction to turn
  296. LLVector3 scratch(at % direction);
  297. if (scratch.mV[VZ] > 0.f)
  298. {
  299. gAgent.setControlFlags(AGENT_CONTROL_YAW_POS);
  300. }
  301. else
  302. {
  303. yaw = -yaw;
  304. gAgent.setControlFlags(AGENT_CONTROL_YAW_NEG);
  305. }
  306. *delta_yaw = yaw;
  307. // Compute when to start slowing down and when to stop
  308. F32 slow_distance;
  309. if (flying)
  310. {
  311. slow_distance = llmax(8.f, mAutoPilotStopDistance + 5.f);
  312. }
  313. else
  314. {
  315. slow_distance = llmax(3.f, mAutoPilotStopDistance + 2.f);
  316. }
  317. // If we are flying, handle autopilot points above or below you.
  318. if (flying && xy_distance < AUTOPILOT_HEIGHT_ADJUST_DISTANCE)
  319. {
  320. F64 curr_height = gAgentAvatarp->getPositionGlobal().mdV[VZ];
  321. F32 delta_z = (F32)(mAutoPilotTargetGlobal.mdV[VZ] - curr_height);
  322. F32 slope = delta_z / xy_distance;
  323. if (slope > 0.45f && delta_z > 6.f)
  324. {
  325. gAgent.setControlFlags(AGENT_CONTROL_FAST_UP |
  326. AGENT_CONTROL_UP_POS);
  327. }
  328. else if (slope > 0.002f && delta_z > 0.5f)
  329. {
  330. gAgent.setControlFlags(AGENT_CONTROL_UP_POS);
  331. }
  332. else if (slope < -0.45f && delta_z < -6.f &&
  333. curr_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND)
  334. {
  335. gAgent.setControlFlags(AGENT_CONTROL_FAST_UP |
  336. AGENT_CONTROL_UP_NEG);
  337. }
  338. else if (slope < -0.002f && delta_z < -0.5f &&
  339. curr_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND)
  340. {
  341. gAgent.setControlFlags(AGENT_CONTROL_UP_NEG);
  342. }
  343. }
  344. // Calculate delta rotation to target heading
  345. F32 delta_target_heading = angle_between(gAgent.getAtAxis(),
  346. mAutoPilotTargetFacing);
  347. if (xy_distance > slow_distance && yaw < F_PI / 10.f)
  348. {
  349. // Walking/flying fast
  350. gAgent.setControlFlags(AGENT_CONTROL_FAST_AT | AGENT_CONTROL_AT_POS);
  351. }
  352. else if (mAutoPilotTargetDist > mAutoPilotStopDistance)
  353. {
  354. U32 movement_flag = 0;
  355. // Walking/flying slow
  356. if (at * direction > 0.9f)
  357. {
  358. movement_flag = AGENT_CONTROL_AT_POS;
  359. }
  360. else if (at * direction < -0.9f)
  361. {
  362. movement_flag = AGENT_CONTROL_AT_NEG;
  363. }
  364. if (flying)
  365. {
  366. // Flying is too fast and has high inertia, artificially slow it
  367. // down. Do not update flags too often: server might not react.
  368. static U64 last_time_microsec = 0;
  369. U64 time_microsec = LLTimer::totalTime();
  370. U64 delta = time_microsec - last_time_microsec;
  371. // Fly during ~0-40 ms, stop during ~40-250 ms
  372. if (delta > 250000) // 250ms
  373. {
  374. // Reset even if !movement_flag
  375. last_time_microsec = time_microsec;
  376. }
  377. else if (delta > 40000) // 40 ms
  378. {
  379. gAgent.clearControlFlags(AGENT_CONTROL_AT_POS |
  380. AGENT_CONTROL_AT_POS);
  381. movement_flag = 0;
  382. }
  383. }
  384. if (movement_flag)
  385. {
  386. gAgent.setControlFlags(movement_flag);
  387. }
  388. }
  389. // Check to see if we need to keep rotating to target orientation
  390. if (mAutoPilotTargetDist < mAutoPilotStopDistance)
  391. {
  392. gAgent.setControlFlags(AGENT_CONTROL_STOP);
  393. if (!mAutoPilotUseRotation ||
  394. delta_target_heading < mAutoPilotRotationThreshold)
  395. {
  396. stopAutoPilot();
  397. }
  398. }
  399. }
  400. #if 0 // Not used
  401. // Draw a representation of current autopilot target
  402. void LLAgentPilot::renderAutoPilotTarget()
  403. {
  404. if (mAutoPilot)
  405. {
  406. F32 height_meters;
  407. LLVector3d target_global;
  408. gGL.matrixMode(LLRender::MM_MODELVIEW);
  409. gGL.pushMatrix();
  410. // Not textured
  411. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  412. // Lovely green
  413. gGL.color4f(0.f, 1.f, 1.f, 1.f);
  414. target_global = mAutoPilotTargetGlobal;
  415. gGL.translatef((F32)(target_global.mdV[VX]),
  416. (F32)(target_global.mdV[VY]),
  417. (F32)(target_global.mdV[VZ]));
  418. height_meters = 1.f;
  419. gGL.scalef(height_meters, height_meters, height_meters);
  420. gSphere.render();
  421. gGL.popMatrix();
  422. }
  423. }
  424. #endif
  425. bool LLAgentPilot::load(const std::string& filename)
  426. {
  427. if (filename.empty() || !LLStartUp::isLoggedIn())
  428. {
  429. return false;
  430. }
  431. std::string fullpath = filename;
  432. if (gDirUtil.getExtension(filename) != "plt")
  433. {
  434. fullpath += ".plt";
  435. }
  436. fullpath = gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT, fullpath);
  437. if (!LLFile::exists(fullpath))
  438. {
  439. return false;
  440. }
  441. llifstream file(fullpath.c_str());
  442. if (!file.is_open())
  443. {
  444. llwarns << "Could not open: " << fullpath << ". Aborted." << llendl;
  445. return false;
  446. }
  447. llinfos << "Loading pilot file: " << fullpath << llendl;
  448. S32 num_actions;
  449. file >> num_actions;
  450. mActions.reserve(num_actions);
  451. for (S32 i = 0; i < num_actions; ++i)
  452. {
  453. S32 action_type;
  454. Action new_action;
  455. file >> new_action.mTime >> action_type;
  456. file >> new_action.mTarget.mdV[VX] >> new_action.mTarget.mdV[VY]
  457. >> new_action.mTarget.mdV[VZ];
  458. new_action.mType = (EActionType)action_type;
  459. mActions.push_back(new_action);
  460. }
  461. file.close();
  462. return true;
  463. }
  464. bool LLAgentPilot::save(const std::string& filename)
  465. {
  466. S32 count = mActions.size();
  467. if (filename.empty() || !count || !LLStartUp::isLoggedIn())
  468. {
  469. return false;
  470. }
  471. std::string fullpath = filename;
  472. if (gDirUtil.getExtension(filename) != "plt")
  473. {
  474. fullpath += ".plt";
  475. }
  476. fullpath = gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT, fullpath);
  477. llofstream file(fullpath.c_str());
  478. if (!file.is_open())
  479. {
  480. llwarns << "Could not open: " << fullpath << " Aborted." << llendl;
  481. return false;
  482. }
  483. llinfos << "Saving to pilot file: " << fullpath << llendl;
  484. file << count << '\n';
  485. for (S32 i = 0; i < count; ++i)
  486. {
  487. file << mActions[i].mTime << "\t" << mActions[i].mType << "\t";
  488. file << std::setprecision(32) << mActions[i].mTarget.mdV[VX] << "\t"
  489. << mActions[i].mTarget.mdV[VY] << "\t"
  490. << mActions[i].mTarget.mdV[VZ] << '\n';
  491. }
  492. file.close();
  493. return true;
  494. }
  495. //static
  496. void LLAgentPilot::remove(const std::string& filename)
  497. {
  498. if (filename.empty() || !LLStartUp::isLoggedIn())
  499. {
  500. return;
  501. }
  502. std::string fullpath = filename;
  503. if (gDirUtil.getExtension(filename) != "plt")
  504. {
  505. fullpath += ".plt";
  506. }
  507. fullpath = gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT, fullpath);
  508. if (LLFile::exists(fullpath))
  509. {
  510. llinfos << "Deleting pilot file: " << fullpath << llendl;
  511. LLFile::remove(fullpath);
  512. }
  513. }
  514. bool LLAgentPilot::startRecord()
  515. {
  516. if (mRecording || mPlaying || !isAgentAvatarValid())
  517. {
  518. return false;
  519. }
  520. mActions.clear();
  521. mTimer.reset();
  522. addAction(STRAIGHT);
  523. mRecording = true;
  524. return true;
  525. }
  526. bool LLAgentPilot::stopRecord()
  527. {
  528. if (!mRecording || !isAgentAvatarValid())
  529. {
  530. return false;
  531. }
  532. addAction(STRAIGHT);
  533. mRecording = false;
  534. return true;
  535. }
  536. void LLAgentPilot::addAction(enum EActionType action_type)
  537. {
  538. if (!isAgentAvatarValid())
  539. {
  540. return;
  541. }
  542. LL_DEBUGS("AutoPilot") << "Adding waypoint: " << gAgent.getPositionGlobal()
  543. << LL_ENDL;
  544. Action action;
  545. action.mType = action_type;
  546. action.mTarget = gAgent.getPositionGlobal();
  547. action.mTime = mTimer.getElapsedTimeF32();
  548. mLastRecordTime = (F32)action.mTime;
  549. mActions.push_back(action);
  550. }
  551. bool LLAgentPilot::startPlayback(S32 num_runs, bool allow_flying)
  552. {
  553. if (mPlaying || mRecording || mActions.empty() || !isAgentAvatarValid())
  554. {
  555. return false;
  556. }
  557. mNumRuns = num_runs;
  558. mAllowFlying = allow_flying;
  559. mPlaying = true;
  560. mCurrentAction = 0;
  561. mTimer.reset();
  562. llinfos << "Starting playback, moving to waypoint 0." << llendl;
  563. if (!allow_flying)
  564. {
  565. gAgent.setFlying(false);
  566. }
  567. startAutoPilotGlobal(mActions[0].mTarget, "Playback", NULL, NULL, NULL,
  568. 0.5f, 0.03f, allow_flying);
  569. mStarted = false;
  570. return true;
  571. }
  572. bool LLAgentPilot::stopPlayback()
  573. {
  574. if (!mPlaying)
  575. {
  576. return false;
  577. }
  578. mPlaying = false;
  579. mCurrentAction = 0;
  580. mTimer.reset();
  581. stopAutoPilot();
  582. return true;
  583. }
  584. void LLAgentPilot::updateTarget()
  585. {
  586. if (mPlaying)
  587. {
  588. if (mCurrentAction < (S32)mActions.size())
  589. {
  590. if (mCurrentAction == 0)
  591. {
  592. if (mAutoPilot)
  593. {
  594. // Wait until we get to the first location before starting.
  595. return;
  596. }
  597. else if (!mStarted)
  598. {
  599. llinfos << "At start, beginning playback" << llendl;
  600. mTimer.reset();
  601. mStarted = true;
  602. }
  603. }
  604. if (mTimer.getElapsedTimeF32() > mActions[mCurrentAction].mTime)
  605. {
  606. #if 0
  607. stopAutoPilot();
  608. #endif
  609. if (++mCurrentAction < (S32)mActions.size())
  610. {
  611. startAutoPilotGlobal(mActions[mCurrentAction].mTarget,
  612. "Playback", NULL, NULL, NULL, 0.5f,
  613. 0.03f, mAllowFlying);
  614. }
  615. else
  616. {
  617. stopPlayback();
  618. if (--mNumRuns != 0)
  619. {
  620. llinfos << "Looping playback." << llendl;
  621. startPlayback(mNumRuns, mAllowFlying);
  622. }
  623. else
  624. {
  625. llinfos << "Done with all runs, disabling pilot."
  626. << llendl;
  627. }
  628. }
  629. }
  630. }
  631. else
  632. {
  633. stopPlayback();
  634. }
  635. }
  636. else if (mRecording && mTimer.getElapsedTimeF32() - mLastRecordTime > 1.f)
  637. {
  638. addAction(STRAIGHT);
  639. }
  640. }
  641. //static
  642. void LLAgentPilot::beginRecord(void*)
  643. {
  644. gAgentPilot.startRecord();
  645. }
  646. //static
  647. void LLAgentPilot::endRecord(void*)
  648. {
  649. if (gAgentPilot.stopRecord())
  650. {
  651. gAgentPilot.save(gSavedSettings.getString("AutoPilotFile"));
  652. }
  653. }
  654. //static
  655. void LLAgentPilot::forgetRecord(void*)
  656. {
  657. if (gAgentPilot.mRecording || gAgentPilot.mPlaying)
  658. {
  659. llwarns << "Cannot forget a record while recording or playing it."
  660. << llendl;
  661. return;
  662. }
  663. gAgentPilot.mActions.clear();
  664. remove(gSavedSettings.getString("AutoPilotFile"));
  665. }
  666. //static
  667. void LLAgentPilot::startPlayback(void*)
  668. {
  669. gAgentPilot.startPlayback(sLoop ? -1 : 1, sAllowFlying);
  670. }
  671. //static
  672. void LLAgentPilot::stopPlayback(void*)
  673. {
  674. gAgentPilot.stopPlayback();
  675. }