llviewermediafocus.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762
  1. /**
  2. * @file llviewermediafocus.cpp
  3. * @brief Governs focus on media prims and implements the media HUD panel
  4. *
  5. * $LicenseInfo:firstyear=2003&license=viewergpl$
  6. *
  7. * Copyright (c) 2003-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 "llviewermediafocus.h"
  34. #include "llbutton.h"
  35. #include "lleditmenuhandler.h"
  36. #include "llkeyboard.h"
  37. #include "llmediaentry.h"
  38. #include "llpanel.h"
  39. #include "llparcel.h"
  40. #include "llpluginclassmedia.h"
  41. #include "llrender.h"
  42. #include "llsliderctrl.h"
  43. #include "lltextureentry.h"
  44. #include "lluictrlfactory.h"
  45. #include "llagent.h"
  46. #include "llappviewer.h" // For gFrameTimeSeconds
  47. #include "llchatbar.h" // For gChatBarp and CHAT_BAR_HEIGHT
  48. #include "lldrawable.h"
  49. #include "llface.h"
  50. #include "llfloatertools.h" // For LLFloaterTools::isVisible()
  51. #include "llhudview.h"
  52. #include "llselectmgr.h"
  53. #include "lltoolbar.h" // For LLToolBar::isVisible()
  54. #include "lltoolpie.h"
  55. #include "llviewercamera.h"
  56. #include "llviewercontrol.h"
  57. #include "llviewerdisplay.h" // For get_hud_matrices()
  58. #include "llviewermedia.h"
  59. #include "llviewerobjectlist.h"
  60. #include "llviewerparcelmgr.h"
  61. #include "llviewerwindow.h"
  62. #include "llvovolume.h"
  63. #include "llweb.h"
  64. ///////////////////////////////////////////////////////////////////////////////
  65. // LLPanelMediaHUD class
  66. // Note: it used to be in a separate llpanelmediahud.h/cpp module, but is only
  67. // consumed by LLViewerMediaFocus, so it is best kept here. HB
  68. ///////////////////////////////////////////////////////////////////////////////
  69. constexpr F32 ZOOM_MEDIUM_PADDING = 1.2f;
  70. class LLPanelMediaHUD final : public LLPanel
  71. {
  72. protected:
  73. LOG_CLASS(LLPanelMediaHUD);
  74. public:
  75. LLPanelMediaHUD();
  76. bool postBuild() override;
  77. void draw() override;
  78. void setAlpha(F32 alpha) override;
  79. bool handleScrollWheel(S32 x, S32 y, S32 clicks) override;
  80. void updateShape();
  81. bool isMouseOver();
  82. LL_INLINE void setMediaFocus(bool b) { mMediaFocus = b; }
  83. void nextZoomLevel();
  84. LL_INLINE void resetZoomLevel() { mCurrentZoom = ZOOM_NONE; }
  85. LL_INLINE bool isZoomed() const
  86. {
  87. return mCurrentZoom == ZOOM_MEDIUM;
  88. }
  89. LL_INLINE LLHandle<LLPanelMediaHUD> getHandle() const
  90. {
  91. return mPanelHandle;
  92. }
  93. enum EZoomLevel
  94. {
  95. ZOOM_NONE = 0,
  96. ZOOM_MEDIUM = 1,
  97. ZOOM_END
  98. };
  99. enum EScrollDir
  100. {
  101. SCROLL_UP = 0,
  102. SCROLL_DOWN,
  103. SCROLL_LEFT,
  104. SCROLL_RIGHT,
  105. SCROLL_NONE
  106. };
  107. void setMediaFace(LLPointer<LLViewerObject> objectp, S32 face = 0,
  108. viewer_media_t mediap = NULL,
  109. LLVector3 pick_normal = LLVector3::zero);
  110. private:
  111. static void onClickClose(void* user_data);
  112. static void onClickBack(void* user_data);
  113. static void onClickForward(void* user_data);
  114. static void onClickHome(void* user_data);
  115. static void onClickOpen(void* user_data);
  116. static void onClickReload(void* user_data);
  117. static void onClickPlay(void* user_data);
  118. static void onClickPause(void* user_data);
  119. static void onClickStop(void* user_data);
  120. static void onClickMediaStop(void* user_data);
  121. static void onClickZoom(void* user_data);
  122. static void onClickVolume(void* user_data);
  123. static void onScrollUp(void* user_data);
  124. static void onScrollUpHeld(void* user_data);
  125. static void onScrollLeft(void* user_data);
  126. static void onScrollLeftHeld(void* user_data);
  127. static void onScrollRight(void* user_data);
  128. static void onScrollRightHeld(void* user_data);
  129. static void onScrollDown(void* user_data);
  130. static void onScrollDownHeld(void* user_data);
  131. static void onScrollStop(void* user_data);
  132. static void onHoverVolume(void* user_data);
  133. static void onHoverSlider(LLUICtrl* ctrl, void* user_data);
  134. static void onVolumeChange(LLUICtrl* ctrl, void* user_data);
  135. LLViewerMediaImpl* getTargetMediaImpl();
  136. LLViewerObject* getTargetObject();
  137. LLPluginClassMedia* getTargetMediaPlugin();
  138. private:
  139. LLUUID mTargetImplID;
  140. LLUUID mTargetObjectID;
  141. LLRootHandle<LLPanelMediaHUD> mPanelHandle;
  142. LLPanel* mFocusedControls;
  143. LLPanel* mHoverControls;
  144. LLButton* mCloseButton;
  145. LLButton* mBackButton;
  146. LLButton* mForwardButton;
  147. LLButton* mHomeButton;
  148. LLButton* mOpenButton;
  149. LLButton* mOpenButton2;
  150. LLButton* mReloadButton;
  151. LLButton* mPlayButton;
  152. LLButton* mPauseButton;
  153. LLButton* mStopButton;
  154. LLButton* mMediaStopButton;
  155. LLButton* mMediaVolumeButton;
  156. LLButton* mMediaMutedButton;
  157. LLButton* mZoomButton;
  158. LLButton* mUnzoomButton;
  159. LLButton* mZoomButton2;
  160. LLSliderCtrl* mVolumeSlider;
  161. LLView* mMediaFullView;
  162. std::string mOpenButtonTooltip;
  163. LLCoordWindow mLastCursorPos;
  164. LLFrameTimer mMouseMoveTimer;
  165. LLFrameTimer mFadeTimer;
  166. LLFrameTimer mVolumeSliderTimer;
  167. LLVector3 mTargetObjectNormal;
  168. S32 mTargetObjectFace;
  169. F32 mLastVolume;
  170. F32 mControlFadeTime;
  171. EZoomLevel mCurrentZoom;
  172. EScrollDir mScrollState;
  173. bool mTargetIsHUDObject;
  174. bool mMediaFocus;
  175. bool mLargeControls;
  176. bool mHasTimeControl;
  177. static LLUUID sLastTargetImplID;
  178. static EZoomLevel sLastMediaZoom;
  179. };
  180. //static
  181. LLUUID LLPanelMediaHUD::sLastTargetImplID;
  182. LLPanelMediaHUD::EZoomLevel LLPanelMediaHUD::sLastMediaZoom =
  183. LLPanelMediaHUD::ZOOM_NONE;
  184. LLPanelMediaHUD::LLPanelMediaHUD()
  185. : mTargetObjectFace(0),
  186. mTargetIsHUDObject(false),
  187. mControlFadeTime(3.f),
  188. mLastVolume(0.f),
  189. mMediaFocus(false),
  190. mLargeControls(false),
  191. mHasTimeControl(false),
  192. mCurrentZoom(ZOOM_NONE),
  193. mScrollState(SCROLL_NONE)
  194. {
  195. LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_hud.xml");
  196. mMouseMoveTimer.reset();
  197. LL_DEBUGS("MediaHUD") << "Stopping the fading timer." << LL_ENDL;
  198. mFadeTimer.stop();
  199. mPanelHandle.bind(this);
  200. }
  201. //virtual
  202. bool LLPanelMediaHUD::postBuild()
  203. {
  204. mMediaFullView = getChild<LLView>("media_full_view");
  205. mFocusedControls = getChild<LLPanel>("media_focused_controls");
  206. mHoverControls = getChild<LLPanel>("media_hover_controls");
  207. mCloseButton = getChild<LLButton>("close");
  208. mCloseButton->setClickedCallback(onClickClose, this);
  209. mBackButton = getChild<LLButton>("back");
  210. mBackButton->setClickedCallback(onClickBack, this);
  211. mForwardButton = getChild<LLButton>("fwd");
  212. mForwardButton->setClickedCallback(onClickForward, this);
  213. mHomeButton = getChild<LLButton>("home");
  214. mHomeButton->setClickedCallback(onClickHome, this);
  215. mStopButton = getChild<LLButton>("stop");
  216. mStopButton->setClickedCallback(onClickStop, this);
  217. mMediaStopButton = getChild<LLButton>("media_stop");
  218. mMediaStopButton->setClickedCallback(onClickMediaStop, this);
  219. mReloadButton = getChild<LLButton>("reload");
  220. mReloadButton->setClickedCallback(onClickReload, this);
  221. mPlayButton = getChild<LLButton>("play");
  222. mPlayButton->setClickedCallback(onClickPlay, this);
  223. mPauseButton = getChild<LLButton>("pause");
  224. mPauseButton->setClickedCallback(onClickPause, this);
  225. mOpenButton = getChild<LLButton>("new_window");
  226. mOpenButton->setClickedCallback(onClickOpen, this);
  227. mOpenButtonTooltip = mOpenButton->getToolTip();
  228. mMediaVolumeButton = getChild<LLButton>("volume");
  229. mMediaVolumeButton->setClickedCallback(onClickVolume, this);
  230. mMediaVolumeButton->setMouseHoverCallback(onHoverVolume);
  231. mMediaMutedButton = getChild<LLButton>("muted");
  232. mMediaMutedButton->setClickedCallback(onClickVolume, this);
  233. mMediaMutedButton->setMouseHoverCallback(onHoverVolume);
  234. mVolumeSlider = getChild<LLSliderCtrl>("volume_slider");
  235. mVolumeSlider->setCommitCallback(onVolumeChange);
  236. mVolumeSlider->setCallbackUserData(this);
  237. mVolumeSlider->setMouseHoverCallback(onHoverSlider);
  238. mZoomButton = getChild<LLButton>("zoom_frame");
  239. mZoomButton->setClickedCallback(onClickZoom, this);
  240. mUnzoomButton = getChild<LLButton>("unzoom_frame");
  241. mUnzoomButton->setClickedCallback(onClickZoom, this);
  242. mOpenButton2 = getChild<LLButton>("new_window_hover");
  243. mOpenButton2->setClickedCallback(onClickOpen, this);
  244. mZoomButton2 = getChild<LLButton>("zoom_frame_hover");
  245. mZoomButton2->setClickedCallback(onClickZoom, this);
  246. LLButton* scroll_up_btn = getChild<LLButton>("scrollup");
  247. scroll_up_btn->setClickedCallback(onScrollUp, this);
  248. scroll_up_btn->setHeldDownCallback(onScrollUpHeld);
  249. scroll_up_btn->setMouseUpCallback(onScrollStop);
  250. LLButton* scroll_left_btn = getChild<LLButton>("scrollleft");
  251. scroll_left_btn->setClickedCallback(onScrollLeft, this);
  252. scroll_left_btn->setHeldDownCallback(onScrollLeftHeld);
  253. scroll_left_btn->setMouseUpCallback(onScrollStop);
  254. LLButton* scroll_right_btn = getChild<LLButton>("scrollright");
  255. scroll_right_btn->setClickedCallback(onScrollRight, this);
  256. scroll_right_btn->setHeldDownCallback(onScrollLeftHeld);
  257. scroll_right_btn->setMouseUpCallback(onScrollStop);
  258. LLButton* scroll_down_btn = getChild<LLButton>("scrolldown");
  259. scroll_down_btn->setClickedCallback(onScrollDown, this);
  260. scroll_down_btn->setHeldDownCallback(onScrollDownHeld);
  261. scroll_down_btn->setMouseUpCallback(onScrollStop);
  262. // Clicks on HUD buttons do not remove keyboard focus from media
  263. setIsChrome(true);
  264. return true;
  265. }
  266. void LLPanelMediaHUD::setMediaFace(LLPointer<LLViewerObject> objectp,
  267. S32 face, viewer_media_t mediap,
  268. LLVector3 pick_normal)
  269. {
  270. if (mediap.notNull() && objectp.notNull())
  271. {
  272. mTargetImplID = mediap->getMediaTextureID();
  273. mTargetObjectID = objectp->getID();
  274. mTargetObjectFace = face;
  275. mTargetObjectNormal = pick_normal;
  276. if (sLastTargetImplID != mTargetImplID)
  277. {
  278. sLastTargetImplID = mTargetImplID;
  279. sLastMediaZoom = mCurrentZoom;
  280. mVolumeSlider->setValue(mediap->getVolume());
  281. }
  282. else
  283. {
  284. mCurrentZoom = sLastMediaZoom;
  285. }
  286. updateShape();
  287. if (mTargetIsHUDObject)
  288. {
  289. // Set the zoom to none
  290. sLastMediaZoom = mCurrentZoom = ZOOM_NONE;
  291. }
  292. }
  293. else
  294. {
  295. mTargetImplID.setNull();
  296. mTargetObjectID.setNull();
  297. mTargetObjectFace = 0;
  298. }
  299. }
  300. LLViewerMediaImpl* LLPanelMediaHUD::getTargetMediaImpl()
  301. {
  302. return LLViewerMedia::getMediaImplFromTextureID(mTargetImplID);
  303. }
  304. LLViewerObject* LLPanelMediaHUD::getTargetObject()
  305. {
  306. return gObjectList.findObject(mTargetObjectID);
  307. }
  308. LLPluginClassMedia* LLPanelMediaHUD::getTargetMediaPlugin()
  309. {
  310. LLViewerMediaImpl* mediap = getTargetMediaImpl();
  311. return mediap && mediap->hasMedia() ? mediap->getMediaPlugin() : NULL;
  312. }
  313. void LLPanelMediaHUD::updateShape()
  314. {
  315. constexpr S32 MIN_HUD_WIDTH = 235;
  316. constexpr S32 MIN_HUD_HEIGHT = 120;
  317. LLParcel* parcel = gViewerParcelMgr.getAgentParcel();
  318. LLViewerMediaImpl* mediap = getTargetMediaImpl();
  319. LLViewerObject* objectp = getTargetObject();
  320. if (!parcel || !mediap || !objectp || LLFloaterTools::isVisible())
  321. {
  322. setVisible(false);
  323. return;
  324. }
  325. mTargetIsHUDObject = objectp->isHUDAttachment();
  326. if (mTargetIsHUDObject)
  327. {
  328. // Make sure the "used on HUD" flag is set for this impl
  329. mediap->setUsedOnHUD(true);
  330. }
  331. bool can_navigate = parcel->getMediaAllowNavigate();
  332. LLPluginClassMedia* pluginp = NULL;
  333. if (mediap->hasMedia())
  334. {
  335. pluginp = getTargetMediaPlugin();
  336. }
  337. LLVOVolume* vobjp = objectp->asVolume();
  338. mLargeControls = false;
  339. // Do not show the media HUD if we do not have permissions
  340. LLTextureEntry* tep = objectp->getTE(mTargetObjectFace);
  341. LLMediaEntry* entryp = tep ? tep->getMediaData() : NULL;
  342. if (entryp)
  343. {
  344. mLargeControls = entryp->getControls() == LLMediaEntry::STANDARD;
  345. if (vobjp &&
  346. !vobjp->hasMediaPermission(entryp, LLVOVolume::MEDIA_PERM_CONTROL))
  347. {
  348. setVisible(false);
  349. return;
  350. }
  351. }
  352. mLargeControls = mLargeControls || mMediaFocus;
  353. // Set the state of the buttons
  354. mBackButton->setVisible(true);
  355. mForwardButton->setVisible(true);
  356. mReloadButton->setVisible(true);
  357. mStopButton->setVisible(false);
  358. mHomeButton->setVisible(true);
  359. mCloseButton->setVisible(true);
  360. mZoomButton->setVisible(!isZoomed());
  361. mUnzoomButton->setVisible(isZoomed());
  362. mZoomButton->setEnabled(!mTargetIsHUDObject);
  363. mUnzoomButton->setEnabled(!mTargetIsHUDObject);
  364. mZoomButton2->setEnabled(!mTargetIsHUDObject);
  365. std::string tooltip = mediap->getMediaURL();
  366. if (tooltip.empty())
  367. {
  368. tooltip = mOpenButtonTooltip + ".";
  369. }
  370. else
  371. {
  372. tooltip = mOpenButtonTooltip + ": " + tooltip;
  373. }
  374. mOpenButton->setToolTip(tooltip);
  375. mOpenButton2->setToolTip(tooltip);
  376. if (mLargeControls)
  377. {
  378. mBackButton->setEnabled(can_navigate && mediap->canNavigateBack());
  379. mForwardButton->setEnabled(can_navigate &&
  380. mediap->canNavigateForward());
  381. mStopButton->setEnabled(can_navigate);
  382. mHomeButton->setEnabled(can_navigate);
  383. F32 media_volume = mediap->getVolume();
  384. bool muted = media_volume <= 0.f;
  385. mMediaVolumeButton->setVisible(!muted);
  386. mMediaMutedButton->setVisible(muted);
  387. mVolumeSlider->setValue((F32)media_volume);
  388. LLPluginClassMediaOwner::EMediaStatus result =
  389. pluginp ? pluginp->getStatus()
  390. : LLPluginClassMediaOwner::MEDIA_NONE;
  391. mHasTimeControl = pluginp && pluginp->pluginSupportsMediaTime();
  392. if (mHasTimeControl)
  393. {
  394. mReloadButton->setEnabled(false);
  395. mReloadButton->setVisible(false);
  396. mMediaStopButton->setVisible(true);
  397. mHomeButton->setVisible(false);
  398. mBackButton->setEnabled(true);
  399. mForwardButton->setEnabled(true);
  400. if (result == LLPluginClassMediaOwner::MEDIA_PLAYING)
  401. {
  402. mPlayButton->setEnabled(false);
  403. mPlayButton->setVisible(false);
  404. mPauseButton->setEnabled(true);
  405. mPauseButton->setVisible(true);
  406. mMediaStopButton->setEnabled(true);
  407. }
  408. else
  409. {
  410. mPlayButton->setEnabled(true);
  411. mPlayButton->setVisible(true);
  412. mPauseButton->setEnabled(false);
  413. mPauseButton->setVisible(false);
  414. mMediaStopButton->setEnabled(false);
  415. }
  416. }
  417. else
  418. {
  419. mPlayButton->setVisible(false);
  420. mPauseButton->setVisible(false);
  421. mMediaStopButton->setVisible(false);
  422. if (result == LLPluginClassMediaOwner::MEDIA_LOADING)
  423. {
  424. mReloadButton->setEnabled(false);
  425. mReloadButton->setVisible(false);
  426. mStopButton->setEnabled(true);
  427. mStopButton->setVisible(true);
  428. }
  429. else
  430. {
  431. mReloadButton->setEnabled(true);
  432. mReloadButton->setVisible(true);
  433. mStopButton->setEnabled(false);
  434. mStopButton->setVisible(false);
  435. }
  436. }
  437. }
  438. mVolumeSlider->setVisible(mLargeControls &&
  439. !mVolumeSliderTimer.hasExpired());
  440. mFocusedControls->setVisible(mLargeControls);
  441. mHoverControls->setVisible(!mLargeControls);
  442. // Handle Scrolling
  443. switch (mScrollState)
  444. {
  445. case SCROLL_UP:
  446. mediap->scrollWheel(0, 0, 0, -1, MASK_NONE);
  447. break;
  448. case SCROLL_DOWN:
  449. mediap->scrollWheel(0, 0, 0, 1, MASK_NONE);
  450. break;
  451. case SCROLL_LEFT:
  452. mediap->scrollWheel(0, 0, 1, 0, MASK_NONE);
  453. //mediap->handleKeyHere(KEY_LEFT, MASK_NONE);
  454. break;
  455. case SCROLL_RIGHT:
  456. mediap->scrollWheel(0, 0, -1, 0, MASK_NONE);
  457. //mediap->handleKeyHere(KEY_RIGHT, MASK_NONE);
  458. break;
  459. case SCROLL_NONE:
  460. default:
  461. break;
  462. }
  463. LLBBox screen_bbox;
  464. LLMatrix4a mat;
  465. if (mTargetIsHUDObject)
  466. {
  467. LLMatrix4a proj, modelview;
  468. if (get_hud_matrices(proj, modelview))
  469. {
  470. mat.setMul(proj, modelview);
  471. }
  472. else
  473. {
  474. llwarns_sparse << "Cannot get HUD matrices" << llendl;
  475. setVisible(false);
  476. return;
  477. }
  478. }
  479. else
  480. {
  481. mat.setMul(gGLProjection, gGLModelView);
  482. }
  483. std::vector<LLVector3> vect_face;
  484. LLVolume* volume = objectp->getVolume();
  485. if (volume)
  486. {
  487. const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace);
  488. LLVector3 ext[2];
  489. ext[0].set(vf.mExtents[0].getF32ptr());
  490. ext[1].set(vf.mExtents[1].getF32ptr());
  491. LLVector3 center = (ext[0] + ext[1]) * 0.5f;
  492. LLVector3 size = (ext[1] - ext[0]) * 0.5f;
  493. LLVector3 vert[] = {
  494. center + size.scaledVec(LLVector3(1.f, 1.f, 1.f)),
  495. center + size.scaledVec(LLVector3(-1.f, 1.f, 1.f)),
  496. center + size.scaledVec(LLVector3(1.f, -1.f, 1.f)),
  497. center + size.scaledVec(LLVector3(-1.f, -1.f, 1.f)),
  498. center + size.scaledVec(LLVector3(1.f, 1.f, -1.f)),
  499. center + size.scaledVec(LLVector3(-1.f, 1.f, -1.f)),
  500. center + size.scaledVec(LLVector3(1.f, -1.f, -1.f)),
  501. center + size.scaledVec(LLVector3(-1.f, -1.f, -1.f)),
  502. };
  503. for (U32 i = 0; i < 8; ++i)
  504. {
  505. vect_face.emplace_back(vobjp->volumePositionToAgent(vert[i]));
  506. }
  507. }
  508. LLVector4a min, max, screen_vert;;
  509. min.splat(1.f);
  510. max.splat(-1.f);
  511. for (std::vector<LLVector3>::iterator vert_it = vect_face.begin(),
  512. vert_end = vect_face.end();
  513. vert_it != vert_end; ++vert_it)
  514. {
  515. // Project silhouette vertices into screen space
  516. screen_vert.load3(vert_it->mV, 1.f);
  517. mat.perspectiveTransform(screen_vert, screen_vert);
  518. // Add to screenspace bounding box
  519. min.setMin(screen_vert, min);
  520. max.setMax(screen_vert, max);
  521. }
  522. LLCoordGL screen_min;
  523. screen_min.mX = ll_round((F32)gViewerWindowp->getWindowWidth() *
  524. (min.getF32ptr()[VX] + 1.f) * 0.5f);
  525. screen_min.mY = ll_round((F32)gViewerWindowp->getWindowHeight() *
  526. (min.getF32ptr()[VY] + 1.f) * 0.5f);
  527. LLCoordGL screen_max;
  528. screen_max.mX = ll_round((F32)gViewerWindowp->getWindowWidth() *
  529. (max.getF32ptr()[VX] + 1.f) * 0.5f);
  530. screen_max.mY = ll_round((F32)gViewerWindowp->getWindowHeight() *
  531. (max.getF32ptr()[VY] + 1.f) * 0.5f);
  532. // Grow panel so that screenspace bounding box fits inside the
  533. // "media_full_view" element of the HUD
  534. LLRect media_hud_rect;
  535. getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY,
  536. screen_max.mX, screen_min.mY),
  537. &media_hud_rect);
  538. media_hud_rect.mLeft -= mMediaFullView->getRect().mLeft;
  539. media_hud_rect.mBottom -= mMediaFullView->getRect().mBottom;
  540. media_hud_rect.mTop += getRect().getHeight() -
  541. mMediaFullView->getRect().mTop;
  542. media_hud_rect.mRight += getRect().getWidth() -
  543. mMediaFullView->getRect().mRight;
  544. // Keep all parts of HUD on-screen
  545. LLRect parent_rect = getParent()->getLocalRect();
  546. // Account for the chat bar height when both the tool and chat bars are
  547. // visible. *TODO: make this accounted for in the HUD view. HB
  548. if (gChatBarp && gChatBarp->getVisible() && LLToolBar::isVisible())
  549. {
  550. parent_rect.mBottom += CHAT_BAR_HEIGHT;
  551. }
  552. media_hud_rect.intersectWith(parent_rect);
  553. // Clamp to minimum size, keeping centered
  554. media_hud_rect.setCenterAndSize(media_hud_rect.getCenterX(),
  555. media_hud_rect.getCenterY(),
  556. llmax(MIN_HUD_WIDTH,
  557. media_hud_rect.getWidth()),
  558. llmax(MIN_HUD_HEIGHT,
  559. media_hud_rect.getHeight()));
  560. userSetShape(media_hud_rect);
  561. setVisible(true);
  562. if (!mMediaFocus)
  563. {
  564. // Test mouse position to see if the cursor is stationary
  565. LLCoordWindow cursor_pos_window;
  566. gWindowp->getCursorPosition(&cursor_pos_window);
  567. // If last pos is not equal to current pos, the mouse has moved
  568. // We need to reset the timer, and make sure the panel is visible
  569. if (cursor_pos_window.mX != mLastCursorPos.mX ||
  570. cursor_pos_window.mY != mLastCursorPos.mY ||
  571. mScrollState != SCROLL_NONE)
  572. {
  573. mMouseMoveTimer.start();
  574. mLastCursorPos = cursor_pos_window;
  575. }
  576. // Mouse has been stationary, but not for long enough to fade the UI
  577. static LLCachedControl<F32> control_timeout(gSavedSettings,
  578. "MediaControlTimeout");
  579. static LLCachedControl<F32> fade_time(gSavedSettings,
  580. "MediaControlFadeTime");
  581. mControlFadeTime = llmax(0.5f, (F32)fade_time);
  582. if (mMouseMoveTimer.getElapsedTimeF32() < control_timeout ||
  583. (mLargeControls && !mVolumeSliderTimer.hasExpired()))
  584. {
  585. // If we have started fading, stop and reset the alpha values
  586. if (mFadeTimer.getStarted())
  587. {
  588. LL_DEBUGS("MediaHUD") << "Stopping the fading timer (mouse moved, media scrolled or volume slider shown)."
  589. << LL_ENDL;
  590. mFadeTimer.stop();
  591. setAlpha(1.f);
  592. }
  593. }
  594. // If we need to start fading the UI (and we have not already started)
  595. else if (!mFadeTimer.getStarted())
  596. {
  597. LL_DEBUGS("MediaHUD") << "Starting the fading timer." << LL_ENDL;
  598. mFadeTimer.reset();
  599. mFadeTimer.start();
  600. }
  601. else if (mFadeTimer.getElapsedTimeF32() >= mControlFadeTime)
  602. {
  603. setVisible(false);
  604. }
  605. }
  606. else if (mFadeTimer.getStarted())
  607. {
  608. LL_DEBUGS("MediaHUD") << "Focused: stopping the fading timer."
  609. << LL_ENDL;
  610. mFadeTimer.stop();
  611. setAlpha(1.f);
  612. }
  613. }
  614. //virtual
  615. void LLPanelMediaHUD::draw()
  616. {
  617. if (mFadeTimer.getStarted())
  618. {
  619. if (mFadeTimer.getElapsedTimeF32() >= mControlFadeTime)
  620. {
  621. setVisible(false);
  622. }
  623. else
  624. {
  625. F32 time = mFadeTimer.getElapsedTimeF32();
  626. F32 alpha = llmax(lerp(1.f, 0.f, time / mControlFadeTime), 0.f);
  627. setAlpha(alpha);
  628. setVisible(true);
  629. }
  630. }
  631. LLPanel::draw();
  632. }
  633. void LLPanelMediaHUD::setAlpha(F32 alpha)
  634. {
  635. LLViewQuery query;
  636. LLView* query_view = mLargeControls ? mFocusedControls : mHoverControls;
  637. child_list_t children = query(query_view);
  638. for (child_list_iter_t it = children.begin(), end = children.end();
  639. it != end; ++it)
  640. {
  641. LLView* viewp = *it;
  642. if (viewp && viewp->isFocusableCtrl())
  643. {
  644. ((LLUICtrl*)viewp)->setAlpha(alpha);
  645. }
  646. }
  647. LLPanel::setAlpha(alpha);
  648. }
  649. //virtual
  650. bool LLPanelMediaHUD::handleScrollWheel(S32 x, S32 y, S32 clicks)
  651. {
  652. return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
  653. }
  654. bool LLPanelMediaHUD::isMouseOver()
  655. {
  656. if (!getVisible())
  657. {
  658. return false;
  659. }
  660. LLCoordWindow cursor_pos_window;
  661. gWindowp->getCursorPosition(&cursor_pos_window);
  662. LLRect screen_rect;
  663. localRectToScreen(getLocalRect(), &screen_rect);
  664. return screen_rect.pointInRect(cursor_pos_window.mX, cursor_pos_window.mY);
  665. }
  666. //static
  667. void LLPanelMediaHUD::onClickClose(void* user_data)
  668. {
  669. LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL);
  670. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  671. if (self)
  672. {
  673. if (self->mCurrentZoom != ZOOM_NONE)
  674. {
  675. #if 0
  676. gAgent.setFocusOnAvatar();
  677. #endif
  678. sLastMediaZoom = self->mCurrentZoom = ZOOM_NONE;
  679. }
  680. self->setVisible(false);
  681. }
  682. }
  683. //static
  684. void LLPanelMediaHUD::onClickBack(void* user_data)
  685. {
  686. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  687. if (self)
  688. {
  689. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  690. if (mediap)
  691. {
  692. if (self->mHasTimeControl)
  693. {
  694. mediap->skipBack(0.2f);
  695. }
  696. else
  697. {
  698. mediap->navigateForward();
  699. }
  700. }
  701. }
  702. }
  703. //static
  704. void LLPanelMediaHUD::onClickForward(void* user_data)
  705. {
  706. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  707. if (self)
  708. {
  709. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  710. if (mediap)
  711. {
  712. if (self->mHasTimeControl)
  713. {
  714. mediap->skipForward(0.2f);
  715. }
  716. else
  717. {
  718. mediap->navigateForward();
  719. }
  720. }
  721. }
  722. }
  723. //static
  724. void LLPanelMediaHUD::onClickHome(void* user_data)
  725. {
  726. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  727. if (self)
  728. {
  729. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  730. if (mediap)
  731. {
  732. mediap->navigateHome();
  733. }
  734. }
  735. }
  736. //static
  737. void LLPanelMediaHUD::onClickOpen(void* user_data)
  738. {
  739. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  740. if (self)
  741. {
  742. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  743. if (mediap)
  744. {
  745. LLWeb::loadURL(mediap->getCurrentMediaURL());
  746. }
  747. }
  748. }
  749. //static
  750. void LLPanelMediaHUD::onClickReload(void* user_data)
  751. {
  752. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  753. if (self)
  754. {
  755. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  756. if (mediap)
  757. {
  758. mediap->navigateReload();
  759. }
  760. }
  761. }
  762. //static
  763. void LLPanelMediaHUD::onClickPlay(void* user_data)
  764. {
  765. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  766. if (self)
  767. {
  768. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  769. if (mediap)
  770. {
  771. mediap->play();
  772. }
  773. }
  774. }
  775. //static
  776. void LLPanelMediaHUD::onClickPause(void* user_data)
  777. {
  778. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  779. if (self)
  780. {
  781. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  782. if (mediap)
  783. {
  784. mediap->pause();
  785. }
  786. }
  787. }
  788. //static
  789. void LLPanelMediaHUD::onClickStop(void* user_data)
  790. {
  791. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  792. if (self)
  793. {
  794. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  795. if (mediap)
  796. {
  797. mediap->navigateStop();
  798. }
  799. }
  800. }
  801. //static
  802. void LLPanelMediaHUD::onClickMediaStop(void* user_data)
  803. {
  804. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  805. if (self)
  806. {
  807. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  808. if (mediap)
  809. {
  810. mediap->stop();
  811. }
  812. }
  813. }
  814. //static
  815. void LLPanelMediaHUD::onClickVolume(void* user_data)
  816. {
  817. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  818. if (self)
  819. {
  820. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  821. if (mediap)
  822. {
  823. F32 volume = mediap->getVolume();
  824. if (volume > 0.f)
  825. {
  826. self->mLastVolume = volume;
  827. mediap->setVolume(0.f);
  828. }
  829. else
  830. {
  831. volume = self->mLastVolume;
  832. if (volume <= 0.f)
  833. {
  834. volume = gSavedSettings.getF32("AudioLevelMedia");
  835. }
  836. mediap->setVolume(volume);
  837. }
  838. self->mVolumeSlider->setValue(volume);
  839. }
  840. }
  841. }
  842. //static
  843. void LLPanelMediaHUD::onClickZoom(void* user_data)
  844. {
  845. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  846. if (self)
  847. {
  848. self->nextZoomLevel();
  849. }
  850. }
  851. void LLPanelMediaHUD::nextZoomLevel()
  852. {
  853. if (mTargetIsHUDObject)
  854. {
  855. // Do not try to zoom on HUD objects...
  856. sLastMediaZoom = mCurrentZoom = ZOOM_NONE;
  857. return;
  858. }
  859. F32 zoom_padding = 0.f;
  860. S32 last_zoom_level = (S32)mCurrentZoom;
  861. sLastMediaZoom = mCurrentZoom = (EZoomLevel)((last_zoom_level + 1) %
  862. (S32)ZOOM_END);
  863. switch (mCurrentZoom)
  864. {
  865. case ZOOM_NONE:
  866. {
  867. gAgent.setFocusOnAvatar();
  868. break;
  869. }
  870. case ZOOM_MEDIUM:
  871. {
  872. zoom_padding = ZOOM_MEDIUM_PADDING;
  873. break;
  874. }
  875. default:
  876. {
  877. gAgent.setFocusOnAvatar();
  878. break;
  879. }
  880. }
  881. if (zoom_padding > 0.f)
  882. {
  883. LLViewerMediaFocus::getInstance()->setCameraZoom(getTargetObject(),
  884. mTargetObjectNormal,
  885. zoom_padding, true);
  886. }
  887. }
  888. //static
  889. void LLPanelMediaHUD::onScrollUp(void* user_data)
  890. {
  891. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  892. if (self)
  893. {
  894. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  895. if (mediap)
  896. {
  897. mediap->scrollWheel(0, 0, 0, -1, MASK_NONE);
  898. }
  899. }
  900. }
  901. //static
  902. void LLPanelMediaHUD::onScrollUpHeld(void* user_data)
  903. {
  904. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  905. if (self)
  906. {
  907. self->mScrollState = SCROLL_UP;
  908. }
  909. }
  910. //static
  911. void LLPanelMediaHUD::onScrollRight(void* user_data)
  912. {
  913. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  914. if (self)
  915. {
  916. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  917. if (mediap)
  918. {
  919. mediap->scrollWheel(0, 0, -1, 0, MASK_NONE);
  920. }
  921. }
  922. }
  923. //static
  924. void LLPanelMediaHUD::onScrollRightHeld(void* user_data)
  925. {
  926. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  927. if (self)
  928. {
  929. self->mScrollState = SCROLL_RIGHT;
  930. }
  931. }
  932. //static
  933. void LLPanelMediaHUD::onScrollLeft(void* user_data)
  934. {
  935. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  936. if (self)
  937. {
  938. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  939. if (mediap)
  940. {
  941. mediap->scrollWheel(0, 0, 1, 0, MASK_NONE);
  942. }
  943. }
  944. }
  945. //static
  946. void LLPanelMediaHUD::onScrollLeftHeld(void* user_data)
  947. {
  948. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  949. if (self)
  950. {
  951. self->mScrollState = SCROLL_LEFT;
  952. }
  953. }
  954. //static
  955. void LLPanelMediaHUD::onScrollDown(void* user_data)
  956. {
  957. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  958. if (self)
  959. {
  960. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  961. if (mediap)
  962. {
  963. mediap->scrollWheel(0, 0, 0, 1, MASK_NONE);
  964. }
  965. }
  966. }
  967. //static
  968. void LLPanelMediaHUD::onScrollDownHeld(void* user_data)
  969. {
  970. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  971. if (self)
  972. {
  973. self->mScrollState = SCROLL_DOWN;
  974. }
  975. }
  976. //static
  977. void LLPanelMediaHUD::onScrollStop(void* user_data)
  978. {
  979. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  980. if (self)
  981. {
  982. self->mScrollState = SCROLL_NONE;
  983. }
  984. }
  985. //static
  986. void LLPanelMediaHUD::onVolumeChange(LLUICtrl* ctrl, void* user_data)
  987. {
  988. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  989. if (self && self->mVolumeSlider)
  990. {
  991. LLViewerMediaImpl* mediap = self->getTargetMediaImpl();
  992. if (mediap)
  993. {
  994. mediap->setVolume(self->mVolumeSlider->getValueF32());
  995. }
  996. }
  997. }
  998. //static
  999. void LLPanelMediaHUD::onHoverSlider(LLUICtrl* ctrl, void* user_data)
  1000. {
  1001. onHoverVolume(user_data);
  1002. }
  1003. //static
  1004. void LLPanelMediaHUD::onHoverVolume(void* user_data)
  1005. {
  1006. static LLCachedControl<F32> control_timeout(gSavedSettings,
  1007. "MediaControlTimeout");
  1008. LLPanelMediaHUD* self = (LLPanelMediaHUD*)user_data;
  1009. if (self)
  1010. {
  1011. self->mVolumeSliderTimer.reset();
  1012. self->mVolumeSliderTimer.setTimerExpirySec(control_timeout);
  1013. }
  1014. }
  1015. ///////////////////////////////////////////////////////////////////////////////
  1016. // LLViewerMediaFocus class proper
  1017. ///////////////////////////////////////////////////////////////////////////////
  1018. LLViewerMediaFocus::LLViewerMediaFocus()
  1019. : mFocusedObjectFace(0),
  1020. mFocusedIsHUDObject(false),
  1021. mHoverObjectFace(0)
  1022. {
  1023. }
  1024. LLViewerMediaFocus::~LLViewerMediaFocus()
  1025. {
  1026. // The destructor for LLSingletons happens at atexit() time, which is too
  1027. // late to do much. Clean up in cleanupClass() instead.
  1028. }
  1029. void LLViewerMediaFocus::cleanupClass()
  1030. {
  1031. LLViewerMediaFocus* self = LLViewerMediaFocus::getInstance();
  1032. if (self)
  1033. {
  1034. if (self->mMediaHUD.get())
  1035. {
  1036. // Paranoia: the media HUD is normally already deleted at this
  1037. // point.
  1038. self->mMediaHUD.get()->resetZoomLevel();
  1039. self->mMediaHUD.get()->setMediaFace(NULL);
  1040. }
  1041. self->mFocusedObjectID.setNull();
  1042. self->mFocusedImplID.setNull();
  1043. }
  1044. }
  1045. void LLViewerMediaFocus::setFocusFace(bool face_auto_zoom,
  1046. LLPointer<LLViewerObject> objectp,
  1047. S32 face, viewer_media_t mediap,
  1048. LLVector3 pick_normal)
  1049. {
  1050. LLParcel* parcel = gViewerParcelMgr.getAgentParcel();
  1051. if (!parcel) return;
  1052. bool allow_media_zoom = !parcel->getMediaPreventCameraZoom();
  1053. static LLCachedControl<bool> media_ui(gSavedSettings, "MediaOnAPrimUI");
  1054. LLViewerMediaImpl* old_mediap = getFocusedMediaImpl();
  1055. if (old_mediap)
  1056. {
  1057. old_mediap->focus(false);
  1058. }
  1059. // Always clear the stored selection.
  1060. mSelection = NULL;
  1061. if (mediap.notNull() && objectp.notNull())
  1062. {
  1063. // Clear the current selection. If we are setting focus on a face,
  1064. // we will reselect the correct object below, when and if appropriate.
  1065. gSelectMgr.deselectAll();
  1066. mPrevFocusedImplID.setNull();
  1067. mFocusedImplID = mediap->getMediaTextureID();
  1068. mFocusedObjectID = objectp->getID();
  1069. mFocusedObjectFace = face;
  1070. mFocusedObjectNormal = pick_normal;
  1071. mFocusedIsHUDObject = objectp->isHUDAttachment();
  1072. if (mFocusedIsHUDObject)
  1073. {
  1074. // Make sure the "used on HUD" flag is set for this impl
  1075. mediap->setUsedOnHUD(true);
  1076. }
  1077. LL_DEBUGS("Media") << "Focusing on object: " << mFocusedObjectID
  1078. << ", face #" << mFocusedObjectFace << LL_ENDL;
  1079. // Focusing on a media face clears its disable flag.
  1080. mediap->setDisabled(false);
  1081. if (!mediap->isParcelMedia())
  1082. {
  1083. LLTextureEntry* tep = objectp->getTE(face);
  1084. if (tep && tep->hasMedia())
  1085. {
  1086. LLMediaEntry* mep = tep->getMediaData();
  1087. allow_media_zoom = mep && mep->getAutoZoom();
  1088. if (!mep)
  1089. {
  1090. // This should never happen.
  1091. llwarns << "Cannot find media implement for focused face"
  1092. << llendl;
  1093. }
  1094. else if (!mediap->hasMedia())
  1095. {
  1096. std::string url =
  1097. mep->getCurrentURL().empty() ? mep->getHomeURL()
  1098. : mep->getCurrentURL();
  1099. mediap->navigateTo(url, "", true);
  1100. }
  1101. }
  1102. else
  1103. {
  1104. // This should never happen.
  1105. llwarns << "Can't find media entry for focused face" << llendl;
  1106. }
  1107. }
  1108. if (!mFocusedIsHUDObject)
  1109. {
  1110. // Set the selection in the selection manager so we can draw the
  1111. // focus ring.
  1112. mSelection = gSelectMgr.selectObjectOnly(objectp, face);
  1113. }
  1114. mediap->focus(true);
  1115. gFocusMgr.setKeyboardFocus(this);
  1116. gEditMenuHandlerp = mediap;
  1117. gFocusMgr.setKeyboardFocus(this);
  1118. // We must do this before processing the media HUD zoom, or it may
  1119. // zoom to the wrong face.
  1120. update();
  1121. // Zoom if necessary and possible
  1122. if (media_ui && !mFocusedIsHUDObject && mMediaHUD.get())
  1123. {
  1124. static LLCachedControl<U32> auto_zoom(gSavedSettings,
  1125. "MediaAutoZoom");
  1126. if (auto_zoom == 1)
  1127. {
  1128. allow_media_zoom = false;
  1129. }
  1130. else if (auto_zoom == 2)
  1131. {
  1132. allow_media_zoom = true;
  1133. }
  1134. if (face_auto_zoom && allow_media_zoom)
  1135. {
  1136. mMediaHUD.get()->resetZoomLevel();
  1137. mMediaHUD.get()->nextZoomLevel();
  1138. }
  1139. }
  1140. }
  1141. else
  1142. {
  1143. LL_DEBUGS("Media") << "Focus lost (no object)." << LL_ENDL;
  1144. if (hasFocus())
  1145. {
  1146. gFocusMgr.setKeyboardFocus(NULL);
  1147. }
  1148. LLViewerMediaImpl* mediap = getFocusedMediaImpl();
  1149. if (gEditMenuHandlerp == mediap)
  1150. {
  1151. gEditMenuHandlerp = NULL;
  1152. }
  1153. mFocusedImplID.setNull();
  1154. // Null out the media hud media pointer
  1155. if (mMediaHUD.get())
  1156. {
  1157. mMediaHUD.get()->resetZoomLevel();
  1158. mMediaHUD.get()->setMediaFace(NULL);
  1159. }
  1160. if (objectp)
  1161. {
  1162. // Still record the focused object... it may mean we need to load
  1163. // media data. This will aid us in determining this object is
  1164. // "important enough"
  1165. mFocusedObjectID = objectp->getID();
  1166. mFocusedObjectFace = face;
  1167. mFocusedIsHUDObject = objectp->isHUDAttachment();
  1168. }
  1169. else
  1170. {
  1171. mFocusedObjectID.setNull();
  1172. mFocusedObjectFace = 0;
  1173. mFocusedIsHUDObject = false;
  1174. }
  1175. }
  1176. if (media_ui && mMediaHUD.get())
  1177. {
  1178. mMediaHUD.get()->setMediaFocus(mFocusedObjectID.notNull());
  1179. }
  1180. }
  1181. void LLViewerMediaFocus::clearFocus()
  1182. {
  1183. mPrevFocusedImplID = mFocusedImplID;
  1184. setFocusFace(false, NULL, 0, NULL);
  1185. }
  1186. void LLViewerMediaFocus::setHoverFace(LLPointer<LLViewerObject> objectp,
  1187. S32 face, viewer_media_t mediap,
  1188. LLVector3 pick_normal)
  1189. {
  1190. if (mediap)
  1191. {
  1192. mHoverImplID = mediap->getMediaTextureID();
  1193. mHoverObjectID = objectp->getID();
  1194. mHoverObjectFace = face;
  1195. mHoverObjectNormal = pick_normal;
  1196. }
  1197. else
  1198. {
  1199. mHoverObjectID.setNull();
  1200. mHoverObjectFace = 0;
  1201. mHoverImplID.setNull();
  1202. }
  1203. }
  1204. void LLViewerMediaFocus::clearHover()
  1205. {
  1206. setHoverFace(NULL, 0, NULL);
  1207. }
  1208. bool LLViewerMediaFocus::getFocus()
  1209. {
  1210. return gFocusMgr.getKeyboardFocus() == this;
  1211. }
  1212. // This function selects an ideal viewing distance given a selection bounding
  1213. // box, normal, and padding value
  1214. void LLViewerMediaFocus::setCameraZoom(LLViewerObject* objectp,
  1215. LLVector3 normal, F32 padding_factor,
  1216. bool zoom_in_only)
  1217. {
  1218. if (mFocusedIsHUDObject)
  1219. {
  1220. // Do not try to zoom on HUD objects...
  1221. return;
  1222. }
  1223. if (!objectp)
  1224. {
  1225. // If we have no object, focus back on the avatar.
  1226. gAgent.setFocusOnAvatar();
  1227. return;
  1228. }
  1229. gAgent.setFocusOnAvatar(false);
  1230. LLBBox bbox = objectp->getBoundingBoxAgent();
  1231. LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
  1232. F32 height, width, depth, angle_of_view, distance;
  1233. // We need the aspect ratio, and the 3 components of the bbox as
  1234. // height, width, and depth.
  1235. F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width,
  1236. &depth);
  1237. F32 camera_aspect = gViewerCamera.getAspect();
  1238. // We will normally use the side of the volume aligned with the short side
  1239. // of the screen (i.e. the height for a screen in a landscape aspect
  1240. // ratio), however there is an edge case where the aspect ratio of the
  1241. // object is more extreme than the screen. In this case we invert the
  1242. // logic, using the longer component of both the object and the screen.
  1243. bool invert = (camera_aspect > 1.f && aspect_ratio > camera_aspect) ||
  1244. (camera_aspect < 1.f && aspect_ratio < camera_aspect);
  1245. // To calculate the optimum viewing distance we will need the angle of the
  1246. // shorter side of the view rectangle. In portrait mode this is the width,
  1247. // and in landscape it is the height. We then calculate the distance based
  1248. // on the corresponding side of the object bbox (width for portrait, height
  1249. // for landscape). We will add half the depth of the bounding box, as the
  1250. // distance projection uses the center point of the bbox.
  1251. if (camera_aspect < 1.f || invert)
  1252. {
  1253. angle_of_view =
  1254. llmax(0.1f, gViewerCamera.getView() * gViewerCamera.getAspect());
  1255. distance = width * 0.5f * padding_factor / tanf(angle_of_view * 0.5f);
  1256. }
  1257. else
  1258. {
  1259. angle_of_view = llmax(0.1f, gViewerCamera.getView());
  1260. distance = height * 0.5f * padding_factor / tanf(angle_of_view * 0.5f);
  1261. }
  1262. distance += depth * 0.5;
  1263. // Finally animate the camera to this new position and focal point
  1264. LLVector3d camera_pos, target_pos;
  1265. // The target lookat position is the center of the selection (in global
  1266. // coords)
  1267. target_pos = center;
  1268. // Target look-from (camera) position is "distance" away from the target
  1269. // along the normal
  1270. LLVector3d pick_norm = LLVector3d(normal);
  1271. pick_norm.normalize();
  1272. camera_pos = target_pos + pick_norm * distance;
  1273. if (pick_norm == LLVector3d::z_axis || pick_norm == LLVector3d::z_axis_neg)
  1274. {
  1275. // If the normal points directly up, the camera will "flip" around. We
  1276. // try to avoid this by adjusting the target camera position a smidge
  1277. // towards current camera position
  1278. // NOTE: this solution is not perfect. All it attempts to solve is the
  1279. // "looking down" problem where the camera flips around when it
  1280. // animates to that position. You still are not guaranteed to be
  1281. // looking at the media in the correct orientation. What this solution
  1282. // does is it will put the camera into position keeping as best it can
  1283. // the current orientation with respect to the face. In other words, if
  1284. // before zoom the media appears "upside down" from the camera, after
  1285. // zooming it will still be upside down, but at least it will not flip.
  1286. LLVector3d cur_cam_pos = LLVector3d(gAgent.getCameraPositionGlobal());
  1287. LLVector3d delta = cur_cam_pos - camera_pos;
  1288. F64 len = delta.length();
  1289. delta.normalize();
  1290. // Move 1% of the distance towards original camera location
  1291. camera_pos += 0.01 * len * delta;
  1292. }
  1293. // If we are not allowing zooming out and the old camera position is closer
  1294. // to the center then the new intended camera position, do not move camera
  1295. // and return.
  1296. if (zoom_in_only &&
  1297. dist_vec_squared(gAgent.getCameraPositionGlobal(),
  1298. target_pos) < dist_vec_squared(camera_pos,
  1299. target_pos))
  1300. {
  1301. return;
  1302. }
  1303. gAgent.setCameraPosAndFocusGlobal(camera_pos, target_pos,
  1304. objectp->getID());
  1305. }
  1306. void LLViewerMediaFocus::focusZoomOnMedia(const LLUUID& media_id)
  1307. {
  1308. LLViewerMediaImpl* mediap =
  1309. LLViewerMedia::getMediaImplFromTextureID(media_id);
  1310. if (!mediap)
  1311. {
  1312. return;
  1313. }
  1314. // Get the first object from the media implement's object list. This is
  1315. // completely arbitrary, but suffices when the object got only one media
  1316. // implement.
  1317. LLVOVolume* objectp = mediap->getSomeObject();
  1318. if (!objectp)
  1319. {
  1320. return;
  1321. }
  1322. // This media is attached to at least one object. Figure out which face it
  1323. // is on.
  1324. S32 face = objectp->getFaceIndexWithMediaImpl(mediap, -1);
  1325. // We do not have a proper pick normal here, and finding a face's real
  1326. // normal is... complicated.
  1327. LLVector3 normal = objectp->getApproximateFaceNormal(face);
  1328. if (normal.isNull())
  1329. {
  1330. // If that did not work, use the inverse of the camera "look at" axis,
  1331. // which should keep the camera pointed in the same direction.
  1332. normal = gViewerCamera.getAtAxis();
  1333. normal *= -1.f;
  1334. }
  1335. // Focus on that face.
  1336. setFocusFace(false, objectp, face, mediap, normal);
  1337. // Attempt to zoom on that face.
  1338. if (mMediaHUD.get() && !objectp->isHUDAttachment())
  1339. {
  1340. mMediaHUD.get()->resetZoomLevel();
  1341. mMediaHUD.get()->nextZoomLevel();
  1342. }
  1343. }
  1344. void LLViewerMediaFocus::unZoom()
  1345. {
  1346. if (mMediaHUD.get() && mMediaHUD.get()->isZoomed())
  1347. {
  1348. mMediaHUD.get()->nextZoomLevel();
  1349. }
  1350. }
  1351. bool LLViewerMediaFocus::isZoomed()
  1352. {
  1353. return mMediaHUD.get() && mMediaHUD.get()->isZoomed();
  1354. }
  1355. bool LLViewerMediaFocus::isZoomedOnMedia(const LLUUID& media_id)
  1356. {
  1357. return isZoomed() &&
  1358. (mFocusedImplID == media_id || mPrevFocusedImplID == media_id);
  1359. }
  1360. void LLViewerMediaFocus::onFocusReceived()
  1361. {
  1362. LLViewerMediaImpl* mediap = getFocusedMediaImpl();
  1363. if (mediap)
  1364. {
  1365. mediap->focus(true);
  1366. }
  1367. LLFocusableElement::onFocusReceived();
  1368. }
  1369. void LLViewerMediaFocus::onFocusLost()
  1370. {
  1371. LLViewerMediaImpl* mediap = getFocusedMediaImpl();
  1372. if (mediap)
  1373. {
  1374. mediap->focus(false);
  1375. }
  1376. gViewerWindowp->focusClient();
  1377. LLFocusableElement::onFocusLost();
  1378. }
  1379. bool LLViewerMediaFocus::handleKey(KEY key, MASK mask, bool called_from_parent)
  1380. {
  1381. LLViewerMediaImpl* mediap = getFocusedMediaImpl();
  1382. if (mediap)
  1383. {
  1384. mediap->handleKeyHere(key, mask);
  1385. }
  1386. return true;
  1387. }
  1388. bool LLViewerMediaFocus::handleKeyUp(KEY key, MASK mask,
  1389. bool called_from_parent)
  1390. {
  1391. LLViewerMediaImpl* mediap = getFocusedMediaImpl();
  1392. if (mediap)
  1393. {
  1394. mediap->handleKeyUpHere(key, mask);
  1395. }
  1396. return true;
  1397. }
  1398. bool LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char,
  1399. bool called_from_parent)
  1400. {
  1401. LLViewerMediaImpl* mediap = getFocusedMediaImpl();
  1402. if (mediap)
  1403. {
  1404. mediap->handleUnicodeCharHere(uni_char);
  1405. }
  1406. return true;
  1407. }
  1408. bool LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
  1409. {
  1410. LLViewerMediaImpl* mediap = getFocusedMediaImpl();
  1411. if (mediap && mediap->hasMedia() && gKeyboardp)
  1412. {
  1413. mediap->scrollWheel(x, y, 0, clicks, gKeyboardp->currentMask(true));
  1414. return true;
  1415. }
  1416. return false;
  1417. }
  1418. void LLViewerMediaFocus::update()
  1419. {
  1420. static LLCachedControl<bool> media_ui(gSavedSettings, "MediaOnAPrimUI");
  1421. if (media_ui && mMediaHUD.get())
  1422. {
  1423. if (mFocusedImplID.notNull() || mMediaHUD.get()->isMouseOver())
  1424. {
  1425. //mMediaHUD.get()->setVisible(true);
  1426. mMediaHUD.get()->updateShape();
  1427. }
  1428. else
  1429. {
  1430. mMediaHUD.get()->setVisible(false);
  1431. }
  1432. }
  1433. LLViewerMediaImpl* mediap = getFocusedMediaImpl();
  1434. LLViewerObject* objectp = getFocusedObject();
  1435. S32 face = mFocusedObjectFace;
  1436. LLVector3 normal = mFocusedObjectNormal;
  1437. if (!mediap || !objectp)
  1438. {
  1439. mediap = getHoverMediaImpl();
  1440. objectp = getHoverObject();
  1441. face = mHoverObjectFace;
  1442. normal = mHoverObjectNormal;
  1443. }
  1444. if (media_ui && mediap && objectp)
  1445. {
  1446. static F32 last_update = 0.f;
  1447. // We have an object and implement to point at. Make sure the media HUD
  1448. // object exists.
  1449. if (!mMediaHUD.get())
  1450. {
  1451. LLPanelMediaHUD* media_hud = new LLPanelMediaHUD();
  1452. mMediaHUD = media_hud->getHandle();
  1453. if (gHUDViewp)
  1454. {
  1455. gHUDViewp->addChild(media_hud);
  1456. }
  1457. mMediaHUD.get()->setMediaFace(objectp, face, mediap, normal);
  1458. }
  1459. // Do not update every frame: that would be insane !
  1460. else if (gFrameTimeSeconds > last_update + 0.5f)
  1461. {
  1462. last_update = gFrameTimeSeconds;
  1463. mMediaHUD.get()->setMediaFace(objectp, face, mediap, normal);
  1464. }
  1465. mPrevFocusedImplID.setNull();
  1466. mFocusedImplID = mediap->getMediaTextureID();
  1467. }
  1468. else if (mMediaHUD.get())
  1469. {
  1470. // The media HUD is no longer needed.
  1471. mMediaHUD.get()->resetZoomLevel();
  1472. mMediaHUD.get()->setMediaFace(NULL);
  1473. }
  1474. }
  1475. // This function calculates the aspect ratio and the world aligned components
  1476. // of a selection bounding box.
  1477. F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox,
  1478. const LLVector3& normal,
  1479. F32* height, F32* width, F32* depth)
  1480. {
  1481. // Convert the selection normal and an up vector to local coordinate space
  1482. // of the bbox
  1483. LLVector3 local_normal = bbox.agentToLocalBasis(normal);
  1484. LLVector3 z_vec = bbox.agentToLocalBasis(LLVector3::z_axis);
  1485. LLVector3 comp1, comp2;
  1486. LLVector3 bbox_max = bbox.getExtentLocal();
  1487. F32 dot1 = 0.f;
  1488. F32 dot2 = 0.f;
  1489. // The largest component of the localized normal vector is the depth
  1490. // component meaning that the other two are the legs of the rectangle.
  1491. local_normal.abs();
  1492. if (local_normal.mV[VX] > local_normal.mV[VY])
  1493. {
  1494. if (local_normal.mV[VX] > local_normal.mV[VZ])
  1495. {
  1496. // Use the y and z comps
  1497. comp1.mV[VY] = bbox_max.mV[VY];
  1498. comp2.mV[VZ] = bbox_max.mV[VZ];
  1499. *depth = bbox_max.mV[VX];
  1500. }
  1501. else
  1502. {
  1503. // Use the x and y comps
  1504. comp1.mV[VY] = bbox_max.mV[VY];
  1505. comp2.mV[VZ] = bbox_max.mV[VZ];
  1506. *depth = bbox_max.mV[VZ];
  1507. }
  1508. }
  1509. else if (local_normal.mV[VY] > local_normal.mV[VZ])
  1510. {
  1511. // Use the x and z comps
  1512. comp1.mV[VX] = bbox_max.mV[VX];
  1513. comp2.mV[VZ] = bbox_max.mV[VZ];
  1514. *depth = bbox_max.mV[VY];
  1515. }
  1516. else
  1517. {
  1518. // Use the x and y comps
  1519. comp1.mV[VY] = bbox_max.mV[VY];
  1520. comp2.mV[VZ] = bbox_max.mV[VZ];
  1521. *depth = bbox_max.mV[VX];
  1522. }
  1523. // The height is the vector closest to vertical in the bbox coordinate
  1524. // space (highest dot product value)
  1525. dot1 = comp1 * z_vec;
  1526. dot2 = comp2 * z_vec;
  1527. if (fabs(dot1) > fabs(dot2))
  1528. {
  1529. *height = comp1.length();
  1530. *width = comp2.length();
  1531. }
  1532. else
  1533. {
  1534. *height = comp2.length();
  1535. *width = comp1.length();
  1536. }
  1537. // Return the aspect ratio.
  1538. return *width / *height;
  1539. }
  1540. bool LLViewerMediaFocus::isFocusedOnFace(LLPointer<LLViewerObject> objectp,
  1541. S32 face)
  1542. {
  1543. return objectp->getID() == mFocusedObjectID && face == mFocusedObjectFace;
  1544. }
  1545. bool LLViewerMediaFocus::isHoveringOverFace(LLPointer<LLViewerObject> objectp,
  1546. S32 face)
  1547. {
  1548. return objectp->getID() == mHoverObjectID && face == mHoverObjectFace;
  1549. }
  1550. LLViewerMediaImpl* LLViewerMediaFocus::getFocusedMediaImpl()
  1551. {
  1552. return LLViewerMedia::getMediaImplFromTextureID(mFocusedImplID);
  1553. }
  1554. LLViewerObject* LLViewerMediaFocus::getFocusedObject()
  1555. {
  1556. return gObjectList.findObject(mFocusedObjectID);
  1557. }
  1558. LLViewerMediaImpl* LLViewerMediaFocus::getHoverMediaImpl()
  1559. {
  1560. return LLViewerMedia::getMediaImplFromTextureID(mHoverImplID);
  1561. }
  1562. LLViewerObject* LLViewerMediaFocus::getHoverObject()
  1563. {
  1564. return gObjectList.findObject(mHoverObjectID);
  1565. }