llhudeffectlookat.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /**
  2. * @file llhudeffectlookat.cpp
  3. * @brief LLHUDEffectLookAt 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 "llhudeffectlookat.h"
  34. #include "llanimationstates.h"
  35. #include "llcachename.h"
  36. #include "lldir.h"
  37. #include "llnotifications.h"
  38. #include "llrender.h"
  39. #include "llxmltree.h"
  40. #include "llmessage.h"
  41. #include "llagent.h"
  42. #include "lldrawable.h"
  43. //MK
  44. #include "mkrlinterface.h"
  45. //mk
  46. #include "llviewercontrol.h"
  47. #include "llviewerdisplay.h" // For hud_render_text()
  48. #include "llviewerobjectlist.h"
  49. #include "llviewerwindow.h"
  50. #include "llvoavatarself.h"
  51. bool LLHUDEffectLookAt::sDebugLookAt = false;
  52. U32 LLHUDEffectLookAt::sMaxLookAtBroadcastDist = 0;
  53. // packet layout
  54. constexpr S32 SOURCE_AVATAR = 0;
  55. constexpr S32 TARGET_OBJECT = 16;
  56. constexpr S32 TARGET_POS = 32;
  57. constexpr S32 LOOKAT_TYPE = 56;
  58. constexpr S32 PKT_SIZE = 57;
  59. constexpr F32 MAX_SENDS_PER_SEC = 4.f; // Throttle
  60. constexpr F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f;
  61. constexpr F32 MIN_TARGET_OFFSET_SQUARED = 0.0001f;
  62. // Cannot use actual F32_MAX, because we add this to the current frametime
  63. constexpr F32 MAX_TIMEOUT = F32_MAX * 0.5f;
  64. /**
  65. * Simple data class holding values for a particular type of attention.
  66. */
  67. class LLAttention
  68. {
  69. public:
  70. LLAttention()
  71. : mTimeout(0.f),
  72. mPriority(0.f)
  73. {
  74. }
  75. LLAttention(F32 timeout, F32 priority, const std::string& name,
  76. LLColor3 color)
  77. : mTimeout(timeout),
  78. mPriority(priority),
  79. mName(name),
  80. mColor(color)
  81. {
  82. }
  83. F32 mTimeout;
  84. F32 mPriority;
  85. LLColor3 mColor;
  86. std::string mName;
  87. };
  88. /**
  89. * Simple data class holding a list of attentions, one for every type.
  90. */
  91. class LLAttentionSet
  92. {
  93. public:
  94. LLAttentionSet(const LLAttention attentions[])
  95. {
  96. for (S32 i = 0; i < LOOKAT_NUM_TARGETS; ++i)
  97. {
  98. mAttentions[i] = attentions[i];
  99. }
  100. }
  101. LL_INLINE LLAttention& operator[](int idx) { return mAttentions[idx]; }
  102. public:
  103. LLAttention mAttentions[LOOKAT_NUM_TARGETS];
  104. };
  105. // Default attribute set data.
  106. // Used to initialize the global attribute set objects, one of which will be
  107. // refered to by the hud object at any given time.
  108. // Note that the values below are only the default values and that any or all of them
  109. // can be overwritten with customizing data from the XML file. The actual values below
  110. // are those that will give exactly the same look-at behavior as before the ability
  111. // to customize was added. - MG
  112. static const
  113. LLAttention
  114. // Default set of masculine attentions
  115. BOY_ATTS[] = {
  116. // LOOKAT_TARGET_NONE
  117. LLAttention(MAX_TIMEOUT, 0, "None",
  118. LLColor3(0.3f, 0.3f, 0.3f)),
  119. // LOOKAT_TARGET_IDLE
  120. LLAttention(3.f, 1, "Idle",
  121. LLColor3(0.5f, 0.5f, 0.5f)),
  122. // LOOKAT_TARGET_AUTO_LISTEN
  123. LLAttention(4.f, 3, "AutoListen",
  124. LLColor3(0.5f, 0.5f, 0.5f)),
  125. // LOOKAT_TARGET_FREELOOK
  126. LLAttention(2.f, 2, "FreeLook",
  127. LLColor3(0.5f, 0.5f, 0.9f)),
  128. // LOOKAT_TARGET_RESPOND
  129. LLAttention(4.f, 3, "Respond",
  130. LLColor3(0.f, 0.f, 0.f)),
  131. // LOOKAT_TARGET_HOVER
  132. LLAttention(1.f, 4, "Hover",
  133. LLColor3(0.5f, 0.9f, 0.5f)),
  134. // LOOKAT_TARGET_CONVERSATION
  135. LLAttention(MAX_TIMEOUT, 0, "Conversation",
  136. LLColor3(0.1f, 0.1f, 0.5f)),
  137. // LOOKAT_TARGET_SELECT
  138. LLAttention(MAX_TIMEOUT, 6, "Select",
  139. LLColor3(0.9f, 0.5f, 0.5f)),
  140. // LOOKAT_TARGET_FOCUS
  141. LLAttention(MAX_TIMEOUT, 6, "Focus",
  142. LLColor3(0.9f, 0.5f, 0.9f)),
  143. // LOOKAT_TARGET_MOUSELOOK
  144. LLAttention(MAX_TIMEOUT, 7, "Mouselook",
  145. LLColor3(0.9f, 0.9f, 0.5f)),
  146. // LOOKAT_TARGET_CLEAR
  147. LLAttention(0.f, 8, "Clear",
  148. LLColor3(1.f, 1.f, 1.f)),
  149. },
  150. // Default set of feminine attentions
  151. GIRL_ATTS[] = {
  152. // LOOKAT_TARGET_NONE
  153. LLAttention(MAX_TIMEOUT, 0, "None",
  154. LLColor3(0.3f, 0.3f, 0.3f)),
  155. // LOOKAT_TARGET_IDLE
  156. LLAttention(3.f, 1, "Idle",
  157. LLColor3(0.5f, 0.5f, 0.5f)),
  158. // LOOKAT_TARGET_AUTO_LISTEN
  159. LLAttention(4.f, 3, "AutoListen",
  160. LLColor3(0.5f, 0.5f, 0.5f)),
  161. // LOOKAT_TARGET_FREELOOK
  162. LLAttention(2.f, 2, "FreeLook",
  163. LLColor3(0.5f, 0.5f, 0.9f)),
  164. // LOOKAT_TARGET_RESPOND
  165. LLAttention(4.f, 3, "Respond",
  166. LLColor3(0.f, 0.f, 0.f)),
  167. // LOOKAT_TARGET_HOVER
  168. LLAttention(1.f, 4, "Hover",
  169. LLColor3(0.5f, 0.9f, 0.5f)),
  170. // LOOKAT_TARGET_CONVERSATION
  171. LLAttention(MAX_TIMEOUT, 0, "Conversation",
  172. LLColor3(0.1f, 0.1f, 0.5f)),
  173. // LOOKAT_TARGET_SELECT
  174. LLAttention(MAX_TIMEOUT, 6, "Select",
  175. LLColor3(0.9f, 0.5f, 0.5f)),
  176. // LOOKAT_TARGET_FOCUS
  177. LLAttention(MAX_TIMEOUT, 6, "Focus",
  178. LLColor3(0.9f, 0.5f, 0.9f)),
  179. // LOOKAT_TARGET_MOUSELOOK
  180. LLAttention(MAX_TIMEOUT, 7, "Mouselook",
  181. LLColor3(0.9f, 0.9f, 0.5f)),
  182. // LOOKAT_TARGET_CLEAR
  183. LLAttention(0.f, 8, "Clear",
  184. LLColor3(1.f, 1.f, 1.f)),
  185. };
  186. static LLAttentionSet sBoyAttentions(BOY_ATTS);
  187. static LLAttentionSet sGirlAttentions(GIRL_ATTS);
  188. static bool loadGender(LLXmlTreeNode* gender)
  189. {
  190. if (!gender)
  191. {
  192. return false;
  193. }
  194. std::string str;
  195. gender->getAttributeString("name", str);
  196. LLAttentionSet& attentions =
  197. str.compare("Masculine") == 0 ? sBoyAttentions : sGirlAttentions;
  198. for (LLXmlTreeNode* attention_node = gender->getChildByName("param");
  199. attention_node; attention_node = gender->getNextNamedChild())
  200. {
  201. S32 index;
  202. attention_node->getAttributeString("attention", str);
  203. if (str == "idle")
  204. {
  205. index = LOOKAT_TARGET_IDLE;
  206. }
  207. else if (str == "auto_listen")
  208. {
  209. index = LOOKAT_TARGET_AUTO_LISTEN;
  210. }
  211. else if (str == "freelook")
  212. {
  213. index = LOOKAT_TARGET_FREELOOK;
  214. }
  215. else if (str == "respond")
  216. {
  217. index = LOOKAT_TARGET_RESPOND;
  218. }
  219. else if (str == "hover")
  220. {
  221. index = LOOKAT_TARGET_HOVER;
  222. }
  223. else if (str == "conversation")
  224. {
  225. index = LOOKAT_TARGET_CONVERSATION;
  226. }
  227. else if (str == "select")
  228. {
  229. index = LOOKAT_TARGET_SELECT;
  230. }
  231. else if (str == "focus")
  232. {
  233. index = LOOKAT_TARGET_FOCUS;
  234. }
  235. else if (str == "mouselook")
  236. {
  237. index = LOOKAT_TARGET_MOUSELOOK;
  238. }
  239. else
  240. {
  241. return false;
  242. }
  243. LLAttention* attention = &attentions[index];
  244. F32 priority, timeout;
  245. attention_node->getAttributeF32("priority", priority);
  246. attention_node->getAttributeF32("timeout", timeout);
  247. if (timeout < 0)
  248. {
  249. timeout = MAX_TIMEOUT;
  250. }
  251. attention->mPriority = priority;
  252. attention->mTimeout = timeout;
  253. }
  254. return true;
  255. }
  256. static bool loadAttentions()
  257. {
  258. static bool first_time = true;
  259. if (!first_time)
  260. {
  261. // Maybe not ideal but otherwise it can continue to fail forever.
  262. return true;
  263. }
  264. first_time = false;
  265. std::string filename = gDirUtil.getFullPath(LL_PATH_CHARACTER,
  266. "attentions.xml");
  267. LLXmlTree xml_tree;
  268. bool success = xml_tree.parseFile(filename, false);
  269. if (!success)
  270. {
  271. return false;
  272. }
  273. LLXmlTreeNode* root = xml_tree.getRoot();
  274. if (!root)
  275. {
  276. return false;
  277. }
  278. //-------------------------------------------------------------------------
  279. // <linden_attentions version="1.0"> (root)
  280. //-------------------------------------------------------------------------
  281. if (!root->hasName("linden_attentions"))
  282. {
  283. llwarns << "Invalid linden_attentions file header: " << filename
  284. << llendl;
  285. return false;
  286. }
  287. static LLStdStringHandle version_string =
  288. LLXmlTree::addAttributeString("version");
  289. std::string version;
  290. if (!root->getFastAttributeString(version_string, version) ||
  291. version != "1.0")
  292. {
  293. llwarns << "Invalid linden_attentions file version: " << version
  294. << llendl;
  295. return false;
  296. }
  297. //-------------------------------------------------------------------------
  298. // <gender>
  299. //-------------------------------------------------------------------------
  300. for (LLXmlTreeNode* child = root->getChildByName("gender"); child;
  301. child = root->getNextNamedChild())
  302. {
  303. if (!loadGender(child))
  304. {
  305. return false;
  306. }
  307. }
  308. return true;
  309. }
  310. LLHUDEffectLookAt::LLHUDEffectLookAt(U8 type)
  311. : LLHUDEffect(type),
  312. mKillTime(0.f),
  313. mLastSendTime(0.f),
  314. mNotifyTime(0.f),
  315. mNotified(false)
  316. {
  317. clearLookAtTarget();
  318. // Parse the default sets
  319. loadAttentions();
  320. // Initialize current attention set. Switches when avatar sex changes.
  321. mAttentions = &sGirlAttentions;
  322. }
  323. //static
  324. void LLHUDEffectLookAt::updateSettings()
  325. {
  326. if (gSavedSettings.getBool("PrivateLookAt"))
  327. {
  328. sMaxLookAtBroadcastDist = gSavedSettings.getU32("PrivateLookAtLimit");
  329. }
  330. else
  331. {
  332. sMaxLookAtBroadcastDist = U32_MAX;
  333. }
  334. }
  335. void LLHUDEffectLookAt::packData(LLMessageSystem* mesgsys)
  336. {
  337. // Pack the default data
  338. LLHUDEffect::packData(mesgsys);
  339. // Pack the type-specific data. Uses a fun packed binary format. Whee !
  340. U8 packed_data[PKT_SIZE];
  341. memset(packed_data, 0, PKT_SIZE);
  342. if (mSourceObject)
  343. {
  344. htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData,
  345. MVT_LLUUID, 16);
  346. }
  347. else
  348. {
  349. htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData,
  350. MVT_LLUUID, 16);
  351. }
  352. // Pack both target object and position; position interpreted as offset if
  353. // target object is non-null.
  354. if (mTargetObject)
  355. {
  356. htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData,
  357. MVT_LLUUID, 16);
  358. }
  359. else
  360. {
  361. htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData,
  362. MVT_LLUUID, 16);
  363. }
  364. htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV,
  365. MVT_LLVector3d, 24);
  366. U8 lookAtTypePacked = (U8)mTargetType;
  367. htonmemcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1);
  368. mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
  369. mLastSendTime = mTimer.getElapsedTimeF32();
  370. }
  371. void LLHUDEffectLookAt::unpackData(LLMessageSystem* mesgsys, S32 blocknum)
  372. {
  373. LLVector3d new_target;
  374. U8 packed_data[PKT_SIZE];
  375. LLUUID data_id;
  376. mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, data_id, blocknum);
  377. if (gAgent.mLookAt.notNull() && data_id == gAgent.mLookAt->getID())
  378. {
  379. return;
  380. }
  381. LLHUDEffect::unpackData(mesgsys, blocknum);
  382. LLUUID source_id;
  383. LLUUID target_id;
  384. S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum,
  385. _PREHASH_TypeData);
  386. if (size != PKT_SIZE)
  387. {
  388. llwarns << "LookAt effect with bad size " << size << llendl;
  389. return;
  390. }
  391. mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data,
  392. PKT_SIZE, blocknum);
  393. htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
  394. LLVOAvatar* avatarp = gObjectList.findAvatar(source_id);
  395. if (!avatarp) // It does happen
  396. {
  397. return;
  398. }
  399. setSourceObject(avatarp);
  400. htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
  401. htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
  402. LLViewerObject* objp = gObjectList.findObject(target_id);
  403. if (objp)
  404. {
  405. setTargetObjectAndOffset(objp, new_target);
  406. }
  407. else if (target_id.isNull())
  408. {
  409. setTargetPosGlobal(new_target);
  410. }
  411. U8 type_unpacked = 0;
  412. htonmemcpy(&type_unpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1);
  413. mTargetType = (ELookAtType)type_unpacked;
  414. if (mTargetType == LOOKAT_TARGET_NONE)
  415. {
  416. clearLookAtTarget();
  417. }
  418. }
  419. void LLHUDEffectLookAt::setTargetObjectAndOffset(LLViewerObject* objp,
  420. const LLVector3d& offset)
  421. {
  422. mTargetObject = objp;
  423. mTargetOffsetGlobal = offset;
  424. mNotifyTime = 0.f;
  425. }
  426. void LLHUDEffectLookAt::setTargetPosGlobal(const LLVector3d& target_pos_global)
  427. {
  428. mTargetObject = NULL;
  429. mTargetOffsetGlobal = target_pos_global;
  430. mNotifyTime = 0.f;
  431. }
  432. // Called by agent logic to set look at behavior locally, and propagate to sim
  433. bool LLHUDEffectLookAt::setLookAt(ELookAtType target_type,
  434. LLViewerObject* object,
  435. LLVector3 position)
  436. {
  437. if (!mSourceObject)
  438. {
  439. return false;
  440. }
  441. if (target_type >= LOOKAT_NUM_TARGETS)
  442. {
  443. llwarns << "Bad target_type " << (S32)target_type << " - ignoring."
  444. << llendl;
  445. return false;
  446. }
  447. // Must be same or higher priority than existing effect
  448. if ((*mAttentions)[target_type].mPriority <
  449. (*mAttentions)[mTargetType].mPriority)
  450. {
  451. return false;
  452. }
  453. // If type of lookat behavior or target object has changed...
  454. if (target_type != mTargetType || object != mTargetObject ||
  455. // or if lookat position has moved a certain amount and we do not have
  456. // just sent an update
  457. (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE &&
  458. mTimer.getElapsedTimeF32() - mLastSendTime > 1.f / MAX_SENDS_PER_SEC))
  459. {
  460. mLastSentOffsetGlobal = position;
  461. F32 timeout = (*mAttentions)[target_type].mTimeout;
  462. setDuration(timeout);
  463. setNeedsSendToSim(true);
  464. }
  465. if (target_type == LOOKAT_TARGET_CLEAR)
  466. {
  467. clearLookAtTarget();
  468. }
  469. else
  470. {
  471. mTargetType = target_type;
  472. mTargetObject = object;
  473. if (object)
  474. {
  475. mTargetOffsetGlobal.set(position);
  476. }
  477. else
  478. {
  479. mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position);
  480. }
  481. mKillTime = mTimer.getElapsedTimeF32() + mDuration;
  482. // This is *required* to update the sim *at once* (even though update()
  483. // is called at each frame), else your avatar's eyes might end up
  484. // looking behind its head in everyone else's viewer... HB
  485. update();
  486. }
  487. return true;
  488. }
  489. void LLHUDEffectLookAt::clearLookAtTarget()
  490. {
  491. mTargetObject = NULL;
  492. mTargetOffsetGlobal.clear();
  493. mTargetType = LOOKAT_TARGET_NONE;
  494. mNotifyTime = 0.f;
  495. if (mSourceObject.notNull())
  496. {
  497. LLVOAvatar* avatarp = (LLVOAvatar*)mSourceObject.get();
  498. avatarp->stopMotion(ANIM_AGENT_HEAD_ROT);
  499. }
  500. }
  501. void LLHUDEffectLookAt::markDead()
  502. {
  503. if (mSourceObject.notNull())
  504. {
  505. LLVOAvatar* avatarp = (LLVOAvatar*)mSourceObject.get();
  506. avatarp->removeAnimationData("LookAtPoint");
  507. }
  508. mSourceObject = NULL;
  509. clearLookAtTarget();
  510. LLHUDEffect::markDead();
  511. }
  512. void LLHUDEffectLookAt::setSourceObject(LLViewerObject* objectp)
  513. {
  514. // Restrict source objects to avatars
  515. if (objectp && objectp->isAvatar())
  516. {
  517. LLHUDEffect::setSourceObject(objectp);
  518. }
  519. }
  520. void LLHUDEffectLookAt::render()
  521. {
  522. static const LLFontGL* font = LLFontGL::getFontSansSerif();
  523. if (!isAgentAvatarValid()) return;
  524. if (sDebugLookAt && mSourceObject.notNull())
  525. {
  526. //MK
  527. if (gRLenabled && gRLInterface.mVisionRestricted)
  528. {
  529. return;
  530. }
  531. //mk
  532. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  533. LLVOAvatar* avatarp = (LLVOAvatar*)mSourceObject.get();
  534. LLVector3 lookerpos = avatarp->mHeadp->getWorldPosition();
  535. LLVector3 target = mTargetPos + lookerpos;
  536. gGL.matrixMode(LLRender::MM_MODELVIEW);
  537. gGL.pushMatrix();
  538. gGL.translatef(target.mV[VX], target.mV[VY], target.mV[VZ]);
  539. gGL.scalef(0.3f, 0.3f, 0.3f);
  540. gGL.begin(LLRender::LINES);
  541. {
  542. LLColor3 color = (*mAttentions)[mTargetType].mColor;
  543. gGL.color3f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]);
  544. gGL.vertex3f(-1.f, 0.f, 0.f);
  545. gGL.vertex3f(1.f, 0.f, 0.f);
  546. gGL.vertex3f(0.f, -1.f, 0.f);
  547. gGL.vertex3f(0.f, 1.f, 0.f);
  548. gGL.vertex3f(0.f, 0.f, -1.f);
  549. gGL.vertex3f(0.f, 0.f, 1.f);
  550. }
  551. gGL.end();
  552. gGL.popMatrix();
  553. //MK
  554. if (gRLenabled &&
  555. (gRLInterface.mContainsShownames ||
  556. gRLInterface.mContainsShownametags))
  557. {
  558. return;
  559. }
  560. //mk
  561. LLVector3 offset = gAgentAvatarp->mHeadp->getWorldPosition() -
  562. lookerpos;
  563. if (offset.length() <= (F32)sMaxLookAtBroadcastDist)
  564. {
  565. // Render name
  566. LLWString text(utf8str_to_wstring(avatarp->getFullname(true)));
  567. offset = (gAgent.getCameraPositionAgent() - target) * 0.5f;
  568. offset.normalize();
  569. LLVector3 shadow_offset = offset * 0.99f;
  570. F32 delta_x = -0.5f * font->getWidthF32(text.c_str());
  571. LLGLEnable gl_blend(GL_BLEND);
  572. gGL.pushMatrix();
  573. gViewerWindowp->setupViewport();
  574. hud_render_text(text, target + shadow_offset, *font,
  575. LLFontGL::NORMAL, delta_x + 1.f, -1.f,
  576. LLColor4::black, false);
  577. hud_render_text(text, target + offset, *font,
  578. LLFontGL::NORMAL, delta_x, 0.f,
  579. (*mAttentions)[mTargetType].mColor, false);
  580. gGL.popMatrix();
  581. }
  582. }
  583. }
  584. static void looked_at_cb(const LLUUID& id, const LLAvatarName& av_name)
  585. {
  586. std::string fullname;
  587. if (LLAvatarNameCache::useDisplayNames())
  588. {
  589. if (LLAvatarNameCache::useDisplayNames() == 2)
  590. {
  591. fullname = av_name.mDisplayName;
  592. }
  593. else
  594. {
  595. fullname = av_name.getNames();
  596. }
  597. }
  598. else
  599. {
  600. fullname = av_name.getLegacyName();
  601. }
  602. LLSD args;
  603. args["NAME"] = fullname;
  604. gNotifications.add("LookedAt", args);
  605. }
  606. void LLHUDEffectLookAt::update()
  607. {
  608. if (!isAgentAvatarValid()) return;
  609. // If the target object is dead, set the target object to NULL
  610. if (mTargetObject.notNull() && mTargetObject->isDead())
  611. {
  612. clearLookAtTarget();
  613. }
  614. // If source avatar is null or dead, mark self as dead and return
  615. if (mSourceObject.isNull() || mSourceObject->isDead())
  616. {
  617. markDead();
  618. return;
  619. }
  620. // Make sure the proper set of avatar attention are currently being used.
  621. LLVOAvatar* avatarp = (LLVOAvatar*)((LLViewerObject*)mSourceObject);
  622. // For now the first cut will just switch on sex. future development could
  623. // adjust timeouts according to avatar age and/or other features.
  624. mAttentions = avatarp->getSex() == SEX_MALE ? &sBoyAttentions
  625. : &sGirlAttentions;
  626. F32 time = mTimer.getElapsedTimeF32();
  627. // Clear out the effect if time is up
  628. if (mKillTime != 0.f && time > mKillTime &&
  629. mTargetType != LOOKAT_TARGET_NONE)
  630. {
  631. clearLookAtTarget();
  632. // Look at timed out (only happens on own avatar), so tell everyone
  633. setNeedsSendToSim(true);
  634. }
  635. if (mTargetType != LOOKAT_TARGET_NONE && calcTargetPosition())
  636. {
  637. LLMotion* head_motion = avatarp->findMotion(ANIM_AGENT_HEAD_ROT);
  638. if (!head_motion || head_motion->isStopped())
  639. {
  640. avatarp->startMotion(ANIM_AGENT_HEAD_ROT);
  641. }
  642. }
  643. LLViewerObject* agentp = (LLViewerObject*)gAgentAvatarp;
  644. if (!mNotified && mTargetType == LOOKAT_TARGET_FOCUS &&
  645. mSourceObject != agentp && mTargetObject &&
  646. (mTargetObject == agentp ||
  647. (mTargetObject->isAttachment() &&
  648. mTargetObject->getRoot() == agentp)))
  649. {
  650. if (mNotifyTime == 0.f)
  651. {
  652. //MK
  653. if (!gRLenabled || !gRLInterface.mVisionRestricted)
  654. //mk
  655. {
  656. static LLCachedControl<U32> delay(gSavedSettings,
  657. "LookAtNotifyDelay");
  658. if (delay > 0)
  659. {
  660. mNotifyTime = time + (F32)delay;
  661. }
  662. }
  663. }
  664. else if (time >= mNotifyTime)
  665. {
  666. LLVector3 offset = gAgentAvatarp->mHeadp->getWorldPosition() -
  667. avatarp->mHeadp->getWorldPosition();
  668. if (offset.length() <= (F32)sMaxLookAtBroadcastDist &&
  669. //MK
  670. (!gRLenabled ||
  671. (!gRLInterface.mContainsShownames &&
  672. !gRLInterface.mContainsShownametags &&
  673. !gRLInterface.mVisionRestricted)))
  674. //mk
  675. {
  676. mNotified = true;
  677. LLAvatarNameCache::get(avatarp->getID(),
  678. boost::bind(&looked_at_cb, _1, _2));
  679. }
  680. }
  681. }
  682. if (sDebugLookAt)
  683. {
  684. //MK
  685. if (gRLenabled && gRLInterface.mVisionRestricted)
  686. {
  687. return;
  688. }
  689. //mk
  690. avatarp->addDebugText((*mAttentions)[mTargetType].mName);
  691. }
  692. }
  693. // Initializes the mTargetPos member from the current mSourceObject,
  694. // mTargetObject and possibly mTargetOffsetGlobal. When mTargetObject is
  695. // another avatar, it sets mTargetPos to be their eyes.
  696. // Has the side-effect of also calling setAnimationData("LookAtPoint") with the
  697. // new mTargetPos on the source object which is assumed to be an avatar.
  698. // Returns whether we successfully calculated a finite target position.
  699. bool LLHUDEffectLookAt::calcTargetPosition()
  700. {
  701. LLVector3 local_offset;
  702. LLViewerObject* target_obj = (LLViewerObject*)mTargetObject;
  703. if (target_obj)
  704. {
  705. local_offset.set(mTargetOffsetGlobal);
  706. }
  707. else
  708. {
  709. local_offset = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal);
  710. }
  711. LLVOAvatar* avatarp = (LLVOAvatar*)mSourceObject.get();
  712. if (target_obj && target_obj->mDrawable.notNull())
  713. {
  714. LLQuaternion target_rot;
  715. if (target_obj->isAvatar())
  716. {
  717. LLVOAvatar* target_av = (LLVOAvatar*)target_obj;
  718. bool looking_at_self = avatarp->isSelf() && target_av->isSelf();
  719. // If selecting self, stare forward
  720. if (looking_at_self &&
  721. mTargetOffsetGlobal.lengthSquared() < MIN_TARGET_OFFSET_SQUARED)
  722. {
  723. // Set the lookat point in front of the avatar
  724. mTargetOffsetGlobal.set(5.0, 0.0, 0.0);
  725. local_offset.set(mTargetOffsetGlobal);
  726. }
  727. // Look the other avatar in the eye. note: what happens if target
  728. // is self ? -MG
  729. mTargetPos = target_av->mHeadp->getWorldPosition();
  730. if (mTargetType == LOOKAT_TARGET_MOUSELOOK ||
  731. mTargetType == LOOKAT_TARGET_FREELOOK)
  732. {
  733. // mouselook and freelook target offsets are absolute
  734. target_rot = LLQuaternion::DEFAULT;
  735. }
  736. else if (looking_at_self && gAgent.cameraCustomizeAvatar())
  737. {
  738. // *NOTE: We have to do this because animation overrides do not
  739. // set lookat behavior.
  740. // *TODO: animation overrides for lookat behavior.
  741. target_rot = target_av->mPelvisp->getWorldRotation();
  742. }
  743. else
  744. {
  745. target_rot = target_av->mRoot->getWorldRotation();
  746. }
  747. }
  748. else // Target obj is not an avatar
  749. {
  750. if (target_obj->mDrawable->getGeneration() == -1)
  751. {
  752. mTargetPos = target_obj->getPositionAgent();
  753. target_rot = target_obj->getWorldRotation();
  754. }
  755. else
  756. {
  757. mTargetPos = target_obj->getRenderPosition();
  758. target_rot = target_obj->getRenderRotation();
  759. }
  760. }
  761. mTargetPos += local_offset * target_rot;
  762. }
  763. else // No target obj or it is not drawable
  764. {
  765. mTargetPos = local_offset;
  766. }
  767. mTargetPos -= avatarp->mHeadp->getWorldPosition();
  768. if (!mTargetPos.isFinite())
  769. {
  770. return false;
  771. }
  772. avatarp->setAnimationData("LookAtPoint", (void*)&mTargetPos);
  773. return true;
  774. }