From 35df5441d3e2789663532c948731aff3a1e04728 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 14 Jun 2010 12:04:49 +0200 Subject: llmediaplugins first step --- linden/indra/newview/llpanelmediahud.cpp | 667 +++++++++++++++++++++++++++++++ 1 file changed, 667 insertions(+) create mode 100644 linden/indra/newview/llpanelmediahud.cpp (limited to 'linden/indra/newview/llpanelmediahud.cpp') diff --git a/linden/indra/newview/llpanelmediahud.cpp b/linden/indra/newview/llpanelmediahud.cpp new file mode 100644 index 0000000..39c4b63 --- /dev/null +++ b/linden/indra/newview/llpanelmediahud.cpp @@ -0,0 +1,667 @@ +/** + * @file llpanelmsgs.cpp + * @brief Message popup preferences panel + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +//LLPanelMediaHUD +#include "llagent.h" +#include "llparcel.h" +#include "llpanel.h" +#include "llselectmgr.h" +#include "llrender.h" +#include "lldrawable.h" +#include "llviewerwindow.h" +#include "lluictrlfactory.h" +#include "llbutton.h" +#include "llface.h" +#include "llhudview.h" +#include "lliconctrl.h" +#include "lltoolpie.h" +#include "llviewercamera.h" +#include "llpanelmediahud.h" +#include "llpluginclassmedia.h" +#include "llviewercontrol.h" +#include "llviewerparcelmgr.h" +#include "llviewermedia.h" +#include "llviewermediafocus.h" +#include "llvovolume.h" +#include "llweb.h" + +glh::matrix4f glh_get_current_modelview(); +glh::matrix4f glh_get_current_projection(); + +const F32 ZOOM_NEAR_PADDING = 1.0f; +const F32 ZOOM_MEDIUM_PADDING = 1.2f; +const F32 ZOOM_FAR_PADDING = 1.5f; + +// +// LLPanelMediaHUD +// + +LLPanelMediaHUD::LLPanelMediaHUD(viewer_media_t media_impl) + : mMediaImpl(media_impl) +{ + mMediaFocus = false; + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_hud.xml"); + mMouseMoveTimer.reset(); + mFadeTimer.stop(); + mCurrentZoom = ZOOM_NONE; + mScrollState = SCROLL_NONE; + + mPanelHandle.bind(this); +} +LLPanelMediaHUD::~LLPanelMediaHUD() +{ + mMediaImpl = NULL; +} + +BOOL LLPanelMediaHUD::postBuild() +{ + LLButton* close_btn = getChild("close"); + close_btn->setClickedCallback(onClickClose, this); + + LLButton* back_btn = getChild("back"); + back_btn->setClickedCallback(onClickBack, this); + + LLButton* fwd_btn = getChild("fwd"); + fwd_btn->setClickedCallback(onClickForward, this); + + LLButton* home_btn = getChild("home"); + home_btn->setClickedCallback(onClickHome, this); + + LLButton* stop_btn = getChild("stop"); + stop_btn->setClickedCallback(onClickStop, this); + + LLButton* media_stop_btn = getChild("media_stop"); + media_stop_btn->setClickedCallback(onClickStop, this); + + LLButton* reload_btn = getChild("reload"); + reload_btn->setClickedCallback(onClickReload, this); + + LLButton* play_btn = getChild("play"); + play_btn->setClickedCallback(onClickPlay, this); + + LLButton* pause_btn = getChild("pause"); + pause_btn->setClickedCallback(onClickPause, this); + + LLButton* open_btn = getChild("new_window"); + open_btn->setClickedCallback(onClickOpen, this); + + LLButton* zoom_btn = getChild("zoom_frame"); + zoom_btn->setClickedCallback(onClickZoom, this); + + LLButton* open_btn_h = getChild("new_window_hover"); + open_btn_h->setClickedCallback(onClickOpen, this); + + LLButton* zoom_btn_h = getChild("zoom_frame_hover"); + zoom_btn_h->setClickedCallback(onClickZoom, this); + + LLButton* scroll_up_btn = getChild("scrollup"); + scroll_up_btn->setClickedCallback(onScrollUp, this); + scroll_up_btn->setHeldDownCallback(onScrollUpHeld); + scroll_up_btn->setMouseUpCallback(onScrollStop); + LLButton* scroll_left_btn = getChild("scrollleft"); + scroll_left_btn->setClickedCallback(onScrollLeft, this); + scroll_left_btn->setHeldDownCallback(onScrollLeftHeld); + scroll_left_btn->setMouseUpCallback(onScrollStop); + LLButton* scroll_right_btn = getChild("scrollright"); + scroll_right_btn->setClickedCallback(onScrollRight, this); + scroll_right_btn->setHeldDownCallback(onScrollLeftHeld); + scroll_right_btn->setMouseUpCallback(onScrollStop); + LLButton* scroll_down_btn = getChild("scrolldown"); + scroll_down_btn->setClickedCallback(onScrollDown, this); + scroll_down_btn->setHeldDownCallback(onScrollDownHeld); + scroll_down_btn->setMouseUpCallback(onScrollStop); + + mMouseInactiveTime = gSavedSettings.getF32("MediaControlTimeout"); + mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime"); + + mCurrentZoom = ZOOM_NONE; + // clicks on HUD buttons do not remove keyboard focus from media + setIsChrome(TRUE); + return TRUE; +} + +void LLPanelMediaHUD::updateShape() +{ + const S32 MIN_HUD_WIDTH=200; + const S32 MIN_HUD_HEIGHT=120; + + LLPluginClassMedia* media_plugin = NULL; + if(mMediaImpl.notNull() && mMediaImpl->hasMedia()) + { + media_plugin = mMediaImpl->getMediaPlugin(); + } + + // Early out for no media plugin + if(media_plugin == NULL) + { + setVisible(FALSE); + return; + } + + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + bool can_navigate = parcel->getMediaAllowNavigate(); + + // LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection(); + + LLSelectNode* nodep = mMediaFocus ? LLSelectMgr::getInstance()->getSelection()->getFirstNode() : LLSelectMgr::getInstance()->getHoverNode(); + if(! nodep) + { + return; + } + setVisible(FALSE); + LLViewerObject* objectp = nodep->getObject(); + + if (objectp) + { + + // Set the state of the buttons + LLButton* back_btn = getChild("back"); + LLButton* fwd_btn = getChild("fwd"); + LLButton* reload_btn = getChild("reload"); + LLButton* play_btn = getChild("play"); + LLButton* pause_btn = getChild("pause"); + LLButton* stop_btn = getChild("stop"); + LLButton* media_stop_btn = getChild("media_stop"); + LLButton* home_btn = getChild("home"); + LLButton* close_btn = getChild("close"); + LLButton* open_btn = getChild("new_window"); + LLPanel* media_focused_panel = getChild("media_focused_controls"); + LLPanel* media_hover_panel = getChild("media_hover_controls"); + back_btn->setVisible(true); + fwd_btn->setVisible(true); + reload_btn->setVisible(true); + stop_btn->setVisible(false); + home_btn->setVisible(true); + close_btn->setVisible(true); + open_btn->setVisible(true); + + + if(mMediaFocus) + { + back_btn->setEnabled(mMediaImpl->canNavigateBack() && can_navigate); + fwd_btn->setEnabled(mMediaImpl->canNavigateForward() && can_navigate); + stop_btn->setEnabled(can_navigate); + home_btn->setEnabled(can_navigate); + LLPluginClassMediaOwner::EMediaStatus result = media_plugin->getStatus(); + + if(media_plugin->pluginSupportsMediaTime()) + { + reload_btn->setEnabled(FALSE); + reload_btn->setVisible(FALSE); + media_stop_btn->setVisible(TRUE); + home_btn->setVisible(FALSE); + back_btn->setEnabled(TRUE); + fwd_btn->setEnabled(TRUE); + switch(result) + { + case LLPluginClassMediaOwner::MEDIA_PLAYING: + play_btn->setEnabled(FALSE); + play_btn->setVisible(FALSE); + pause_btn->setEnabled(TRUE); + pause_btn->setVisible(TRUE); + media_stop_btn->setEnabled(TRUE); + break; + case LLPluginClassMediaOwner::MEDIA_PAUSED: + default: + pause_btn->setEnabled(FALSE); + pause_btn->setVisible(FALSE); + play_btn->setEnabled(TRUE); + play_btn->setVisible(TRUE); + media_stop_btn->setEnabled(FALSE); + break; + } + } + else + { + play_btn->setVisible(FALSE); + pause_btn->setVisible(FALSE); + media_stop_btn->setVisible(FALSE); + if(result == LLPluginClassMediaOwner::MEDIA_LOADING) + { + reload_btn->setEnabled(FALSE); + reload_btn->setVisible(FALSE); + stop_btn->setEnabled(TRUE); + stop_btn->setVisible(TRUE); + } + else + { + reload_btn->setEnabled(TRUE); + reload_btn->setVisible(TRUE); + stop_btn->setEnabled(FALSE); + stop_btn->setVisible(FALSE); + } + } + } + media_focused_panel->setVisible(mMediaFocus); + media_hover_panel->setVisible(!mMediaFocus); + + if(media_plugin == NULL) + // Handle Scrolling + switch (mScrollState) + { + case SCROLL_UP: + media_plugin->scrollEvent(0, -1, MASK_NONE); + break; + case SCROLL_DOWN: + media_plugin->scrollEvent(0, 1, MASK_NONE); + break; + case SCROLL_LEFT: + mMediaImpl->handleKeyHere(KEY_LEFT, MASK_NONE); + break; + case SCROLL_RIGHT: + mMediaImpl->handleKeyHere(KEY_RIGHT, MASK_NONE); + break; + case SCROLL_NONE: + default: + break; + } + LLBBox screen_bbox; + setVisible(TRUE); + glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview(); + std::vector::iterator vert_it; + std::vector::iterator vert_end; + std::vector vect_face; + + LLVolume* volume = objectp->getVolume(); + + if (volume) + { + const LLVolumeFace& vf = volume->getVolumeFace(nodep->getLastSelectedTE()); + + const LLVector3* ext = vf.mExtents; + + LLVector3 center = (ext[0]+ext[1])*0.5f; + LLVector3 size = (ext[1]-ext[0])*0.5f; + LLVector3 vert[] = + { + center + size.scaledVec(LLVector3(1,1,1)), + center + size.scaledVec(LLVector3(-1,1,1)), + center + size.scaledVec(LLVector3(1,-1,1)), + center + size.scaledVec(LLVector3(-1,-1,1)), + center + size.scaledVec(LLVector3(1,1,-1)), + center + size.scaledVec(LLVector3(-1,1,-1)), + center + size.scaledVec(LLVector3(1,-1,-1)), + center + size.scaledVec(LLVector3(-1,-1,-1)), + }; + + LLVOVolume* vo = (LLVOVolume*) objectp; + + for (U32 i = 0; i < 8; i++) + { + vect_face.push_back(vo->volumePositionToAgent(vert[i])); + } + } + vert_it = vect_face.begin(); + vert_end = vect_face.end(); + + LLVector3 min = LLVector3(1,1,1); + LLVector3 max = LLVector3(-1,-1,-1); + for(; vert_it != vert_end; ++vert_it) + { + // project silhouette vertices into screen space + glh::vec3f screen_vert = glh::vec3f(vert_it->mV); + mat.mult_matrix_vec(screen_vert); + + // add to screenspace bounding box + update_min_max(min, max, LLVector3(screen_vert.v)); + } + + LLCoordGL screen_min; + screen_min.mX = llround((F32)gViewerWindow->getWindowWidth() * (min.mV[VX] + 1.f) * 0.5f); + screen_min.mY = llround((F32)gViewerWindow->getWindowHeight() * (min.mV[VY] + 1.f) * 0.5f); + + LLCoordGL screen_max; + screen_max.mX = llround((F32)gViewerWindow->getWindowWidth() * (max.mV[VX] + 1.f) * 0.5f); + screen_max.mY = llround((F32)gViewerWindow->getWindowHeight() * (max.mV[VY] + 1.f) * 0.5f); + + // grow panel so that screenspace bounding box fits inside "media_region" element of HUD + LLRect media_hud_rect; + getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_hud_rect); + LLView* media_region = getChild("media_region"); + media_hud_rect.mLeft -= media_region->getRect().mLeft; + media_hud_rect.mBottom -= media_region->getRect().mBottom; + media_hud_rect.mTop += getRect().getHeight() - media_region->getRect().mTop; + media_hud_rect.mRight += getRect().getWidth() - media_region->getRect().mRight; + + + LLRect old_hud_rect = media_hud_rect; + // keep all parts of HUD on-screen + media_hud_rect.intersectWith(getParent()->getLocalRect()); + + // If we had to clip the rect, don't display the border + childSetVisible("bg_image", false); + + // clamp to minimum size, keeping centered + media_hud_rect.setCenterAndSize(media_hud_rect.getCenterX(), media_hud_rect.getCenterY(), + llmax(MIN_HUD_WIDTH, media_hud_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_hud_rect.getHeight())); + + userSetShape(media_hud_rect); + + // Test mouse position to see if the cursor is stationary + LLCoordWindow cursor_pos_window; + getWindow()->getCursorPosition(&cursor_pos_window); + + // If last pos is not equal to current pos, the mouse has moved + // We need to reset the timer, and make sure the panel is visible + if(cursor_pos_window.mX != mLastCursorPos.mX || + cursor_pos_window.mY != mLastCursorPos.mY || + mScrollState != SCROLL_NONE) + { + mMouseMoveTimer.start(); + mLastCursorPos = cursor_pos_window; + } + + // Mouse has been stationary, but not for long enough to fade the UI + if(mMouseMoveTimer.getElapsedTimeF32() < mMouseInactiveTime) + { + // If we have started fading, reset the alpha values + if(mFadeTimer.getStarted()) + { + F32 alpha = 1.0f; + setAlpha(alpha); + mFadeTimer.stop(); + } + } + // If we need to start fading the UI (and we have not already started) + else if(! mFadeTimer.getStarted()) + { + mFadeTimer.reset(); + mFadeTimer.start(); + } + } +} +/*virtual*/ +void LLPanelMediaHUD::draw() +{ + if(mFadeTimer.getStarted()) + { + if(mFadeTimer.getElapsedTimeF32() >= mControlFadeTime) + { + setVisible(FALSE); + } + else + { + F32 time = mFadeTimer.getElapsedTimeF32(); + F32 alpha = llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f); + setAlpha(alpha); + } + } + LLPanel::draw(); +} +void LLPanelMediaHUD::setAlpha(F32 alpha) +{ + LLViewQuery query; + + LLView* query_view = mMediaFocus ? getChildView("media_focused_controls") : getChildView("media_hover_controls"); + child_list_t children = query(query_view); + for (child_list_iter_t child_iter = children.begin(); + child_iter != children.end(); ++child_iter) + { + LLUICtrl* ctrl = dynamic_cast(*child_iter); + if (ctrl) + ctrl->setAlpha(alpha); + } + + LLPanel::setAlpha(alpha); +} +BOOL LLPanelMediaHUD::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks); +} +bool LLPanelMediaHUD::isMouseOver() +{ + if( ! getVisible() ) + { + return false; + } + LLRect screen_rect; + LLCoordWindow cursor_pos_window; + getWindow()->getCursorPosition(&cursor_pos_window); + + localRectToScreen(getLocalRect(), &screen_rect); + // screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); + + if(screen_rect.pointInRect(cursor_pos_window.mX, cursor_pos_window.mY)) + { + return true; + } + return false; +} + +//static +void LLPanelMediaHUD::onClickClose(void* user_data) +{ + LLViewerMediaFocus::getInstance()->setFocusFace(FALSE, NULL, 0, NULL); + LLPanelMediaHUD* this_panel = static_cast (user_data); + if(this_panel->mCurrentZoom != ZOOM_NONE) + { + // gAgent.setFocusOnAvatar(TRUE, ANIMATE); + this_panel->mCurrentZoom = ZOOM_NONE; + } + this_panel->setVisible(FALSE); + +} + +//static +void LLPanelMediaHUD::onClickBack(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime()) + { + this_panel->mMediaImpl->getMediaPlugin()->start(-2.0); + } + else + { + this_panel->mMediaImpl->getMediaPlugin()->browse_back(); + } + + } +} +//static +void LLPanelMediaHUD::onClickForward(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime()) + { + this_panel->mMediaImpl->getMediaPlugin()->start(2.0); + } + else + { + this_panel->mMediaImpl->getMediaPlugin()->browse_forward(); + } + } +} +//static +void LLPanelMediaHUD::onClickHome(void* user_data) +{ + //LLViewerMedia::navigateHome(); + LLPanelMediaHUD* this_panel = static_cast (user_data); + if(this_panel->mMediaImpl.notNull()) + { + this_panel->mMediaImpl->navigateHome(); + } +} +//static +void LLPanelMediaHUD::onClickOpen(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if(this_panel->mMediaImpl.notNull()) + { + LLWeb::loadURL(this_panel->mMediaImpl->getMediaURL()); + } +} +//static +void LLPanelMediaHUD::onClickReload(void* user_data) +{ + //LLViewerMedia::navigateHome(); + LLPanelMediaHUD* this_panel = static_cast (user_data); + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if(objectp && this_panel->mMediaImpl.notNull()) + { + this_panel->mMediaImpl->navigateTo(objectp->getMediaURL()); + } +} +//static +void LLPanelMediaHUD::onClickPlay(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + this_panel->mMediaImpl->getMediaPlugin()->start(); + } +} +//static +void LLPanelMediaHUD::onClickPause(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + this_panel->mMediaImpl->getMediaPlugin()->pause(); + } +} +//static +void LLPanelMediaHUD::onClickStop(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime()) + { + this_panel->mMediaImpl->getMediaPlugin()->stop(); + } + else + { + this_panel->mMediaImpl->getMediaPlugin()->browse_stop(); + } + } +} +//static +void LLPanelMediaHUD::onClickZoom(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + this_panel->nextZoomLevel(); +} +void LLPanelMediaHUD::nextZoomLevel() +{ + F32 zoom_padding = 0.0f; + S32 last_zoom_level = (S32)mCurrentZoom; + mCurrentZoom = (EZoomLevel)((last_zoom_level + 1) % (S32)ZOOM_END); + + switch (mCurrentZoom) + { + case ZOOM_NONE: + { + gAgent.setFocusOnAvatar(TRUE, ANIMATE); + break; + } + case ZOOM_MEDIUM: + { + zoom_padding = ZOOM_MEDIUM_PADDING; + break; + } + default: + { + gAgent.setFocusOnAvatar(TRUE, ANIMATE); + break; + } + } + + if (zoom_padding > 0.0f) + LLViewerMediaFocus::getInstance()->setCameraZoom(zoom_padding); +} +void LLPanelMediaHUD::onScrollUp(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if(this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + this_panel->mMediaImpl->getMediaPlugin()->scrollEvent(0, -1, MASK_NONE); + } +} +void LLPanelMediaHUD::onScrollUpHeld(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + this_panel->mScrollState = SCROLL_UP; +} +void LLPanelMediaHUD::onScrollRight(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if(this_panel->mMediaImpl.notNull()) + { + this_panel->mMediaImpl->handleKeyHere(KEY_RIGHT, MASK_NONE); + } +} +void LLPanelMediaHUD::onScrollRightHeld(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + this_panel->mScrollState = SCROLL_RIGHT; +} + +void LLPanelMediaHUD::onScrollLeft(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if(this_panel->mMediaImpl.notNull()) + { + this_panel->mMediaImpl->handleKeyHere(KEY_LEFT, MASK_NONE); + } +} +void LLPanelMediaHUD::onScrollLeftHeld(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + this_panel->mScrollState = SCROLL_LEFT; +} + +void LLPanelMediaHUD::onScrollDown(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + if(this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + this_panel->mMediaImpl->getMediaPlugin()->scrollEvent(0, 1, MASK_NONE); + } +} +void LLPanelMediaHUD::onScrollDownHeld(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + this_panel->mScrollState = SCROLL_DOWN; +} + +void LLPanelMediaHUD::onScrollStop(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast (user_data); + this_panel->mScrollState = SCROLL_NONE; +} -- cgit v1.1