diff --git a/etc/message.xml b/etc/message.xml
index dd1fda059e..d2ba9843e4 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -668,7 +668,14 @@
FetchLib
true
-
+
+ ObjectMedia
+ false
+
+ ObjectMediaNavigate
+ false
+
+
messageBans
+ LastMediaSettingsTab
+
+ Comment
+ Last selected tab in media settings window
+ Persist
+ 1
+ Type
+ S32
+ Value
+ 0
+
LastRunVersion
Comment
@@ -4455,7 +4466,7 @@
Type
Boolean
Value
- 0
+ 1
MemoryLogFrequency
@@ -5216,6 +5227,51 @@
Value
1
+
+ PluginInstancesCPULimit
+
+ Comment
+ Amount of total plugin CPU usage before inworld plugins start getting turned down to "slideshow" priority. Set to 0 to disable this check.
+ Persist
+ 1
+ Type
+ F32
+ Value
+ 0.0
+
+ PluginInstancesLow
+
+ Comment
+ Limit on the number of inworld media plugins that will run at "low" priority
+ Persist
+ 1
+ Type
+ U32
+ Value
+ 4
+
+ PluginInstancesNormal
+
+ Comment
+ Limit on the number of inworld media plugins that will run at "normal" priority
+ Persist
+ 1
+ Type
+ U32
+ Value
+ 4
+
+ PluginInstancesTotal
+
+ Comment
+ Hard limit on the number of plugins that will be instantiated at once
+ Persist
+ 1
+ Type
+ U32
+ Value
+ 16
+
PrecachingDelay
Comment
@@ -5238,6 +5294,28 @@
Value
13
+ PrimMediaFetchQueueDelay
+
+ Comment
+ Timer delay for fetching media from the queue (in seconds).
+ Persist
+ 1
+ Type
+ F32
+ Value
+ 1.0
+
+ PrimMediaRetryTimerDelay
+
+ Comment
+ Timer delay for retrying on media queries (in seconds).
+ Persist
+ 1
+ Type
+ F32
+ Value
+ 5.0
+
ProbeHardwareOnStartup
Comment
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 4cf12a1533..069155c255 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -960,6 +960,30 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
return retval;
}
+const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one.
+//static
+S32 LLDrawable::getMinVisFrameRange()
+{
+ return MIN_VIS_FRAME_RANGE ;
+}
+
+BOOL LLDrawable::isRecentlyVisible() const
+{
+ //currently visible or visible in the previous frame.
+ BOOL vis = isVisible() || (sCurVisible - mVisible < MIN_VIS_FRAME_RANGE) ;
+
+ if(!vis)
+ {
+ LLSpatialGroup* group = getSpatialGroup();
+ if (group && group->isRecentlyVisible())
+ {
+ mVisible = sCurVisible;
+ vis = TRUE ;
+ }
+ }
+
+ return vis ;
+}
BOOL LLDrawable::isVisible() const
{
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 986440397b..5a10b688da 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -78,7 +78,8 @@ public:
BOOL isLight() const;
- BOOL isVisible() const;
+ BOOL isVisible() const;
+ BOOL isRecentlyVisible() const;
virtual void setVisible(LLCamera& camera_in, std::vector* results = NULL, BOOL for_select = FALSE);
@@ -278,7 +279,8 @@ public:
S32 mQuietCount;
static S32 getCurrentFrame() { return sCurVisible; }
-
+ static S32 getMinVisFrameRange();
+
void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; }
LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; }
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index fc5b27dd1b..a5b0b05603 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -270,16 +270,34 @@ void LLFace::setTexture(LLViewerTexture* tex)
{
mTexture->removeFace(this) ;
removeAtlas() ;
- }
+ }
mTexture = tex ;
-
+
if(mTexture.notNull())
{
mTexture->addFace(this) ;
}
}
+void LLFace::switchTexture(LLViewerTexture* new_texture)
+{
+ if(mTexture == new_texture)
+ {
+ return ;
+ }
+
+ if(!new_texture)
+ {
+ llerrs << "Can not switch to a null texture." << llendl ;
+ }
+ new_texture->addTextureStats(mTexture->getMaxVirtualSize()) ;
+
+ getViewerObject()->changeTEImage(mTEOffset, new_texture) ;
+ setTexture(new_texture) ;
+ gPipeline.markTextured(getDrawable());
+}
+
void LLFace::setTEOffset(const S32 te_offset)
{
mTEOffset = te_offset;
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index cafad5706c..f6ffefcb7c 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -89,6 +89,7 @@ public:
U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool
U16 getGeomStart() const { return mGeomIndex; } // index into draw pool
void setTexture(LLViewerTexture* tex) ;
+ void switchTexture(LLViewerTexture* new_texture);
LLXformMatrix* getXform() const { return mXform; }
BOOL hasGeometry() const { return mGeomCount > 0; }
LLVector3 getPositionAgent() const;
diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp
index c7ec4bd585..9b7f3305e5 100644
--- a/indra/newview/llfloatermediabrowser.cpp
+++ b/indra/newview/llfloatermediabrowser.cpp
@@ -146,7 +146,10 @@ void LLFloaterMediaBrowser::buildURLHistory()
}
// initialize URL history in the plugin
- mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history);
+ if(mBrowser && mBrowser->getMediaPlugin())
+ {
+ mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history);
+ }
}
std::string LLFloaterMediaBrowser::getSupportURL()
diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp
new file mode 100644
index 0000000000..811cc26efb
--- /dev/null
+++ b/indra/newview/llfloatermediasettings.cpp
@@ -0,0 +1,249 @@
+/**
+ * @file llfloatermediasettings.cpp
+ * @brief Tabbed dialog for media settings - class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 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"
+
+#include "llfloaterreg.h"
+#include "llfloatermediasettings.h"
+#include "llpanelmediasettingsgeneral.h"
+#include "llpanelmediasettingssecurity.h"
+#include "llpanelmediasettingspermissions.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+#include "llbutton.h"
+#include "llselectmgr.h"
+
+LLFloaterMediaSettings* LLFloaterMediaSettings::sInstance = NULL;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLFloaterMediaSettings::LLFloaterMediaSettings(const LLSD& key)
+ : LLFloater(key),
+ mTabContainer(NULL),
+ mPanelMediaSettingsGeneral(NULL),
+ mPanelMediaSettingsSecurity(NULL),
+ mPanelMediaSettingsPermissions(NULL),
+ mWaitingToClose( false )
+{
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_media_settings.xml");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLFloaterMediaSettings::~LLFloaterMediaSettings()
+{
+ if ( mPanelMediaSettingsGeneral )
+ {
+ delete mPanelMediaSettingsGeneral;
+ mPanelMediaSettingsGeneral = NULL;
+ }
+
+ if ( mPanelMediaSettingsSecurity )
+ {
+ delete mPanelMediaSettingsSecurity;
+ mPanelMediaSettingsSecurity = NULL;
+ }
+
+ if ( mPanelMediaSettingsPermissions )
+ {
+ delete mPanelMediaSettingsPermissions;
+ mPanelMediaSettingsPermissions = NULL;
+ }
+
+ sInstance = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLFloaterMediaSettings::postBuild()
+{
+ mCloseSignal.connect(boost::bind(&LLFloaterMediaSettings::onClose, this));
+
+ mApplyBtn = getChild("Apply");
+ mApplyBtn->setClickedCallback(onBtnApply, this);
+
+ mCancelBtn = getChild("Cancel");
+ mCancelBtn->setClickedCallback(onBtnCancel, this);
+
+ mOKBtn = getChild("OK");
+ mOKBtn->setClickedCallback(onBtnOK, this);
+
+ mTabContainer = getChild( "tab_container" );
+
+ mPanelMediaSettingsGeneral = new LLPanelMediaSettingsGeneral();
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams().
+ panel(mPanelMediaSettingsGeneral));
+ mPanelMediaSettingsGeneral->setParent( this );
+
+ // note that "permissions" tab is really "Controls" tab - refs to 'perms' and
+ // 'permissions' not changed to 'controls' since we don't want to change
+ // shared files in server code and keeping everything the same seemed best.
+ mPanelMediaSettingsPermissions = new LLPanelMediaSettingsPermissions();
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams().
+ panel(mPanelMediaSettingsPermissions));
+
+ mPanelMediaSettingsSecurity = new LLPanelMediaSettingsSecurity();
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams().
+ panel(mPanelMediaSettingsSecurity));
+
+ // restore the last tab viewed from persistance variable storage
+ if (!mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab")))
+ {
+ mTabContainer->selectFirstTab();
+ };
+
+ sInstance = this;
+
+ return TRUE;
+}
+
+//static
+LLFloaterMediaSettings* LLFloaterMediaSettings::getInstance()
+{
+ if ( !sInstance )
+ {
+ sInstance = (LLFloaterReg::getTypedInstance("media_settings"));
+ }
+
+ return sInstance;
+}
+
+//static
+void LLFloaterMediaSettings::apply()
+{
+
+ LLSD settings;
+ sInstance->mPanelMediaSettingsGeneral->getValues( settings );
+ sInstance->mPanelMediaSettingsSecurity->getValues( settings );
+ sInstance->mPanelMediaSettingsPermissions->getValues( settings );
+ LLSelectMgr::getInstance()->selectionSetMedia( LLTextureEntry::MF_HAS_MEDIA );
+ LLSelectMgr::getInstance()->selectionSetMediaData(settings);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void LLFloaterMediaSettings::onClose()
+{
+ if(mPanelMediaSettingsGeneral)
+ {
+ mPanelMediaSettingsGeneral->onClose();
+ }
+ LLFloaterReg::hideInstance("whitelist_entry");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//static
+void LLFloaterMediaSettings::initValues( const LLSD& media_settings )
+{
+ sInstance->clearValues();
+ // update all panels with values from simulator
+ sInstance->mPanelMediaSettingsGeneral->
+ initValues( sInstance->mPanelMediaSettingsGeneral, media_settings );
+
+ sInstance->mPanelMediaSettingsSecurity->
+ initValues( sInstance->mPanelMediaSettingsSecurity, media_settings );
+
+ sInstance->mPanelMediaSettingsPermissions->
+ initValues( sInstance->mPanelMediaSettingsPermissions, media_settings );
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterMediaSettings::commitFields()
+{
+ if (hasFocus())
+ {
+ LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus());
+ if (cur_focus->acceptsTextInput())
+ {
+ cur_focus->onCommit();
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//static
+void LLFloaterMediaSettings::clearValues()
+{
+ // clean up all panels before updating
+ sInstance->mPanelMediaSettingsGeneral->clearValues(sInstance->mPanelMediaSettingsGeneral);
+ sInstance->mPanelMediaSettingsSecurity->clearValues(sInstance->mPanelMediaSettingsSecurity);
+ sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterMediaSettings::onBtnOK( void* userdata )
+{
+ sInstance->commitFields();
+
+ sInstance->apply();
+
+ sInstance->closeFloater();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterMediaSettings::onBtnApply( void* userdata )
+{
+ sInstance->commitFields();
+
+ sInstance->apply();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterMediaSettings::onBtnCancel( void* userdata )
+{
+ sInstance->closeFloater();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterMediaSettings::onTabChanged(void* user_data, bool from_click)
+{
+ LLTabContainer* self = (LLTabContainer*)user_data;
+ gSavedSettings.setS32("LastMediaSettingsTab", self->getCurrentPanelIndex());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterMediaSettings::enableOkApplyBtns( bool enable )
+{
+ setCtrlsEnabled( enable );
+ childSetEnabled( "OK", enable );
+ childSetEnabled( "Apply", enable );
+}
diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h
new file mode 100644
index 0000000000..b95c590346
--- /dev/null
+++ b/indra/newview/llfloatermediasettings.h
@@ -0,0 +1,81 @@
+/**
+ * @file llfloatermediasettings.cpp
+ * @brief Tabbed dialog for media settings - class definition
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-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$
+ */
+
+#ifndef LL_LLFLOATERMEDIASETTINGS_H
+#define LL_LLFLOATERMEDIASETTINGS_H
+
+#include "llfloater.h"
+#include "lltabcontainer.h"
+
+class LLPanelMediaSettingsGeneral;
+class LLPanelMediaSettingsSecurity;
+class LLPanelMediaSettingsPermissions;
+
+class LLFloaterMediaSettings :
+ public LLFloater
+{
+public:
+ LLFloaterMediaSettings(const LLSD& key);
+ ~LLFloaterMediaSettings();
+
+ virtual BOOL postBuild();
+ static LLFloaterMediaSettings* getInstance();
+ static void apply();
+ static void initValues( const LLSD& media_settings );
+ static void clearValues();
+ void enableOkApplyBtns( bool enable );
+ LLPanelMediaSettingsSecurity* getPanelSecurity(){return mPanelMediaSettingsSecurity;};
+
+protected:
+ LLButton *mOKBtn;
+ LLButton *mCancelBtn;
+ LLButton *mApplyBtn;
+
+ LLTabContainer *mTabContainer;
+ LLPanelMediaSettingsGeneral* mPanelMediaSettingsGeneral;
+ LLPanelMediaSettingsSecurity* mPanelMediaSettingsSecurity;
+ LLPanelMediaSettingsPermissions* mPanelMediaSettingsPermissions;
+
+ void onClose();
+ static void onBtnOK(void*);
+ static void onBtnCancel(void*);
+ static void onBtnApply(void*);
+ static void onTabChanged(void* user_data, bool from_click);
+ void commitFields();
+
+ static LLFloaterMediaSettings* sInstance;
+
+private:
+ bool mWaitingToClose;
+};
+
+#endif // LL_LLFLOATERMEDIASETTINGS_H
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 761b5c9219..57c043a1e0 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -195,8 +195,8 @@ void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator);
viewer_media_t get_web_media()
{
- viewer_media_t media_source = LLViewerMedia::newMediaImpl("", LLUUID::null, 0, 0, 0, 0, "text/html");
-
+ viewer_media_t media_source = LLViewerMedia::newMediaImpl(LLUUID::null);
+ media_source->initializeMedia("text/html");
return media_source;
}
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index f334344279..7dc29379e4 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -44,9 +44,11 @@
#include "llcombobox.h"
#include "lldraghandle.h"
#include "llfloaterbuildoptions.h"
+#include "llfloatermediasettings.h"
#include "llfloateropenobject.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
+#include "llmediaentry.h"
#include "llmenugl.h"
#include "llpanelcontents.h"
#include "llpanelface.h"
@@ -97,7 +99,7 @@ const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] =
};
// Local prototypes
-void commit_select_component(LLUICtrl *ctrl, void *data);
+void commit_select_component(void *data);
void click_show_more(void*);
void click_popup_info(void*);
void click_popup_done(void*);
@@ -105,15 +107,14 @@ void click_popup_minimize(void*);
void click_popup_rotate_left(void*);
void click_popup_rotate_reset(void*);
void click_popup_rotate_right(void*);
-void commit_slider_dozer_size(LLUICtrl *, void*);
-void commit_slider_dozer_force(LLUICtrl *, void*);
+void commit_slider_dozer_force(LLUICtrl *);
void click_apply_to_selection(void*);
-void commit_radio_group_focus(LLUICtrl* ctrl, void* data);
-void commit_radio_group_move(LLUICtrl* ctrl, void* data);
-void commit_radio_group_edit(LLUICtrl* ctrl, void* data);
-void commit_radio_group_land(LLUICtrl* ctrl, void* data);
-void commit_grid_mode(LLUICtrl *, void*);
-void commit_slider_zoom(LLUICtrl *, void*);
+void commit_radio_group_focus(LLUICtrl* ctrl);
+void commit_radio_group_move(LLUICtrl* ctrl);
+void commit_radio_group_edit(LLUICtrl* ctrl);
+void commit_radio_group_land(LLUICtrl* ctrl);
+void commit_grid_mode(LLUICtrl *);
+void commit_slider_zoom(LLUICtrl *ctrl);
//static
@@ -210,43 +211,28 @@ BOOL LLFloaterTools::postBuild()
getDragHandle()->setEnabled( !gSavedSettings.getBOOL("ToolboxAutoMove") );
LLRect rect;
- mBtnFocus = getChild("button focus");//btn;
- childSetAction("button focus",LLFloaterTools::setEditTool, (void*)LLToolCamera::getInstance());
- mBtnMove = getChild("button move");
- childSetAction("button move",LLFloaterTools::setEditTool, (void*)LLToolGrab::getInstance());
- mBtnEdit = getChild("button edit");
- childSetAction("button edit",LLFloaterTools::setEditTool, (void*)LLToolCompTranslate::getInstance());
- mBtnCreate = getChild("button create");
- childSetAction("button create",LLFloaterTools::setEditTool, (void*)LLToolCompCreate::getInstance());
- mBtnLand = getChild("button land" );
- childSetAction("button land",LLFloaterTools::setEditTool, (void*)LLToolSelectLand::getInstance());
- mTextStatus = getChild("text status");
-
- childSetCommitCallback("slider zoom",commit_slider_zoom,this);
-
- mRadioGroupFocus = getChild("focus_radio_group");
- childSetCommitCallback("focus_radio_group", commit_radio_group_focus, this);
-
- mRadioGroupMove = getChild("move_radio_group");
- childSetCommitCallback("move_radio_group", commit_radio_group_move, this);
-
- mRadioGroupEdit = getChild("edit_radio_group");
- childSetCommitCallback("edit_radio_group", commit_radio_group_edit, this);
-
- mCheckSelectIndividual = getChild("checkbox edit linked parts");
+ mBtnFocus = getChild("button focus");//btn;
+ mBtnMove = getChild("button move");
+ mBtnEdit = getChild("button edit");
+ mBtnCreate = getChild("button create");
+ mBtnLand = getChild("button land" );
+ mTextStatus = getChild("text status");
+ mRadioGroupFocus = getChild("focus_radio_group");
+ mRadioGroupMove = getChild("move_radio_group");
+ mRadioGroupEdit = getChild("edit_radio_group");
+ mBtnGridOptions = getChild("Options...");
+
+ mCheckSelectIndividual = getChild("checkbox edit linked parts");
childSetValue("checkbox edit linked parts",(BOOL)gSavedSettings.getBOOL("EditLinkedParts"));
- childSetCommitCallback("checkbox edit linked parts",commit_select_component,this);
- mCheckSnapToGrid = getChild("checkbox snap to grid");
+ mCheckSnapToGrid = getChild("checkbox snap to grid");
childSetValue("checkbox snap to grid",(BOOL)gSavedSettings.getBOOL("SnapEnabled"));
- mBtnGridOptions = getChild("Options...");
- childSetAction("Options...",onClickGridOptions, this);
- mCheckStretchUniform = getChild("checkbox uniform");
+ mCheckStretchUniform = getChild("checkbox uniform");
childSetValue("checkbox uniform",(BOOL)gSavedSettings.getBOOL("ScaleUniform"));
- mCheckStretchTexture = getChild("checkbox stretch textures");
+ mCheckStretchTexture = getChild("checkbox stretch textures");
childSetValue("checkbox stretch textures",(BOOL)gSavedSettings.getBOOL("ScaleStretchTextures"));
- mTextGridMode = getChild("text ruler mode");
- mComboGridMode = getChild("combobox grid mode");
- childSetCommitCallback("combobox grid mode",commit_grid_mode, this);
+ mTextGridMode = getChild("text ruler mode");
+ mComboGridMode = getChild("combobox grid mode");
+
//
// Create Buttons
//
@@ -271,18 +257,11 @@ BOOL LLFloaterTools::postBuild()
mCheckCopyRotates = getChild("checkbox copy rotates");
childSetValue("checkbox copy rotates",(BOOL)gSavedSettings.getBOOL("CreateToolCopyRotates"));
- mRadioGroupLand = getChild("land_radio_group");
- childSetCommitCallback("land_radio_group", commit_radio_group_land, this);
-
- mBtnApplyToSelection = getChild("button apply to selection");
- childSetAction("button apply to selection",click_apply_to_selection, (void*)0);
-
- mSliderDozerSize = getChild("slider brush size");
- childSetCommitCallback("slider brush size", commit_slider_dozer_size, (void*)0);
+ mRadioGroupLand = getChild("land_radio_group");
+ mBtnApplyToSelection = getChild("button apply to selection");
+ mSliderDozerSize = getChild("slider brush size");
childSetValue( "slider brush size", gSavedSettings.getF32("LandBrushSize"));
-
- mSliderDozerForce = getChild("slider force");
- childSetCommitCallback("slider force",commit_slider_dozer_force, (void*)0);
+ mSliderDozerForce = getChild("slider force");
// the setting stores the actual force multiplier, but the slider is logarithmic, so we convert here
childSetValue( "slider force", log10(gSavedSettings.getF32("LandBrushForce")));
@@ -369,6 +348,22 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mFactoryMap["land info panel"] = LLCallbackMap(createPanelLandInfo, this);//LLPanelLandInfo
//Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_tools.xml",FALSE);
+ mCommitCallbackRegistrar.add("BuildTool.setTool", boost::bind(&LLFloaterTools::setTool,this, _2));
+ mCommitCallbackRegistrar.add("BuildTool.commitZoom", boost::bind(&commit_slider_zoom, _1));
+ mCommitCallbackRegistrar.add("BuildTool.commitRadioFocus", boost::bind(&commit_radio_group_focus, _1));
+ mCommitCallbackRegistrar.add("BuildTool.commitRadioMove", boost::bind(&commit_radio_group_move,_1));
+ mCommitCallbackRegistrar.add("BuildTool.commitRadioEdit", boost::bind(&commit_radio_group_edit,_1));
+
+ mCommitCallbackRegistrar.add("BuildTool.selectComponent", boost::bind(&commit_select_component, this));
+ mCommitCallbackRegistrar.add("BuildTool.gridOptions", boost::bind(&LLFloaterTools::onClickGridOptions,this));
+ mCommitCallbackRegistrar.add("BuildTool.applyToSelection", boost::bind(&click_apply_to_selection, this));
+ mCommitCallbackRegistrar.add("BuildTool.gridMode", boost::bind(&commit_grid_mode,_1));
+ mCommitCallbackRegistrar.add("BuildTool.commitRadioLand", boost::bind(&commit_radio_group_land,_1));
+ mCommitCallbackRegistrar.add("BuildTool.LandBrushForce", boost::bind(&commit_slider_dozer_force,_1));
+ mCommitCallbackRegistrar.add("BuildTool.AddMedia", boost::bind(&LLFloaterTools::onClickBtnAddMedia,this));
+ mCommitCallbackRegistrar.add("BuildTool.DeleteMedia", boost::bind(&LLFloaterTools::onClickBtnDeleteMedia,this));
+ mCommitCallbackRegistrar.add("BuildTool.EditMedia", boost::bind(&LLFloaterTools::onClickBtnEditMedia,this));
+
}
LLFloaterTools::~LLFloaterTools()
@@ -427,6 +422,7 @@ void LLFloaterTools::refresh()
mPanelObject->refresh();
mPanelVolume->refresh();
mPanelFace->refresh();
+ refreshMedia();
mPanelContents->refresh();
mPanelLandInfo->refresh();
}
@@ -756,6 +752,7 @@ void LLFloaterTools::onClose()
LLToolMgr::getInstance()->getCurrentToolset()->selectFirstTool();
//gMenuBarView->setItemVisible("BuildTools", FALSE);
+ LLFloaterReg::hideInstance("media_settings");
}
void click_popup_info(void*)
@@ -767,7 +764,7 @@ void click_popup_done(void*)
handle_reset_view();
}
-void commit_radio_group_move(LLUICtrl* ctrl, void* data)
+void commit_radio_group_move(LLUICtrl* ctrl)
{
LLRadioGroup* group = (LLRadioGroup*)ctrl;
std::string selected = group->getValue().asString();
@@ -788,7 +785,7 @@ void commit_radio_group_move(LLUICtrl* ctrl, void* data)
}
}
-void commit_radio_group_focus(LLUICtrl* ctrl, void* data)
+void commit_radio_group_focus(LLUICtrl* ctrl)
{
LLRadioGroup* group = (LLRadioGroup*)ctrl;
std::string selected = group->getValue().asString();
@@ -812,7 +809,7 @@ void commit_radio_group_focus(LLUICtrl* ctrl, void* data)
}
}
-void commit_slider_zoom(LLUICtrl *ctrl, void*)
+void commit_slider_zoom(LLUICtrl *ctrl)
{
// renormalize value, since max "volume" level is 0.5 for some reason
F32 zoom_level = (F32)ctrl->getValue().asReal() * 2.f; // / 0.5f;
@@ -837,26 +834,19 @@ void click_popup_rotate_right(void*)
dialog_refresh_all();
}
-
-void commit_slider_dozer_size(LLUICtrl *ctrl, void*)
-{
- F32 size = (F32)ctrl->getValue().asReal();
- gSavedSettings.setF32("LandBrushSize", size);
-}
-
-void commit_slider_dozer_force(LLUICtrl *ctrl, void*)
+void commit_slider_dozer_force(LLUICtrl *ctrl)
{
// the slider is logarithmic, so we exponentiate to get the actual force multiplier
F32 dozer_force = pow(10.f, (F32)ctrl->getValue().asReal());
gSavedSettings.setF32("LandBrushForce", dozer_force);
}
-void click_apply_to_selection(void* user)
+void click_apply_to_selection(void*)
{
LLToolBrushLand::getInstance()->modifyLandInSelectionGlobal();
}
-void commit_radio_group_edit(LLUICtrl *ctrl, void *data)
+void commit_radio_group_edit(LLUICtrl *ctrl)
{
S32 show_owners = gSavedSettings.getBOOL("ShowParcelOwners");
@@ -881,7 +871,7 @@ void commit_radio_group_edit(LLUICtrl *ctrl, void *data)
gSavedSettings.setBOOL("ShowParcelOwners", show_owners);
}
-void commit_radio_group_land(LLUICtrl* ctrl, void* data)
+void commit_radio_group_land(LLUICtrl* ctrl)
{
LLRadioGroup* group = (LLRadioGroup*)ctrl;
std::string selected = group->getValue().asString();
@@ -909,7 +899,7 @@ void commit_radio_group_land(LLUICtrl* ctrl, void* data)
}
}
-void commit_select_component(LLUICtrl *ctrl, void *data)
+void commit_select_component(void *data)
{
LLFloaterTools* floaterp = (LLFloaterTools*)data;
@@ -933,7 +923,7 @@ void commit_select_component(LLUICtrl *ctrl, void *data)
}
}
-void commit_grid_mode(LLUICtrl *ctrl, void *data)
+void commit_grid_mode(LLUICtrl *ctrl)
{
LLComboBox* combo = (LLComboBox*)ctrl;
@@ -948,10 +938,9 @@ void LLFloaterTools::setObjectType( LLPCode pcode )
gFocusMgr.setMouseCapture(NULL);
}
-// static
-void LLFloaterTools::onClickGridOptions(void* data)
+
+void LLFloaterTools::onClickGridOptions()
{
- //LLFloaterTools* floaterp = (LLFloaterTools*)data;
LLFloaterReg::showInstance("build_options");
// RN: this makes grid options dependent on build tools window
//floaterp->addDependentFloater(LLFloaterBuildOptions::getInstance(), FALSE);
@@ -964,8 +953,558 @@ void LLFloaterTools::setEditTool(void* tool_pointer)
LLToolMgr::getInstance()->getCurrentToolset()->selectTool( tool );
}
+void LLFloaterTools::setTool(const LLSD& user_data)
+{
+ std::string control_name = user_data.asString();
+ if(control_name == "Focus")
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool((LLTool *) LLToolCamera::getInstance() );
+ else if (control_name == "Move" )
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *)LLToolGrab::getInstance() );
+ else if (control_name == "Edit" )
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolCompTranslate::getInstance());
+ else if (control_name == "Create" )
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolCompCreate::getInstance());
+ else if (control_name == "Land" )
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolSelectLand::getInstance());
+ else
+ llwarns<<" no parameter name "<setCurrentToolset(gBasicToolset);
LLFloater::onFocusReceived();
}
+
+// Media stuff
+void LLFloaterTools::refreshMedia()
+{
+ getMediaState();
+ LLFloaterMediaSettings::getInstance();
+ LLFloaterMediaSettings::initValues(mMediaSettings );
+}
+
+
+
+void LLFloaterTools::getMediaState()
+{
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+
+ if( !objectp )
+ {
+ childSetEnabled("media_tex", FALSE);
+ childSetEnabled("add_media", FALSE);
+ childSetEnabled("delete_media", FALSE);
+ childSetEnabled("edit_media", FALSE);
+ updateMediaSettings();
+ return;
+ }
+
+ bool editable = gAgent.isGodlike() || (objectp->permModify() && objectp->getPCode() == LL_PCODE_VOLUME);
+
+ // Media settings
+ U8 has_media = (U8)0;
+ struct media_functor : public LLSelectedTEGetFunctor
+ {
+ U8 get(LLViewerObject* object, S32 face)
+ {
+ return (object->getTE(face)->getMediaTexGen());
+ }
+ } func;
+ bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, has_media );
+
+ // update UI depending on whether "object" (prim or face) has media
+ // and whether or not you are allowed to edit it.
+ bool bool_has_media = (has_media & LLTextureEntry::MF_HAS_MEDIA);
+ childSetEnabled("media_tex", bool_has_media & editable);
+ childSetEnabled( "edit_media", bool_has_media & editable );
+ childSetEnabled( "delete_media", bool_has_media & editable );
+ childSetEnabled( "add_media", ( ! bool_has_media ) & editable );
+
+ // load values for media settings
+ updateMediaSettings();
+
+ // if identical is set, all faces are same
+ if ( identical )
+ {
+ // TODO: display a list of all media on the face - use 'identical' flag
+ };
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// called when a user wants to add media to a prim or prim face
+void LLFloaterTools::onClickBtnAddMedia()
+{
+ // check for the edit tool and now many faces are selected
+ LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
+ if((tool != LLToolFace::getInstance()) || LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected())
+ {
+ LLNotifications::instance().add("MultipleFacesSelected",LLSD(), LLSD(), multipleFacesSelectedConfirm);
+
+ }
+ else
+ {
+ onClickBtnEditMedia();
+ }
+
+}
+
+// static
+bool LLFloaterTools::multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ switch( option )
+ {
+ case 0: // "Yes"
+ gFloaterTools->onClickBtnEditMedia();
+ break;
+ case 1: // "No"
+ default:
+ break;
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called when a user wants to edit existing media settings on a prim or prim face
+// TODO: test if there is media on the item and only allow editing if present
+void LLFloaterTools::onClickBtnEditMedia()
+{
+ refreshMedia();
+ LLFloaterReg::showInstance("media_settings");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called when a user wants to delete media from a prim or prim face
+void LLFloaterTools::onClickBtnDeleteMedia()
+{
+ LLNotifications::instance().add("DeleteMedia", LLSD(), LLSD(), deleteMediaConfirm);
+}
+
+
+// static
+bool LLFloaterTools::deleteMediaConfirm(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ switch( option )
+ {
+ case 0: // "Yes"
+ LLSelectMgr::getInstance()->selectionSetMedia( 0 );
+ if(LLFloaterReg::instanceVisible("media_settings"))
+ {
+ LLFloaterReg::hideInstance("media_settings");
+ }
+ break;
+
+ case 1: // "No"
+ default:
+ break;
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterTools::updateMediaSettings()
+{
+ bool identical( false );
+ std::string base_key( "" );
+ std::string value_str( "" );
+ int value_int = 0;
+ bool value_bool = false;
+ LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
+ // TODO: (CP) refactor this using something clever or boost or both !!
+
+ LLMediaEntry default_media_data;
+
+ // controls
+ U8 value_u8 = default_media_data.getControls();
+ struct functor_getter_controls : public LLSelectedTEGetFunctor< U8 >
+ {
+ U8 get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getControls();
+ LLMediaEntry default_media_data;
+ return default_media_data.getControls();
+ };
+
+ } func_controls;
+ identical = selected_objects->getSelectedTEValue( &func_controls, value_u8 );
+ base_key = std::string( LLMediaEntry::CONTROLS_KEY );
+ mMediaSettings[ base_key ] = value_u8;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // First click (formerly left click)
+ value_bool = default_media_data.getFirstClickInteract();
+ struct functor_getter_first_click : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getFirstClickInteract();
+ LLMediaEntry default_media_data;
+ return default_media_data.getFirstClickInteract();
+ };
+
+ } func_first_click;
+ identical = selected_objects->getSelectedTEValue( &func_first_click, value_bool );
+ base_key = std::string( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Home URL
+ value_str = default_media_data.getHomeURL();
+ struct functor_getter_home_url : public LLSelectedTEGetFunctor< std::string >
+ {
+ std::string get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getHomeURL();
+ LLMediaEntry default_media_data;
+ return default_media_data.getHomeURL();
+ };
+
+ } func_home_url;
+ identical = selected_objects->getSelectedTEValue( &func_home_url, value_str );
+ base_key = std::string( LLMediaEntry::HOME_URL_KEY );
+ mMediaSettings[ base_key ] = value_str;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+ llwarns<<"Angela debug : home url string == "<
+ {
+ std::string get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getCurrentURL();
+ LLMediaEntry default_media_data;
+ return default_media_data.getCurrentURL();
+ };
+
+ } func_current_url;
+ identical = selected_objects->getSelectedTEValue( &func_current_url, value_str );
+ base_key = std::string( LLMediaEntry::CURRENT_URL_KEY );
+ mMediaSettings[ base_key ] = value_str;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Auto zoom
+ value_bool = default_media_data.getAutoZoom();
+ struct functor_getter_auto_zoom : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getAutoZoom();
+ LLMediaEntry default_media_data;
+ return default_media_data.getAutoZoom();
+ };
+
+ } func_auto_zoom;
+ identical = selected_objects->getSelectedTEValue( &func_auto_zoom, value_bool );
+ base_key = std::string( LLMediaEntry::AUTO_ZOOM_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Auto play
+ value_bool = default_media_data.getAutoPlay();
+ struct functor_getter_auto_play : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getAutoPlay();
+ LLMediaEntry default_media_data;
+ return default_media_data.getAutoPlay();
+ };
+
+ } func_auto_play;
+ identical = selected_objects->getSelectedTEValue( &func_auto_play, value_bool );
+ base_key = std::string( LLMediaEntry::AUTO_PLAY_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Auto scale
+ value_bool = default_media_data.getAutoScale();
+ struct functor_getter_auto_scale : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getAutoScale();
+ LLMediaEntry default_media_data;
+ return default_media_data.getAutoScale();;
+ };
+
+ } func_auto_scale;
+ identical = selected_objects->getSelectedTEValue( &func_auto_scale, value_bool );
+ base_key = std::string( LLMediaEntry::AUTO_SCALE_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Auto loop
+ value_bool = default_media_data.getAutoLoop();
+ struct functor_getter_auto_loop : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getAutoLoop();
+ LLMediaEntry default_media_data;
+ return default_media_data.getAutoLoop();
+ };
+
+ } func_auto_loop;
+ identical = selected_objects->getSelectedTEValue( &func_auto_loop, value_bool );
+ base_key = std::string( LLMediaEntry::AUTO_LOOP_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // width pixels (if not auto scaled)
+ value_int = default_media_data.getWidthPixels();
+ struct functor_getter_width_pixels : public LLSelectedTEGetFunctor< int >
+ {
+ int get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getWidthPixels();
+ LLMediaEntry default_media_data;
+ return default_media_data.getWidthPixels();
+ };
+
+ } func_width_pixels;
+ identical = selected_objects->getSelectedTEValue( &func_width_pixels, value_int );
+ base_key = std::string( LLMediaEntry::WIDTH_PIXELS_KEY );
+ mMediaSettings[ base_key ] = value_int;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // height pixels (if not auto scaled)
+ value_int = default_media_data.getHeightPixels();
+ struct functor_getter_height_pixels : public LLSelectedTEGetFunctor< int >
+ {
+ int get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getHeightPixels();
+ LLMediaEntry default_media_data;
+ return default_media_data.getHeightPixels();
+ };
+
+ } func_height_pixels;
+ identical = selected_objects->getSelectedTEValue( &func_height_pixels, value_int );
+ base_key = std::string( LLMediaEntry::HEIGHT_PIXELS_KEY );
+ mMediaSettings[ base_key ] = value_int;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Enable Alt image
+ value_bool = default_media_data.getAltImageEnable();
+ struct functor_getter_enable_alt_image : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getAltImageEnable();
+ LLMediaEntry default_media_data;
+ return default_media_data.getAltImageEnable();
+ };
+
+ } func_enable_alt_image;
+ identical = selected_objects->getSelectedTEValue( &func_enable_alt_image, value_bool );
+ base_key = std::string( LLMediaEntry::ALT_IMAGE_ENABLE_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Perms - owner interact
+ value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER );
+ struct functor_getter_perms_owner_interact : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_OWNER));
+ LLMediaEntry default_media_data;
+ return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER );
+ };
+
+ } func_perms_owner_interact;
+ identical = selected_objects->getSelectedTEValue( &func_perms_owner_interact, value_bool );
+ base_key = std::string( LLPanelContents::PERMS_OWNER_INTERACT_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Perms - owner control
+ value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER );
+ struct functor_getter_perms_owner_control : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_OWNER));
+ LLMediaEntry default_media_data;
+ return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER );
+ };
+
+ } func_perms_owner_control;
+ identical = selected_objects ->getSelectedTEValue( &func_perms_owner_control, value_bool );
+ base_key = std::string( LLPanelContents::PERMS_OWNER_CONTROL_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Perms - group interact
+ value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP );
+ struct functor_getter_perms_group_interact : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_GROUP));
+ LLMediaEntry default_media_data;
+ return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP );
+ };
+
+ } func_perms_group_interact;
+ identical = selected_objects->getSelectedTEValue( &func_perms_group_interact, value_bool );
+ base_key = std::string( LLPanelContents::PERMS_GROUP_INTERACT_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Perms - group control
+ value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP );
+ struct functor_getter_perms_group_control : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_GROUP));
+ LLMediaEntry default_media_data;
+ return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP );
+ };
+
+ } func_perms_group_control;
+ identical = selected_objects->getSelectedTEValue( &func_perms_group_control, value_bool );
+ base_key = std::string( LLPanelContents::PERMS_GROUP_CONTROL_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Perms - anyone interact
+ value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE );
+ struct functor_getter_perms_anyone_interact : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_ANYONE));
+ LLMediaEntry default_media_data;
+ return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE );
+ };
+
+ } func_perms_anyone_interact;
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_perms_anyone_interact, value_bool );
+ base_key = std::string( LLPanelContents::PERMS_ANYONE_INTERACT_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // Perms - anyone control
+ value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE );
+ struct functor_getter_perms_anyone_control : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_ANYONE));
+ LLMediaEntry default_media_data;
+ return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE );
+ };
+
+ } func_perms_anyone_control;
+ identical = selected_objects->getSelectedTEValue( &func_perms_anyone_control, value_bool );
+ base_key = std::string( LLPanelContents::PERMS_ANYONE_CONTROL_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // security - whitelist enable
+ value_bool = default_media_data.getWhiteListEnable();
+ struct functor_getter_whitelist_enable : public LLSelectedTEGetFunctor< bool >
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getWhiteListEnable();
+ LLMediaEntry default_media_data;
+ return default_media_data.getWhiteListEnable();
+ };
+
+ } func_whitelist_enable;
+ identical = selected_objects->getSelectedTEValue( &func_whitelist_enable, value_bool );
+ base_key = std::string( LLMediaEntry::WHITELIST_ENABLE_KEY );
+ mMediaSettings[ base_key ] = value_bool;
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
+ // security - whitelist URLs
+ std::vector value_vector_str = default_media_data.getWhiteList();
+ struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector >
+ {
+ std::vector get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return object->getTE(face)->getMediaData()->getWhiteList();
+ LLMediaEntry default_media_data;
+ return default_media_data.getWhiteList();
+ };
+
+ } func_whitelist_urls;
+ identical = selected_objects->getSelectedTEValue( &func_whitelist_urls, value_vector_str );
+ base_key = std::string( LLMediaEntry::WHITELIST_KEY );
+ mMediaSettings[ base_key ].clear();
+ std::vector< std::string >::iterator iter = value_vector_str.begin();
+ while( iter != value_vector_str.end() )
+ {
+ std::string white_list_url = *iter;
+ mMediaSettings[ base_key ].append( white_list_url );
+ ++iter;
+ };
+
+ mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+}
+
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index 1b9f1d31ec..008c9677ed 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -100,13 +100,24 @@ public:
void setStatusText(const std::string& text);
static void setEditTool(void* data);
+ void setTool(const LLSD& user_data);
void saveLastTool();
+ void onClickBtnDeleteMedia();
+ void onClickBtnAddMedia();
+ void onClickBtnEditMedia();
+
+
private:
void onClose();
void refresh();
-
+ void refreshMedia();
+ void getMediaState();
+ void updateMediaSettings();
+ void getMeidaState();
+ static bool deleteMediaConfirm(const LLSD& notification, const LLSD& response);
+ static bool multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response);
static void setObjectType( LLPCode pcode );
- static void onClickGridOptions(void* data);
+ void onClickGridOptions();
public:
LLButton *mBtnFocus;
@@ -175,6 +186,10 @@ private:
BOOL mDirty;
std::map mStatusText;
+
+protected:
+ LLSD mMediaSettings;
+
};
extern LLFloaterTools *gFloaterTools;
diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index 1e975cd447..2b01a56373 100644
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -35,6 +35,7 @@
#include "llfloaterurlentry.h"
#include "llpanellandmedia.h"
+#include "llpanelface.h"
// project includes
#include "llcombobox.h"
@@ -145,13 +146,23 @@ void LLFloaterURLEntry::buildURLHistory()
void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type)
{
- LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get();
+ LLPanelLandMedia* panel_media = dynamic_cast(mPanelLandMediaHandle.get());
if (panel_media)
{
// status is ignored for now -- error = "none/none"
panel_media->setMediaType(mime_type);
panel_media->setMediaURL(mMediaURLEdit->getValue().asString());
}
+ else
+ {
+ LLPanelFace* panel_face = dynamic_cast(mPanelLandMediaHandle.get());
+ if(panel_face)
+ {
+ panel_face->setMediaType(mime_type);
+ panel_face->setMediaURL(mMediaURLEdit->getValue().asString());
+ }
+
+ }
// Decrement the cursor
getWindow()->decBusyCount();
childSetVisible("loading_label", false);
@@ -159,29 +170,18 @@ void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_
}
// static
-LLHandle LLFloaterURLEntry::show(LLHandle parent)
+LLHandle LLFloaterURLEntry::show(LLHandle parent, const std::string media_url)
{
- if (sInstance)
- {
- sInstance->openFloater();
- }
- else
+ if (!sInstance)
{
sInstance = new LLFloaterURLEntry(parent);
}
- sInstance->updateFromLandMediaPanel();
+ sInstance->openFloater();
+ sInstance->addURLToCombobox(media_url);
return sInstance->getHandle();
}
-void LLFloaterURLEntry::updateFromLandMediaPanel()
-{
- LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get();
- if (panel_media)
- {
- std::string media_url = panel_media->getMediaURL();
- addURLToCombobox(media_url);
- }
-}
+
bool LLFloaterURLEntry::addURLToCombobox(const std::string& media_url)
{
diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h
index 0aeca823b8..6dd9c8453c 100644
--- a/indra/newview/llfloaterurlentry.h
+++ b/indra/newview/llfloaterurlentry.h
@@ -44,10 +44,8 @@ class LLFloaterURLEntry : public LLFloater
public:
// Can only be shown by LLPanelLandMedia, and pushes data back into
// that panel via the handle.
- static LLHandle show(LLHandle panel_land_media_handle);
+ static LLHandle show(LLHandle panel_land_media_handle, const std::string media_url);
/*virtual*/ BOOL postBuild();
- void updateFromLandMediaPanel();
-
void headerFetchComplete(U32 status, const std::string& mime_type);
bool addURLToCombobox(const std::string& media_url);
diff --git a/indra/newview/llfloaterwhitelistentry.cpp b/indra/newview/llfloaterwhitelistentry.cpp
new file mode 100644
index 0000000000..551a5191fc
--- /dev/null
+++ b/indra/newview/llfloaterwhitelistentry.cpp
@@ -0,0 +1,97 @@
+/**
+ * @file llfloaterwhitelistentry.cpp
+ * @brief LLFloaterWhistListEntry class implementation
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-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"
+
+#include "llfloaterreg.h"
+#include "llfloatermediasettings.h"
+#include "llfloaterwhitelistentry.h"
+#include "llpanelmediasettingssecurity.h"
+#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "lllineeditor.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+LLFloaterWhiteListEntry::LLFloaterWhiteListEntry( const LLSD& key ) :
+ LLFloater(key)
+{
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_whitelist_entry.xml");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+LLFloaterWhiteListEntry::~LLFloaterWhiteListEntry()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLFloaterWhiteListEntry::postBuild()
+{
+ mWhiteListEdit = getChild("whitelist_entry");
+
+ childSetAction("cancel_btn", onBtnCancel, this);
+ childSetAction("ok_btn", onBtnOK, this);
+
+ setDefaultBtn("ok_btn");
+
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterWhiteListEntry::onBtnOK( void* userdata )
+{
+ LLFloaterWhiteListEntry *self =(LLFloaterWhiteListEntry *)userdata;
+
+ LLPanelMediaSettingsSecurity* panel = LLFloaterReg::getTypedInstance("media_settings")->getPanelSecurity();
+ if ( panel )
+ {
+ std::string white_list_item = self->mWhiteListEdit->getText();
+
+ panel->addWhiteListItem( white_list_item );
+ };
+
+ self->closeFloater();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterWhiteListEntry::onBtnCancel( void* userdata )
+{
+ LLFloaterWhiteListEntry *self =(LLFloaterWhiteListEntry *)userdata;
+
+ self->closeFloater();
+}
diff --git a/indra/newview/llfloaterwhitelistentry.h b/indra/newview/llfloaterwhitelistentry.h
new file mode 100644
index 0000000000..8ab5fb78b9
--- /dev/null
+++ b/indra/newview/llfloaterwhitelistentry.h
@@ -0,0 +1,56 @@
+/**
+ * @file llfloaterwhitelistentry.h
+ * @brief LLFloaterWhiteListEntry class definition
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-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$
+ */
+
+#ifndef LL_LLFLOATERWHITELISTENTRY_H
+#define LL_LLFLOATERWHITELISTENTRY_H
+
+#include "llfloater.h"
+
+class LLLineEditor;
+
+class LLFloaterWhiteListEntry :
+ public LLFloater
+{
+ public:
+ LLFloaterWhiteListEntry(const LLSD& key);
+ ~LLFloaterWhiteListEntry();
+
+ BOOL postBuild();
+
+ private:
+ LLLineEditor* mWhiteListEdit;
+
+ static void onBtnOK(void*);
+ static void onBtnCancel(void*);
+};
+
+#endif // LL_LLFLOATERWHITELISTENTRY_H
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 6ec098b92b..b996c15a7d 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -43,6 +43,7 @@
#include "llviewborder.h"
#include "llviewercontrol.h"
#include "llviewermedia.h"
+#include "llviewertexture.h"
#include "llviewerwindow.h"
#include "llnotifications.h"
#include "llweb.h"
@@ -63,6 +64,9 @@ LLMediaCtrl::Params::Params()
border_visible("border_visible", true),
ignore_ui_scale("ignore_ui_scale", true),
hide_loading("hide_loading", false),
+ decouple_texture_size("decouple_texture_size", false),
+ texture_width("texture_width", 1024),
+ texture_height("texture_height", 1024),
caret_color("caret_color")
{}
@@ -82,10 +86,12 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
mMediaSource( 0 ),
mTakeFocusOnClick( true ),
mCurrentNavUrl( "" ),
- mLastSetCursor( UI_CURSOR_ARROW ),
mStretchToFill( true ),
mMaintainAspectRatio ( true ),
- mHideLoading (false)
+ mHideLoading (false),
+ mDecoupleTextureSize ( false ),
+ mTextureWidth ( 1024 ),
+ mTextureHeight ( 1024 )
{
{
LLColor4 color = p.caret_color().get();
@@ -99,24 +105,29 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
setBorderVisible(p.border_visible());
mHideLoading = p.hide_loading();
+
+ setDecoupleTextureSize(p.decouple_texture_size());
+
+ setTextureSize(p.texture_width(), p.texture_height());
- S32 screen_width = mIgnoreUIScale ?
- llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth();
- S32 screen_height = mIgnoreUIScale ?
- llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight();
+ if(!getDecoupleTextureSize())
+ {
+ S32 screen_width = mIgnoreUIScale ?
+ llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth();
+ S32 screen_height = mIgnoreUIScale ?
+ llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight();
+
+ setTextureSize(screen_width, screen_height);
+ }
mMediaTextureID.generate();
- mMediaSource = LLViewerMedia::newMediaImpl(mHomePageUrl, mMediaTextureID, screen_width, screen_height, false, false, "text/html");
- if ( !mMediaSource )
- {
- llwarns << "media source create failed " << llendl;
- // return;
- }
-
- mMediaSource->setVisible( getVisible() );
-
- mMediaSource->addObserver( this );
+ // We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
+ if(!mHomePageUrl.empty())
+ {
+ navigateHome();
+ }
+
// FIXME: How do we create a bevel now?
// LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 );
// mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN );
@@ -179,9 +190,10 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
convertInputCoords(x, y);
if (mMediaSource)
+ {
mMediaSource->mouseMove(x, y);
-
- gViewerWindow->setCursor(mLastSetCursor);
+ gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
+ }
return TRUE;
}
@@ -389,19 +401,19 @@ void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility )
//
void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
{
- S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width;
- S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height;
-
-// llinfos << "reshape called with width = " << width << ", height = " << height << llendl;
-
- // when floater is minimized, these sizes are negative
- if ( screen_height > 0 && screen_width > 0 )
+ if(!getDecoupleTextureSize())
{
- mMediaSource->setSize(screen_width, screen_height);
- mForceUpdate = true;
- }
+ S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width;
+ S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height;
- LLPanel::reshape( width, height, called_from_parent );
+ // when floater is minimized, these sizes are negative
+ if ( screen_height > 0 && screen_width > 0 )
+ {
+ setTextureSize(screen_width, screen_height);
+ }
+ }
+
+ LLUICtrl::reshape( width, height, called_from_parent );
}
////////////////////////////////////////////////////////////////////////////////
@@ -475,9 +487,10 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type)
return;
}
- if (mMediaSource)
+ if (ensureMediaSourceExists())
{
mCurrentNavUrl = url_in;
+ mMediaSource->setSize(mTextureWidth, mTextureHeight);
mMediaSource->navigateTo(url_in, mime_type, mime_type.empty());
}
}
@@ -513,9 +526,10 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str
return;
}
}
- if (mMediaSource)
+ if (ensureMediaSourceExists())
{
mCurrentNavUrl = expanded_filename;
+ mMediaSource->setSize(mTextureWidth, mTextureHeight);
mMediaSource->navigateTo(expanded_filename, "text/html", false);
}
@@ -525,11 +539,11 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str
//
void LLMediaCtrl::navigateHome()
{
- if( mHomePageUrl.length() )
+ if (ensureMediaSourceExists())
{
- if (mMediaSource)
- mMediaSource->navigateTo(mHomePageUrl);
- };
+ mMediaSource->setSize(mTextureWidth, mTextureHeight);
+ mMediaSource->navigateHome();
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -537,6 +551,10 @@ void LLMediaCtrl::navigateHome()
void LLMediaCtrl::setHomePageUrl( const std::string urlIn )
{
mHomePageUrl = urlIn;
+ if (mMediaSource)
+ {
+ mMediaSource->setHomeURL(mHomePageUrl);
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -546,6 +564,21 @@ bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned i
//NOOP
return false;
}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::setTextureSize(S32 width, S32 height)
+{
+ mTextureWidth = width;
+ mTextureHeight = height;
+
+ if(mMediaSource)
+ {
+ mMediaSource->setSize(mTextureWidth, mTextureHeight);
+ mForceUpdate = true;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
//
std::string LLMediaCtrl::getHomePageUrl()
@@ -553,6 +586,38 @@ std::string LLMediaCtrl::getHomePageUrl()
return mHomePageUrl;
}
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLMediaCtrl::ensureMediaSourceExists()
+{
+ if(mMediaSource.isNull())
+ {
+ // If we don't already have a media source, try to create one.
+ mMediaSource = LLViewerMedia::newMediaImpl(mMediaTextureID, mTextureWidth, mTextureHeight);
+ if ( mMediaSource )
+ {
+ mMediaSource->setUsedInUI(true);
+ mMediaSource->setHomeURL(mHomePageUrl);
+ mMediaSource->setVisible( getVisible() );
+ mMediaSource->addObserver( this );
+ }
+ else
+ {
+ llwarns << "media source create failed " << llendl;
+ // return;
+ }
+ }
+
+ return !mMediaSource.isNull();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::unloadMediaSource()
+{
+ mMediaSource = NULL;
+}
+
////////////////////////////////////////////////////////////////////////////////
//
LLPluginClassMedia* LLMediaCtrl::getMediaPlugin()
@@ -574,13 +639,17 @@ void LLMediaCtrl::draw()
{
return;
}
+
+ if(!media_plugin || (!media_plugin->textureValid()))
+ {
+ // Don't try to draw without a valid texture
+ return;
+ }
LLViewerMediaTexture* media_texture = LLViewerTextureManager::findMediaTexture(mMediaTextureID);
if (!media_texture )
- {
return;
- }
if ( gRestoreGL == 1 )
{
@@ -658,7 +727,7 @@ void LLMediaCtrl::draw()
width = llmin(media_plugin->getWidth(), r.getWidth());
height = llmin(media_plugin->getHeight(), r.getHeight());
}
-
+
x_offset = (r.getWidth() - width) / 2;
y_offset = (r.getHeight() - height) / 2;
@@ -774,24 +843,9 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
case MEDIA_EVENT_CURSOR_CHANGED:
{
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
-
- std::string cursor = self->getCursorName();
-
- if(cursor == "arrow")
- mLastSetCursor = UI_CURSOR_ARROW;
- else if(cursor == "ibeam")
- mLastSetCursor = UI_CURSOR_IBEAM;
- else if(cursor == "splith")
- mLastSetCursor = UI_CURSOR_SIZEWE;
- else if(cursor == "splitv")
- mLastSetCursor = UI_CURSOR_SIZENS;
- else if(cursor == "hand")
- mLastSetCursor = UI_CURSOR_HAND;
- else // for anything else, default to the arrow
- mLastSetCursor = UI_CURSOR_ARROW;
- };
+ }
break;
-
+
case MEDIA_EVENT_NAVIGATE_BEGIN:
{
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL;
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index a19b3ad67b..5ea03f1e6c 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -37,7 +37,6 @@
#include "lluictrl.h"
#include "llframetimer.h"
-#include "lldynamictexture.h"
class LLViewBorder;
class LLUICtrlFactory;
@@ -50,7 +49,6 @@ class LLMediaCtrl :
public LLViewerMediaEventEmitter
{
LOG_CLASS(LLMediaCtrl);
-
public:
struct Params : public LLInitParam::Block
{
@@ -58,7 +56,11 @@ public:
Optional border_visible,
ignore_ui_scale,
- hide_loading;
+ hide_loading,
+ decouple_texture_size;
+
+ Optional texture_width,
+ texture_height;
Optional caret_color;
@@ -127,9 +129,17 @@ public:
void setForceUpdate(bool force_update) { mForceUpdate = force_update; }
bool getForceUpdate() { return mForceUpdate; }
+ bool ensureMediaSourceExists();
+ void unloadMediaSource();
+
LLPluginClassMedia* getMediaPlugin();
bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue );
+
+ void setDecoupleTextureSize(bool decouple) { mDecoupleTextureSize = decouple; }
+ bool getDecoupleTextureSize() { return mDecoupleTextureSize; }
+
+ void setTextureSize(S32 width, S32 height);
// over-rides
@@ -173,10 +183,12 @@ public:
bool mAlwaysRefresh;
viewer_media_t mMediaSource;
bool mTakeFocusOnClick;
- ECursorType mLastSetCursor;
bool mStretchToFill;
bool mMaintainAspectRatio;
bool mHideLoading;
+ bool mDecoupleTextureSize;
+ S32 mTextureWidth;
+ S32 mTextureHeight;
};
#endif // LL_LLMediaCtrl_H
diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp
index 5da646497b..ea528a1df8 100644
--- a/indra/newview/llpanelcontents.cpp
+++ b/indra/newview/llpanelcontents.cpp
@@ -72,6 +72,13 @@
//
// Globals
//
+const char* LLPanelContents::TENTATIVE_SUFFIX = "_tentative";
+const char* LLPanelContents::PERMS_OWNER_INTERACT_KEY = "perms_owner_interact";
+const char* LLPanelContents::PERMS_OWNER_CONTROL_KEY = "perms_owner_control";
+const char* LLPanelContents::PERMS_GROUP_INTERACT_KEY = "perms_group_interact";
+const char* LLPanelContents::PERMS_GROUP_CONTROL_KEY = "perms_group_control";
+const char* LLPanelContents::PERMS_ANYONE_INTERACT_KEY = "perms_anyone_interact";
+const char* LLPanelContents::PERMS_ANYONE_CONTROL_KEY = "perms_anyone_control";
BOOL LLPanelContents::postBuild()
{
@@ -83,7 +90,7 @@ BOOL LLPanelContents::postBuild()
childSetAction("button permissions",&LLPanelContents::onClickPermissions, this);
mPanelInventory = getChild("contents_inventory");
-
+
return TRUE;
}
@@ -112,7 +119,7 @@ void LLPanelContents::getState(LLViewerObject *objectp )
LLSelectMgr::getInstance()->selectGetGroup(group_id); // sets group_id as a side effect SL-23488
// BUG? Check for all objects being editable?
- BOOL editable = gAgent.isGodlike()
+ bool editable = gAgent.isGodlike()
|| (objectp->permModify()
&& ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488
BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME );
@@ -123,8 +130,8 @@ void LLPanelContents::getState(LLViewerObject *objectp )
all_volume &&
((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1)
|| (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)));
-}
+}
void LLPanelContents::refresh()
{
@@ -135,7 +142,7 @@ void LLPanelContents::refresh()
if (mPanelInventory)
{
mPanelInventory->refresh();
- }
+ }
}
diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h
index de1914bff9..bab980b524 100644
--- a/indra/newview/llpanelcontents.h
+++ b/indra/newview/llpanelcontents.h
@@ -51,11 +51,23 @@ public:
void refresh();
- static void onClickNewScript( void* userdata);
- static void onClickPermissions( void* userdata);
+
+ static void onClickNewScript(void*);
+ static void onClickPermissions(void*);
+
+ // Key suffix for "tentative" fields
+ static const char* TENTATIVE_SUFFIX;
+
+ // These aren't fields in LLMediaEntry, so we have to define them ourselves for checkbox control
+ static const char* PERMS_OWNER_INTERACT_KEY;
+ static const char* PERMS_OWNER_CONTROL_KEY;
+ static const char* PERMS_GROUP_INTERACT_KEY;
+ static const char* PERMS_GROUP_CONTROL_KEY;
+ static const char* PERMS_ANYONE_INTERACT_KEY;
+ static const char* PERMS_ANYONE_CONTROL_KEY;
protected:
- void getState(LLViewerObject *object);
+ void getState(LLViewerObject *object);
public:
LLPanelInventory* mPanelInventory;
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 08a50d4b6e..c61b987b1c 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -49,6 +49,7 @@
#include "llcombobox.h"
#include "lldrawpoolbump.h"
#include "lllineeditor.h"
+#include "llmediaentry.h"
#include "llresmgr.h"
#include "llselectmgr.h"
#include "llspinctrl.h"
@@ -61,6 +62,7 @@
#include "llviewermedia.h"
#include "llviewerobject.h"
#include "llviewerstats.h"
+#include "llvovolume.h"
#include "lluictrlfactory.h"
#include "llpluginclassmedia.h"
@@ -70,6 +72,18 @@
BOOL LLPanelFace::postBuild()
{
+ childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this);
+ childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this);
+ childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("checkbox flip t",&LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureInfo, this);
+ childSetAction("button apply",&LLPanelFace::onClickApply,this);
+ childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, this);
+ childSetAction("button align",&LLPanelFace::onClickAutoFix,this);
+
LLRect rect = this->getRect();
LLTextureCtrl* mTextureCtrl;
LLColorSwatchCtrl* mColorSwatch;
@@ -91,7 +105,7 @@ BOOL LLPanelFace::postBuild()
mTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitTexture, this, _2) );
mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) );
mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) );
- mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, _2));
+ mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2));
mTextureCtrl->setFollowsTop();
mTextureCtrl->setFollowsLeft();
// Don't allow (no copy) or (no transfer) textures to be selected during immediate mode
@@ -161,17 +175,6 @@ BOOL LLPanelFace::postBuild()
mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this);
}
- childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this);
- childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this);
- childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("checkbox flip t",&LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureInfo, this);
- childSetAction("button apply",&onClickApply,this);
- childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, this);
- childSetAction("button align",onClickAutoFix,this);
clearCtrls();
@@ -382,10 +385,8 @@ void LLPanelFace::getState()
BOOL editable = objectp->permModify();
// only turn on auto-adjust button if there is a media renderer and the media is loaded
- childSetEnabled("textbox autofix",FALSE);
- //mLabelTexAutoFix->setEnabled ( FALSE );
- childSetEnabled("button align",FALSE);
- //mBtnAutoFix->setEnabled ( FALSE );
+ childSetEnabled("textbox autofix", editable);
+ childSetEnabled("button align", editable);
//if ( LLMediaEngine::getInstance()->getMediaRenderer () )
// if ( LLMediaEngine::getInstance()->getMediaRenderer ()->isLoaded () )
@@ -785,6 +786,9 @@ void LLPanelFace::getState()
childSetEnabled("button align",FALSE);
childSetEnabled("button apply",FALSE);
+ childSetEnabled("has media", FALSE);
+ childSetEnabled("media info set", FALSE);
+
}
}
@@ -862,7 +866,7 @@ void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata)
}
// static
-BOOL LLPanelFace::onDragTexture(LLInventoryItem* item)
+BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item)
{
BOOL accept = TRUE;
for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
@@ -917,15 +921,25 @@ void LLPanelFace::onClickApply(void* userdata)
LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter );
}
-// commit the fit media texture to prim button
-
struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor
{
virtual bool apply(LLViewerObject* object, S32 te)
{
- // TODO: the media impl pointer should actually be stored by the texture
- viewer_media_t pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(object->getTE ( te )->getID());
- // only do this if it's a media texture
+ viewer_media_t pMediaImpl;
+
+ const LLTextureEntry* tep = object->getTE(te);
+ const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if ( mep )
+ {
+ pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+ }
+
+ if ( pMediaImpl.isNull())
+ {
+ // If we didn't find face media for this face, check whether this face is showing parcel media.
+ pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(tep->getID());
+ }
+
if ( pMediaImpl.notNull())
{
LLPluginClassMedia *media = pMediaImpl->getMediaPlugin();
@@ -957,3 +971,14 @@ void LLPanelFace::onClickAutoFix(void* userdata)
LLPanelFaceSendFunctor sendfunc;
LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
}
+
+
+
+// TODO: I don't know who put these in or what these are for???
+void LLPanelFace::setMediaURL(const std::string& url)
+{
+}
+void LLPanelFace::setMediaType(const std::string& mime_type)
+{
+}
+
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 9600129696..6a8704ce14 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -47,6 +47,7 @@ class LLTextBox;
class LLTextureCtrl;
class LLUICtrl;
class LLViewerObject;
+class LLFloater;
class LLPanelFace : public LLPanel
{
@@ -56,6 +57,8 @@ public:
virtual ~LLPanelFace();
void refresh();
+ void setMediaURL(const std::string& url);
+ void setMediaType(const std::string& mime_type);
protected:
void getState();
@@ -69,9 +72,10 @@ protected:
void sendShiny(); // applies and sends shininess
void sendFullbright(); // applies and sends full bright
void sendGlow();
+ void sendMedia();
// this function is to return TRUE if the drag should succeed.
- static BOOL onDragTexture(LLInventoryItem* item);
+ static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item);
void onCommitTexture(const LLSD& data);
void onCancelTexture(const LLSD& data);
@@ -87,10 +91,11 @@ protected:
static void onCommitShiny( LLUICtrl* ctrl, void* userdata);
static void onCommitFullbright( LLUICtrl* ctrl, void* userdata);
static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
-
+
static void onClickApply(void*);
static void onClickAutoFix(void*);
static F32 valueGlow(LLViewerObject* object, S32 face);
+
};
#endif
diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp
index 994bf7e3f9..42ad9820a8 100644
--- a/indra/newview/llpanellandmedia.cpp
+++ b/indra/newview/llpanellandmedia.cpp
@@ -122,9 +122,6 @@ BOOL LLPanelLandMedia::postBuild()
mSetURLButton = getChild("set_media_url");
childSetAction("set_media_url", onSetBtn, this);
- mResetURLButton = getChild("reset_media_url");
- childSetAction("reset_media_url", onResetBtn, this);
-
return TRUE;
}
@@ -215,13 +212,7 @@ void LLPanelLandMedia::refresh()
mMediaTextureCtrl->setEnabled( can_change_media );
mSetURLButton->setEnabled( can_change_media );
- mResetURLButton->setEnabled( can_change_media );
- LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mURLEntryFloater.get();
- if (floater_url_entry)
- {
- floater_url_entry->updateFromLandMediaPanel();
- }
}
}
@@ -341,7 +332,7 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata)
void LLPanelLandMedia::onSetBtn(void *userdata)
{
LLPanelLandMedia *self = (LLPanelLandMedia *)userdata;
- self->mURLEntryFloater = LLFloaterURLEntry::show( self->getHandle() );
+ self->mURLEntryFloater = LLFloaterURLEntry::show( self->getHandle(), self->getMediaURL() );
LLFloater* parent_floater = gFloaterView->getParentFloater(self);
if (parent_floater)
{
diff --git a/indra/newview/llpanellandmedia.h b/indra/newview/llpanellandmedia.h
index 5ad1f9758d..3deea29d17 100644
--- a/indra/newview/llpanellandmedia.h
+++ b/indra/newview/llpanellandmedia.h
@@ -63,8 +63,6 @@ private:
LLLineEditor* mMediaDescEdit;
LLComboBox* mMediaTypeCombo;
LLButton* mSetURLButton;
- LLButton* mResetURLButton;
- LLSpinCtrl* mMediaResetCtrl;
LLSpinCtrl* mMediaHeightCtrl;
LLSpinCtrl* mMediaWidthCtrl;
LLTextBox* mMediaResetCtrlLabel;
@@ -74,13 +72,6 @@ private:
LLCheckBoxCtrl* mMediaLoopCheck;
LLCheckBoxCtrl* mMediaUrlCheck;
LLHandle mURLEntryFloater;
- LLCheckBoxCtrl* mMediaNavigateAllowCheck;
- LLCheckBoxCtrl* mMediaURLFilterCheck;
- LLLineEditor* mMediaURLFilterDomainEdit;
- LLButton* mMediaURLFilterAddButton;
- LLButton* mMediaURLFilterRemoveButton;
- LLScrollListCtrl* mURLFilterList;
- LLRadioGroup* mRadioNavigateControl;
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index daf0fbd5e0..a7f66f3293 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -70,6 +70,7 @@
#include "llmediactrl.h"
#include "llrootview.h"
+
#include "llfloatertos.h"
#include "lltrans.h"
#include "llglheaders.h"
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp
new file mode 100644
index 0000000000..be40d6fb5f
--- /dev/null
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -0,0 +1,409 @@
+/**
+ * @file llpanelmediasettingsgeneral.cpp
+ * @brief LLPanelMediaSettingsGeneral class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 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"
+
+#include "llpanelmediasettingsgeneral.h"
+#include "llcombobox.h"
+#include "llcheckboxctrl.h"
+#include "llspinctrl.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llbutton.h"
+#include "lltexturectrl.h"
+#include "llurl.h"
+#include "llwindow.h"
+#include "llmediaentry.h"
+#include "llmediactrl.h"
+#include "llpanelcontents.h"
+#include "llpluginclassmedia.h"
+#include "llfloatermediasettings.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
+ mControls( NULL ),
+ mAutoLoop( NULL ),
+ mFirstClick( NULL ),
+ mAutoZoom( NULL ),
+ mAutoPlay( NULL ),
+ mAutoScale( NULL ),
+ mWidthPixels( NULL ),
+ mHeightPixels( NULL ),
+ mHomeURL( NULL ),
+ mCurrentURL( NULL ),
+ mAltImageEnable( NULL ),
+ mParent( NULL )
+{
+ // build dialog from XML
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml");
+ mCommitCallbackRegistrar.add("Media.ResetCurrentUrl", boost::bind(&LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl, this));
+// mCommitCallbackRegistrar.add("Media.CommitHomeURL", boost::bind(&LLPanelMediaSettingsGeneral::onCommitHomeURL, this));
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsGeneral::postBuild()
+{
+ // connect member vars with UI widgets
+ mAltImageEnable = getChild< LLCheckBoxCtrl >( LLMediaEntry::ALT_IMAGE_ENABLE_KEY );
+ mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY );
+ mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY );
+ mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
+ mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );
+ mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY );
+ mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY );
+ mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
+ mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );
+ mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY );
+ mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY );
+ mPreviewMedia = getChild("preview_media");
+
+ // watch commit action for HOME URL
+ childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this);
+
+ // interrogates controls and updates widgets as required
+ updateMediaPreview();
+ updateCurrentURL();
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+
+ // enable/disable pixel values image entry based on auto scale checkbox
+ if ( mAutoScale->getValue().asBoolean() == false )
+ {
+ childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true );
+ childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true );
+ }
+ else
+ {
+ childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false );
+ childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false );
+ };
+
+ // enable/disable UI based on type of media
+ bool reset_button_is_active = true;
+ if( mPreviewMedia )
+ {
+ LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
+ if( media_plugin )
+ {
+ // some controls are only appropriate for time or browser type plugins
+ // so we selectively enable/disable them - need to do it in draw
+ // because the information from plugins arrives assynchronously
+ bool show_time_controls = media_plugin->pluginSupportsMediaTime();
+ if ( show_time_controls )
+ {
+ childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false );
+ reset_button_is_active = false;
+ childSetEnabled( "current_url_label", false );
+ childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true );
+ }
+ else
+ {
+ childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true );
+ reset_button_is_active = true;
+ childSetEnabled( "current_url_label", true );
+ childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false );
+ };
+ };
+ };
+
+ // current URL can change over time.
+ updateCurrentURL();
+
+ // enable/disable RESRET button depending on permissions
+ // since this is the same as a navigate action
+ U32 owner_mask_on;
+ U32 owner_mask_off;
+ U32 valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_OWNER,
+ &owner_mask_on, &owner_mask_off );
+ U32 group_mask_on;
+ U32 group_mask_off;
+ U32 valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_GROUP,
+ &group_mask_on, &group_mask_off );
+ U32 everyone_mask_on;
+ U32 everyone_mask_off;
+ S32 valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_EVERYONE,
+ &everyone_mask_on, &everyone_mask_off );
+
+ bool user_can_press_reset = false;
+
+ // if perms we got back are valid
+ if ( valid_owner_perms &&
+ valid_group_perms &&
+ valid_everyone_perms )
+ {
+ // if user is allowed to press the RESET button
+ if ( ( owner_mask_on & PERM_MODIFY ) ||
+ ( group_mask_on & PERM_MODIFY ) ||
+ ( group_mask_on & PERM_MODIFY ) )
+ {
+ user_can_press_reset = true;
+ }
+ else
+ // user is NOT allowed to press the RESET button
+ {
+ user_can_press_reset = false;
+ };
+ };
+
+ // several places modify this widget so we must collect states in one place
+ if ( reset_button_is_active )
+ {
+ // user has perms to press reset button and it is active
+ if ( user_can_press_reset )
+ {
+ childSetEnabled( "current_url_reset_btn", true );
+ }
+ // user does not has perms to press reset button and it is active
+ else
+ {
+ childSetEnabled( "current_url_reset_btn", false );
+ };
+ }
+ else
+ // reset button is inactive so we just slam it to off - other states don't matter
+ {
+ childSetEnabled( "current_url_reset_btn", false );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::clearValues( void* userdata )
+{
+ LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->mAltImageEnable ->clear();
+ self->mAutoLoop->clear();
+ self->mAutoPlay->clear();
+ self->mAutoScale->clear();
+ self->mAutoZoom ->clear();
+ self->mControls->clear();
+ self->mCurrentURL->clear();
+ self->mFirstClick->clear();
+ self->mHeightPixels->clear();
+ self->mHomeURL->clear();
+ self->mWidthPixels->clear();
+ self->mPreviewMedia->unloadMediaSource();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings )
+{
+ LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+
+ //llinfos << "---------------" << llendl;
+ //llinfos << ll_pretty_print_sd(media_settings) << llendl;
+ //llinfos << "---------------" << llendl;
+
+ std::string base_key( "" );
+ std::string tentative_key( "" );
+
+ struct
+ {
+ std::string key_name;
+ LLUICtrl* ctrl_ptr;
+ std::string ctrl_type;
+
+ } data_set [] =
+ {
+ { LLMediaEntry::AUTO_LOOP_KEY, self->mAutoLoop, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" },
+ { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" },
+ { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLLineEditor" },
+ { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" },
+ { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" },
+ { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" },
+ { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" },
+ { LLMediaEntry::ALT_IMAGE_ENABLE_KEY, self->mAltImageEnable, "LLCheckBoxCtrl" },
+ { "", NULL , "" }
+ };
+
+ for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+ {
+ base_key = std::string( data_set[ i ].key_name );
+ tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+ // TODO: CP - I bet there is a better way to do this using Boost
+ if ( media_settings[ base_key ].isDefined() )
+ {
+ if ( data_set[ i ].ctrl_type == "LLLineEditor" )
+ {
+ static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )->
+ setText( media_settings[ base_key ].asString() );
+ }
+ else
+ if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+ static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asBoolean() );
+ else
+ if ( data_set[ i ].ctrl_type == "LLComboBox" )
+ static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
+ setCurrentByIndex( media_settings[ base_key ].asInteger() );
+ else
+ if ( data_set[ i ].ctrl_type == "LLSpinCtrl" )
+ static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asInteger() );
+
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+
+ // interrogates controls and updates widgets as required
+ self->updateMediaPreview();
+ self->updateCurrentURL();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper to set media control to media URL as required
+void LLPanelMediaSettingsGeneral::updateMediaPreview()
+{
+ if ( mHomeURL->getValue().asString().length() > 0 )
+ {
+ mPreviewMedia->navigateTo( mHomeURL->getValue().asString() );
+ }
+ else
+ // new home URL will be empty if media is deleted but
+ // we still need to clean out the preview.
+ {
+ mPreviewMedia->unloadMediaSource();
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper to set current URL
+void LLPanelMediaSettingsGeneral::updateCurrentURL()
+{
+ if( mPreviewMedia )
+ {
+ LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
+ if( media_plugin )
+ {
+ // get current URL from plugin and display
+ std::string current_location = media_plugin->getLocation();
+ if ( current_location.length() )
+ {
+ childSetText( "current_url", current_location );
+ }
+ else
+ // current location may be empty so we need to clear it
+ {
+ const std::string empty_string( "" );
+ childSetText( "current_url", empty_string );
+ };
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void LLPanelMediaSettingsGeneral::onClose()
+{
+ if(mPreviewMedia)
+ {
+ mPreviewMedia->unloadMediaSource();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata )
+{
+ LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->updateMediaPreview();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl()
+{
+ // TODO: reset home URL but need to consider permissions too
+ //LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::apply( void* userdata )
+{
+ LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+
+ // build LLSD Fragment
+ LLSD media_data_general;
+ self->getValues(media_data_general);
+
+ // this merges contents of LLSD passed in with what's there so this is ok
+ LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
+{
+ fill_me_in[LLMediaEntry::ALT_IMAGE_ENABLE_KEY] = mAltImageEnable->getValue();
+ fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue();
+ fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue();
+ fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue();
+ fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue();
+ fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex();
+ // XXX Don't send current URL!
+ //fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
+ fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue();
+ fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue();
+ fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue();
+ fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent )
+{
+ mParent = parent;
+};
diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h
new file mode 100644
index 0000000000..24678a3a07
--- /dev/null
+++ b/indra/newview/llpanelmediasettingsgeneral.h
@@ -0,0 +1,89 @@
+/**
+ * @file llpanelmediasettingsgeneral.h
+ * @brief LLPanelMediaSettingsGeneral class definition
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 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$
+ */
+
+#ifndef LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H
+#define LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H
+
+#include "llpanel.h"
+
+class LLButton;
+class LLCheckBoxCtrl;
+class LLComboBox;
+class LLLineEditor;
+class LLSpinCtrl;
+class LLTextureCtrl;
+class LLMediaCtrl;
+class LLFloaterMediaSettings;
+
+class LLPanelMediaSettingsGeneral : public LLPanel
+{
+public:
+ BOOL postBuild();
+ virtual void draw();
+ static void apply(void*);
+ void getValues(LLSD &fill_me_in);
+
+ LLPanelMediaSettingsGeneral();
+ ~LLPanelMediaSettingsGeneral();
+
+ void setParent( LLFloaterMediaSettings* parent );
+ static void initValues( void* userdata, const LLSD& media_settings );
+ static void clearValues( void* userdata );
+
+ void updateMediaPreview();
+ void updateCurrentURL();
+
+ void onClose();
+
+protected:
+ LLFloaterMediaSettings* mParent;
+
+private:
+ void onBtnResetCurrentUrl();
+ static void onCommitHomeURL(LLUICtrl* ctrl, void *userdata );
+
+ LLComboBox* mControls;
+ LLCheckBoxCtrl* mAutoLoop;
+ LLCheckBoxCtrl* mFirstClick;
+ LLTextureCtrl* mMediaPreview;
+ LLCheckBoxCtrl* mAutoZoom;
+ LLCheckBoxCtrl* mAutoPlay;
+ LLCheckBoxCtrl* mAutoScale;
+ LLSpinCtrl* mWidthPixels;
+ LLSpinCtrl* mHeightPixels;
+ LLLineEditor* mHomeURL;
+ LLLineEditor* mCurrentURL;
+ LLCheckBoxCtrl* mAltImageEnable;
+ LLMediaCtrl* mPreviewMedia;
+};
+
+#endif // LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H
diff --git a/indra/newview/llpanelmediasettingspermissions.cpp b/indra/newview/llpanelmediasettingspermissions.cpp
new file mode 100644
index 0000000000..d6a2677f4b
--- /dev/null
+++ b/indra/newview/llpanelmediasettingspermissions.cpp
@@ -0,0 +1,223 @@
+/**
+ * @file llpanelmediasettingspermissions.cpp
+ * @brief LLPanelMediaSettingsPermissions class implementation
+ *
+ * note that "permissions" tab is really "Controls" tab - refs to 'perms' and
+ * 'permissions' not changed to 'controls' since we don't want to change
+ * shared files in server code and keeping everything the same seemed best.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 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"
+
+#include "llpanelmediasettingspermissions.h"
+#include "llpanelcontents.h"
+#include "llcombobox.h"
+#include "llcheckboxctrl.h"
+#include "llspinctrl.h"
+#include "llurlhistory.h"
+#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llnamebox.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsPermissions::LLPanelMediaSettingsPermissions() :
+ mPermsOwnerInteract( 0 ),
+ mPermsOwnerControl( 0 ),
+ mPermsGroupName( 0 ),
+ mPermsGroupInteract( 0 ),
+ mPermsGroupControl( 0 ),
+ mPermsWorldInteract( 0 ),
+ mPermsWorldControl( 0 )
+{
+ // build dialog from XML
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_permissions.xml");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsPermissions::postBuild()
+{
+ // connect member vars with UI widgets
+ mPermsOwnerInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_OWNER_INTERACT_KEY );
+ mPermsOwnerControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_OWNER_CONTROL_KEY );
+ mPermsGroupInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_GROUP_INTERACT_KEY );
+ mPermsGroupControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_GROUP_CONTROL_KEY );
+ mPermsWorldInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_ANYONE_INTERACT_KEY );
+ mPermsWorldControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_ANYONE_CONTROL_KEY );
+
+ mPermsGroupName = getChild< LLNameBox >( "perms_group_name" );
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsPermissions::~LLPanelMediaSettingsPermissions()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void LLPanelMediaSettingsPermissions::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+
+ childSetText("perms_group_name",LLStringUtil::null);
+ LLUUID group_id;
+ BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id);
+ if (groups_identical)
+ {
+ if(mPermsGroupName)
+ {
+ mPermsGroupName->setNameID(group_id, true);
+ mPermsGroupName->setEnabled(true);
+ };
+ }
+ else
+ {
+ if(mPermsGroupName)
+ {
+ mPermsGroupName->setNameID(LLUUID::null, TRUE);
+ mPermsGroupName->refresh(LLUUID::null, LLStringUtil::null, LLStringUtil::null, true);
+ mPermsGroupName->setEnabled(false);
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsPermissions::clearValues( void* userdata )
+{
+ LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata;
+ self->mPermsOwnerInteract->clear();
+ self->mPermsOwnerControl->clear();
+ self->mPermsGroupInteract ->clear();
+ self->mPermsGroupControl->clear();
+ self->mPermsWorldInteract ->clear();
+ self->mPermsWorldControl ->clear();
+// mPermsGroupName ->setValue(0);
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& media_settings )
+{
+ LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata;
+
+ std::string base_key( "" );
+ std::string tentative_key( "" );
+
+ struct
+ {
+ std::string key_name;
+ LLUICtrl* ctrl_ptr;
+ std::string ctrl_type;
+
+ } data_set [] =
+ {
+ { LLPanelContents::PERMS_OWNER_INTERACT_KEY, self->mPermsOwnerInteract, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_OWNER_CONTROL_KEY, self->mPermsOwnerControl, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_GROUP_INTERACT_KEY, self->mPermsGroupInteract, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_GROUP_CONTROL_KEY, self->mPermsGroupControl, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_ANYONE_INTERACT_KEY, self->mPermsWorldInteract, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_ANYONE_CONTROL_KEY, self->mPermsWorldControl, "LLCheckBoxCtrl" },
+ { "", NULL , "" }
+ };
+
+ for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+ {
+ base_key = std::string( data_set[ i ].key_name );
+ tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+
+ // TODO: CP - I bet there is a better way to do this using Boost
+ if ( media_settings[ base_key ].isDefined() )
+ {
+ if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+ {
+ // the sense of the checkboxes changed and it made sense
+ // to just reverse their sense back again here and avoid
+ // changing server code.
+ static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( ! media_settings[ base_key ].asBoolean() );
+ }
+ else
+ if ( data_set[ i ].ctrl_type == "LLComboBox" )
+ static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
+ setCurrentByIndex( media_settings[ base_key ].asInteger() );
+
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsPermissions::apply( void* userdata )
+{
+ LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata;
+
+ // build LLSD Fragment
+ LLSD media_data_permissions;
+ self->getValues(media_data_permissions);
+
+ // this merges contents of LLSD passed in with what's there so this is ok
+ LLSelectMgr::getInstance()->selectionSetMediaData( media_data_permissions );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsPermissions::getValues( LLSD &fill_me_in )
+{
+ // *NOTE: For some reason, gcc does not like these symbol references in the
+ // expressions below (inside the static_casts). I have NO idea why :(.
+ // For some reason, assigning them to const temp vars here fixes the link
+ // error. Bizarre.
+ const U8 none = LLMediaEntry::PERM_NONE;
+ const U8 owner = LLMediaEntry::PERM_OWNER;
+ const U8 group = LLMediaEntry::PERM_GROUP;
+ const U8 anyone = LLMediaEntry::PERM_ANYONE;
+ const LLSD::Integer control = static_cast(
+ (mPermsOwnerControl->getValue() ? none : owner ) |
+ (mPermsGroupControl->getValue() ? none : group ) |
+ (mPermsWorldControl->getValue() ? none : anyone ));
+ const LLSD::Integer interact = static_cast(
+ (mPermsOwnerInteract->getValue() ? none : owner ) |
+ (mPermsGroupInteract->getValue() ? none : group ) |
+ (mPermsWorldInteract->getValue() ? none : anyone ));
+ fill_me_in[LLMediaEntry::PERMS_CONTROL_KEY] = control;
+ fill_me_in[LLMediaEntry::PERMS_INTERACT_KEY] = interact;
+}
diff --git a/indra/newview/llpanelmediasettingspermissions.h b/indra/newview/llpanelmediasettingspermissions.h
new file mode 100644
index 0000000000..ce293e07b9
--- /dev/null
+++ b/indra/newview/llpanelmediasettingspermissions.h
@@ -0,0 +1,71 @@
+/**
+ * @file llpanelmediasettingspermissions.h
+ * @brief LLPanelMediaSettingsPermissions class definition
+ *
+ * note that "permissions" tab is really "Controls" tab - refs to 'perms' and
+ * 'permissions' not changed to 'controls' since we don't want to change
+ * shared files in server code and keeping everything the same seemed best.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 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$
+ */
+
+#ifndef LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H
+#define LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H
+
+#include "llpanel.h"
+#include "lluuid.h"
+
+class LLComboBox;
+class LLCheckBoxCtrl;
+class LLNameBox;
+
+class LLPanelMediaSettingsPermissions : public LLPanel
+{
+ public:
+ BOOL postBuild();
+ virtual void draw();
+ static void apply(void*);
+ void getValues(LLSD &fill_me_in);
+
+ LLPanelMediaSettingsPermissions();
+ ~LLPanelMediaSettingsPermissions();
+
+ static void initValues( void* userdata, const LLSD& media_settings );
+ static void clearValues( void* userdata );
+
+ private:
+ LLCheckBoxCtrl* mPermsOwnerInteract;
+ LLCheckBoxCtrl* mPermsOwnerControl;
+ LLNameBox* mPermsGroupName;
+ LLCheckBoxCtrl* mPermsGroupInteract;
+ LLCheckBoxCtrl* mPermsGroupControl;
+ LLCheckBoxCtrl* mPermsWorldInteract;
+ LLCheckBoxCtrl* mPermsWorldControl;
+};
+
+#endif // LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H
diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp
new file mode 100644
index 0000000000..a4eee82aa9
--- /dev/null
+++ b/indra/newview/llpanelmediasettingssecurity.cpp
@@ -0,0 +1,233 @@
+/**
+ * @file llpanelmediasettingssecurity.cpp
+ * @brief LLPanelMediaSettingsSecurity class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 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"
+#include "llfloaterreg.h"
+#include "llpanelmediasettingssecurity.h"
+#include "llpanelcontents.h"
+#include "llcheckboxctrl.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llfloaterwhitelistentry.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity()
+{
+ // build dialog from XML
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml");
+ mCommitCallbackRegistrar.add("Media.whitelistAdd", boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this));
+ mCommitCallbackRegistrar.add("Media.whitelistDelete", boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsSecurity::postBuild()
+{
+ mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY );
+ mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY );
+
+ childSetAction("whitelist_add", onBtnAdd, this);
+ childSetAction("whitelist_del", onBtnDel, this);
+
+ setDefaultBtn("whitelist_add");
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+
+ // if list is empty, disable DEL button and checkbox to enable use of list
+ if ( mWhiteListList->isEmpty() )
+ {
+ childSetEnabled( "whitelist_del", false );
+ childSetEnabled( LLMediaEntry::WHITELIST_KEY, false );
+ childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false );
+ }
+ else
+ {
+ childSetEnabled( "whitelist_del", true );
+ childSetEnabled( LLMediaEntry::WHITELIST_KEY, true );
+ childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true );
+ };
+
+ // if nothing is selected, disable DEL button
+ if ( mWhiteListList->getSelectedValue().asString().empty() )
+ {
+ childSetEnabled( "whitelist_del", false );
+ }
+ else
+ {
+ childSetEnabled( "whitelist_del", true );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ std::string base_key( "" );
+ std::string tentative_key( "" );
+
+ struct
+ {
+ std::string key_name;
+ LLUICtrl* ctrl_ptr;
+ std::string ctrl_type;
+
+ } data_set [] =
+ {
+ { LLMediaEntry::WHITELIST_ENABLE_KEY, self->mEnableWhiteList, "LLCheckBoxCtrl" },
+ { LLMediaEntry::WHITELIST_KEY, self->mWhiteListList, "LLScrollListCtrl" },
+ { "", NULL , "" }
+ };
+
+ for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+ {
+ base_key = std::string( data_set[ i ].key_name );
+ tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+
+ // TODO: CP - I bet there is a better way to do this using Boost
+ if ( media_settings[ base_key ].isDefined() )
+ {
+ if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+ {
+ static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asBoolean() );
+ }
+ else
+ if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" )
+ {
+ // get control
+ LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr );
+ list->deleteAllItems();
+
+ // points to list of white list URLs
+ LLSD url_list = media_settings[ base_key ];
+
+ // iterate over them and add to scroll list
+ LLSD::array_iterator iter = url_list.beginArray();
+ while( iter != url_list.endArray() )
+ {
+ // TODO: is iter guaranteed to be valid here?
+ std::string url = *iter;
+ list->addSimpleElement( url );
+ ++iter;
+ };
+ };
+
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::clearValues( void* userdata )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+ self->mEnableWhiteList->clear();
+ self->mWhiteListList->deleteAllItems();
+}
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::apply( void* userdata )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ // build LLSD Fragment
+ LLSD media_data_security;
+ self->getValues(media_data_security);
+ // this merges contents of LLSD passed in with what's there so this is ok
+ LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in )
+{
+ fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue();
+
+ // iterate over white list and extract items
+ std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
+ std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
+ fill_me_in[LLMediaEntry::WHITELIST_KEY].clear();
+ while( iter != white_list_items.end() )
+ {
+ std::string white_list_url = (*iter)->getValue().asString();
+ fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url );
+ ++iter;
+ };
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url)
+{
+ mWhiteListList->addSimpleElement( url );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata )
+{
+ LLFloaterReg::showInstance("whitelist_entry");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ self->mWhiteListList->deleteSelectedItems();
+}
diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h
new file mode 100644
index 0000000000..d77509897d
--- /dev/null
+++ b/indra/newview/llpanelmediasettingssecurity.h
@@ -0,0 +1,64 @@
+/**
+ * @file llpanelmediasettingssecurity.h
+ * @brief LLPanelMediaSettingsSecurity class definition
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 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$
+ */
+
+#ifndef LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H
+#define LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H
+
+#include "llpanel.h"
+
+class LLCheckBoxCtrl;
+class LLScrollListCtrl;
+
+class LLPanelMediaSettingsSecurity : public LLPanel
+{
+ public:
+ BOOL postBuild();
+ virtual void draw();
+ static void apply(void*);
+ void getValues(LLSD &fill_me_in);
+
+ LLPanelMediaSettingsSecurity();
+ ~LLPanelMediaSettingsSecurity();
+
+ static void initValues( void* userdata, const LLSD& media_settings );
+ static void clearValues( void* userdata );
+ void addWhiteListItem(const std::string& url);
+
+ private:
+ LLCheckBoxCtrl* mEnableWhiteList;
+ LLScrollListCtrl* mWhiteListList;
+
+ static void onBtnAdd(void*);
+ static void onBtnDel(void*);
+};
+
+#endif // LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index b25331e439..ae8c9f770b 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -1721,13 +1721,8 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright)
getSelection()->applyToObjects(&sendfunc);
}
-void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url)
+void LLSelectMgr::selectionSetMedia(U8 media_type)
{
- U8 media_flags = LLTextureEntry::MF_NONE;
- if (media_type == LLViewerObject::MEDIA_TYPE_WEB_PAGE)
- {
- media_flags = LLTextureEntry::MF_WEB_PAGE;
- }
struct f : public LLSelectedTEFunctor
{
@@ -1737,33 +1732,72 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string&
{
if (object->permModify())
{
- // update viewer side color in anticipation of update from simulator
+ // update viewer has media
object->setTEMediaFlags(te, mMediaFlags);
}
return true;
}
- } setfunc(media_flags);
+ } setfunc(media_type);
getSelection()->applyToTEs(&setfunc);
-
- struct g : public LLSelectedObjectFunctor
+ struct f2 : public LLSelectedObjectFunctor
{
- U8 media_type;
- const std::string& media_url ;
- g(U8 a, const std::string& b) : media_type(a), media_url(b) {}
virtual bool apply(LLViewerObject* object)
{
if (object->permModify())
{
object->sendTEUpdate();
- object->setMediaType(media_type);
- object->setMediaURL(media_url);
}
return true;
}
- } sendfunc(media_type, media_url);
- getSelection()->applyToObjects(&sendfunc);
+ } func2;
+ mSelectedObjects->applyToObjects( &func2 );
}
+// This function expects media_data to be a map containing relevant
+// media data name/value pairs (e.g. home_url, etc.)
+void LLSelectMgr::selectionSetMediaData(const LLSD &media_data)
+{
+
+ struct f : public LLSelectedTEFunctor
+ {
+ const LLSD &mMediaData;
+ f(const LLSD& t) : mMediaData(t) {}
+ bool apply(LLViewerObject* object, S32 te)
+ {
+ if (object->permModify())
+ {
+ LLVOVolume *vo = dynamic_cast(object);
+ if (NULL != vo)
+ {
+ vo->syncMediaData(te, mMediaData, true/*merge*/, true/*ignore_agent*/);
+ }
+ }
+ return true;
+ }
+ } setfunc(media_data);
+ getSelection()->applyToTEs(&setfunc);
+
+ struct f2 : public LLSelectedObjectFunctor
+ {
+ virtual bool apply(LLViewerObject* object)
+ {
+ if (object->permModify())
+ {
+ LLVOVolume *vo = dynamic_cast(object);
+ if (NULL != vo)
+ {
+ // Send updated media data FOR THE ENTIRE OBJECT
+ vo->sendMediaDataUpdate();
+ }
+ }
+ return true;
+ }
+ } func2;
+ getSelection()->applyToObjects(&func2);
+}
+
+
+
void LLSelectMgr::selectionSetGlow(F32 glow)
{
struct f1 : public LLSelectedTEFunctor
@@ -5057,7 +5091,15 @@ void LLSelectNode::selectTE(S32 te_index, BOOL selected)
{
return;
}
- mTESelectMask |= 0x1 << te_index;
+ S32 mask = 0x1 << te_index;
+ if(selected)
+ {
+ mTESelectMask |= mask;
+ }
+ else
+ {
+ mTESelectMask &= ~mask;
+ }
mLastTESelected = te_index;
}
@@ -6042,6 +6084,29 @@ bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool first
return result;
}
+BOOL LLObjectSelection::isMultipleTESelected()
+{
+ BOOL te_selected = FALSE;
+ // ...all faces
+ for (LLObjectSelection::iterator iter = begin();
+ iter != end(); iter++)
+ {
+ LLSelectNode* nodep = *iter;
+ for (S32 i = 0; i < SELECT_MAX_TES; i++)
+ {
+ if(nodep->isTESelected(i))
+ {
+ if(te_selected)
+ {
+ return TRUE;
+ }
+ te_selected = TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
//-----------------------------------------------------------------------------
// contains()
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 08c2783746..9e02170d74 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -307,6 +307,7 @@ public:
S32 getTECount();
S32 getRootObjectCount();
+ BOOL isMultipleTESelected();
BOOL contains(LLViewerObject* object);
BOOL contains(LLViewerObject* object, S32 te);
@@ -504,7 +505,8 @@ public:
void selectionSetTexGen( U8 texgen );
void selectionSetShiny( U8 shiny );
void selectionSetFullbright( U8 fullbright );
- void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url );
+ void selectionSetMedia( U8 media_type );
+ void selectionSetMediaData(const LLSD &media_data); // NOTE: modifies media_data!!!
void selectionSetClickAction(U8 action);
void selectionSetIncludeInSearch(bool include_in_search);
void selectionSetGlow(const F32 glow);
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 4e13cb17a2..7bf0d31d94 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -433,6 +433,11 @@ void LLSpatialGroup::clearDrawMap()
mDrawMap.clear();
}
+BOOL LLSpatialGroup::isRecentlyVisible() const
+{
+ return (LLDrawable::getCurrentFrame() - (S32)mVisible) < LLDrawable::getMinVisFrameRange() ;
+}
+
BOOL LLSpatialGroup::isVisible() const
{
return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 16e8782a8e..64c2a9acbc 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -267,6 +267,7 @@ public:
BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE);
BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group
BOOL isVisible() const;
+ BOOL isRecentlyVisible() const;
void setVisible();
void shift(const LLVector3 &offset);
BOOL boundObjects(BOOL empty, LLVector3& newMin, LLVector3& newMax);
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index ceb1358d1c..880d5d5e12 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -67,18 +67,20 @@ LLTool::~LLTool()
BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
{
- // This is necessary to force clicks in the world to cause edit
- // boxes that might have keyboard focus to relinquish it, and hence
- // cause a commit to update their value. JC
- if (down)
+ BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
+
+ // This behavior was moved here from LLViewerWindow::handleAnyMouseClick, so it can be selectively overridden by LLTool subclasses.
+ if(down && result)
{
+ // This is necessary to force clicks in the world to cause edit
+ // boxes that might have keyboard focus to relinquish it, and hence
+ // cause a commit to update their value. JC
gFocusMgr.setKeyboardFocus(NULL);
}
-
- return LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
+
+ return result;
}
-
BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (gDebugClicks)
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 5c210c5c28..d5db224143 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -48,6 +48,7 @@
#include "lltooltip.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
+#include "llmediaentry.h"
#include "llmenugl.h"
#include "llmutelist.h"
#include "llselectmgr.h"
@@ -75,8 +76,6 @@ extern void handle_buy(void*);
extern BOOL gDebugClicks;
-static bool handle_media_click(const LLPickInfo& info);
-static bool handle_media_hover(const LLPickInfo& info);
static void handle_click_action_play();
static void handle_click_action_open_media(LLPointer objectp);
static ECursorType cursor_from_parcel_media(U8 click_action);
@@ -90,6 +89,16 @@ LLToolPie::LLToolPie()
{ }
+BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
+{
+ BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
+
+ // This override DISABLES the keyboard focus reset that LLTool::handleAnyMouseClick adds.
+ // LLToolPie will do the right thing in its pick callback.
+
+ return result;
+}
+
BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
{
//left mouse down always picks transparent
@@ -258,9 +267,9 @@ BOOL LLToolPie::pickLeftMouseDownCallback()
}
}
- if (handle_media_click(mPick))
+ if (handleMediaClick(mPick))
{
- return FALSE;
+ return TRUE;
}
// put focus back "in world"
@@ -466,10 +475,7 @@ void LLToolPie::selectionPropertiesReceived()
BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
{
mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE);
-
- // FIXME: This was in the pluginapi branch, but I don't think it's correct.
-// gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
-
+
LLViewerObject *parent = NULL;
LLViewerObject *object = mHoverPick.getObject();
@@ -484,7 +490,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
gViewerWindow->setCursor(cursor);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
- else if (handle_media_hover(mHoverPick))
+ else if (handleMediaHover(mHoverPick))
{
// cursor set by media object
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
@@ -522,6 +528,9 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
{
LLViewerObject* obj = mPick.getObject();
+
+ handleMediaMouseUp();
+
U8 click_action = final_click_action(obj);
if (click_action != CLICK_ACTION_NONE)
{
@@ -543,6 +552,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
break;
}
}
+
mGrabMouseButtonDown = FALSE;
LLToolMgr::getInstance()->clearTransientTool();
gAgent.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on
@@ -1038,6 +1048,7 @@ void LLToolPie::stopEditing()
void LLToolPie::onMouseCaptureLost()
{
mMouseOutsideSlop = FALSE;
+ handleMediaMouseUp();
}
@@ -1078,7 +1089,7 @@ static void handle_click_action_play()
}
}
-static bool handle_media_click(const LLPickInfo& pick)
+bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
{
//FIXME: how do we handle object in different parcel than us?
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
@@ -1104,22 +1115,25 @@ static bool handle_media_click(const LLPickInfo& pick)
// is media playing on this face?
const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
+ LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
+ viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL;
- viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID());
- if (tep
- && media_impl.notNull()
- && media_impl->hasMedia()
- && gSavedSettings.getBOOL("MediaOnAPrimUI"))
+ if (tep
+ && mep
+ && gSavedSettings.getBOOL("MediaOnAPrimUI")
+ && media_impl.notNull())
{
- LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection();
- if (! selection->contains(pick.getObject(), pick.mObjectFace))
+ // LLObjectSelectionHandle selection = /*LLViewerMediaFocus::getInstance()->getSelection()*/ LLSelectMgr::getInstance()->getSelection();
+ if (/*! selection->contains(pick.getObject(), pick.mObjectFace)*/
+ ! LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) )
{
LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl);
}
else
{
- media_impl->mouseDown(pick.mXYCoords.mX, pick.mXYCoords.mY);
- media_impl->mouseCapture(); // the mouse-up will happen when capture is lost
+ media_impl->mouseDown(pick.mUVCoords);
+ mMediaMouseCaptureID = mep->getMediaID();
+ setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
}
return true;
@@ -1131,7 +1145,7 @@ static bool handle_media_click(const LLPickInfo& pick)
return false;
}
-static bool handle_media_hover(const LLPickInfo& pick)
+bool LLToolPie::handleMediaHover(const LLPickInfo& pick)
{
//FIXME: how do we handle object in different parcel than us?
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
@@ -1156,15 +1170,20 @@ static bool handle_media_hover(const LLPickInfo& pick)
// is media playing on this face?
const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
- viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID());
- if (tep
- && media_impl.notNull()
- && media_impl->hasMedia()
+ const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if (mep
&& gSavedSettings.getBOOL("MediaOnAPrimUI"))
- {
- if(LLViewerMediaFocus::getInstance()->getFocus())
+ {
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+ if(LLViewerMediaFocus::getInstance()->getFocus() && media_impl.notNull())
{
- media_impl->mouseMove(pick.mXYCoords.mX, pick.mXYCoords.mY);
+ media_impl->mouseMove(pick.mUVCoords);
+
+ gViewerWindow->setCursor(media_impl->getLastSetCursor());
+ }
+ else
+ {
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
}
// Set mouse over flag if unset
@@ -1182,6 +1201,28 @@ static bool handle_media_hover(const LLPickInfo& pick)
return false;
}
+bool LLToolPie::handleMediaMouseUp()
+{
+ bool result = false;
+ if(mMediaMouseCaptureID.notNull())
+ {
+ // Face media needs to know the mouse went up.
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mMediaMouseCaptureID);
+ if(media_impl)
+ {
+ // This will send a mouseUp event to the plugin using the last known mouse coordinate (from a mouseDown or mouseMove), which is what we want.
+ media_impl->onMouseCaptureLost();
+ }
+
+ mMediaMouseCaptureID.setNull();
+
+ setMouseCapture(FALSE);
+
+ result = true;
+ }
+
+ return result;
+}
static void handle_click_action_open_media(LLPointer objectp)
{
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 328653d2b8..f6a67c13b1 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -42,9 +42,12 @@ class LLObjectSelection;
class LLToolPie : public LLTool, public LLSingleton
{
+ LOG_CLASS(LLToolPie);
public:
LLToolPie( );
+ // Virtual functions inherited from LLMouseHandler
+ virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@@ -81,9 +84,15 @@ private:
BOOL useClickAction (MASK mask, LLViewerObject* object,LLViewerObject* parent);
void showVisualContextMenuEffect();
+
+ bool handleMediaClick(const LLPickInfo& info);
+ bool handleMediaHover(const LLPickInfo& info);
+ bool handleMediaMouseUp();
+
private:
BOOL mGrabMouseButtonDown;
BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region
+ LLUUID mMediaMouseCaptureID;
LLPickInfo mPick;
LLPickInfo mHoverPick;
LLPointer mClickActionObject;
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 725ed57d20..2f656479f6 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -67,6 +67,7 @@
#include "llfloaterhardwaresettings.h"
#include "llfloaterhelpbrowser.h"
#include "llfloatermediabrowser.h"
+#include "llfloatermediasettings.h"
#include "llfloaterhud.h"
#include "llfloaterimagepreview.h"
#include "llimfloater.h"
@@ -105,6 +106,7 @@
#include "llfloaterurldisplay.h"
#include "llfloatervoicedevicesettings.h"
#include "llfloaterwater.h"
+#include "llfloaterwhitelistentry.h"
#include "llfloaterwindlight.h"
#include "llfloaterworldmap.h"
#include "llinspectavatar.h"
@@ -178,6 +180,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
LLFloaterReg::add("media_browser", "floater_media_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
+ LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
@@ -238,6 +241,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("voice_call", "floater_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
+ LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build);
// *NOTE: Please keep these alphabetized for easier merges
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index f033d66c1f..100a34291b 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -35,12 +35,14 @@
#include "llviewermedia.h"
#include "llviewermediafocus.h"
#include "llmimetypes.h"
+#include "llmediaentry.h"
#include "llviewercontrol.h"
#include "llviewertexture.h"
#include "llviewerparcelmedia.h"
#include "llviewerparcelmgr.h"
#include "llversionviewer.h"
#include "llviewertexturelist.h"
+#include "llvovolume.h"
#include "llpluginclassmedia.h"
#include "llevent.h" // LLSimpleListener
@@ -95,10 +97,10 @@ bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer )
///////////////////////////////////////////////////////////////////////////////
//
-void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLPluginClassMediaOwner::EMediaEvent event )
+void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLViewerMediaObserver::EMediaEvent event )
{
+ // Broadcast the event to any observers.
observerListType::iterator iter = mObservers.begin();
-
while( iter != mObservers.end() )
{
LLViewerMediaObserver *self = *iter;
@@ -166,43 +168,17 @@ public:
};
typedef std::vector impl_list;
static impl_list sViewerMediaImplList;
+static LLTimer sMediaCreateTimer;
+static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
//////////////////////////////////////////////////////////////////////////////////////////
-// LLViewerMedia
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-viewer_media_t LLViewerMedia::newMediaImpl(const std::string& media_url,
- const LLUUID& texture_id,
- S32 media_width, S32 media_height, U8 media_auto_scale,
- U8 media_loop,
- std::string mime_type)
+static void add_media_impl(LLViewerMediaImpl* media)
{
- LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id);
- if(media_impl == NULL || texture_id.isNull())
- {
- // Create the media impl
- media_impl = new LLViewerMediaImpl(media_url, texture_id, media_width, media_height, media_auto_scale, media_loop, mime_type);
- sViewerMediaImplList.push_back(media_impl);
- }
- else
- {
- media_impl->stop();
- media_impl->mTextureId = texture_id;
- media_impl->mMediaURL = media_url;
- media_impl->mMediaWidth = media_width;
- media_impl->mMediaHeight = media_height;
- media_impl->mMediaAutoScale = media_auto_scale;
- media_impl->mMediaLoop = media_loop;
- if(! media_url.empty())
- media_impl->navigateTo(media_url, mime_type, true);
- }
- return media_impl;
+ sViewerMediaImplList.push_back(media);
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::removeMedia(LLViewerMediaImpl* media)
+static void remove_media_impl(LLViewerMediaImpl* media)
{
impl_list::iterator iter = sViewerMediaImplList.begin();
impl_list::iterator end = sViewerMediaImplList.end();
@@ -217,6 +193,104 @@ void LLViewerMedia::removeMedia(LLViewerMediaImpl* media)
}
}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// LLViewerMedia
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+viewer_media_t LLViewerMedia::newMediaImpl(
+ const LLUUID& texture_id,
+ S32 media_width,
+ S32 media_height,
+ U8 media_auto_scale,
+ U8 media_loop)
+{
+ LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id);
+ if(media_impl == NULL || texture_id.isNull())
+ {
+ // Create the media impl
+ media_impl = new LLViewerMediaImpl(texture_id, media_width, media_height, media_auto_scale, media_loop);
+ }
+ else
+ {
+ media_impl->stop();
+ media_impl->mTextureId = texture_id;
+ media_impl->mMediaWidth = media_width;
+ media_impl->mMediaHeight = media_height;
+ media_impl->mMediaAutoScale = media_auto_scale;
+ media_impl->mMediaLoop = media_loop;
+ }
+
+ return media_impl;
+}
+
+viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self)
+{
+ // Try to find media with the same media ID
+ viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
+
+ bool was_loaded = false;
+ bool needs_navigate = false;
+
+ if(media_impl)
+ {
+ was_loaded = media_impl->hasMedia();
+
+ media_impl->setHomeURL(media_entry->getHomeURL());
+
+ media_impl->mMediaAutoScale = media_entry->getAutoScale();
+ media_impl->mMediaLoop = media_entry->getAutoLoop();
+ media_impl->mMediaWidth = media_entry->getWidthPixels();
+ media_impl->mMediaHeight = media_entry->getHeightPixels();
+ if (media_impl->mMediaSource)
+ {
+ media_impl->mMediaSource->setAutoScale(media_impl->mMediaAutoScale);
+ media_impl->mMediaSource->setLoop(media_impl->mMediaLoop);
+ media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
+ }
+
+ if((was_loaded || media_entry->getAutoPlay()) && !update_from_self)
+ {
+ if(!media_entry->getCurrentURL().empty())
+ {
+ needs_navigate = (media_entry->getCurrentURL() != previous_url);
+ }
+ else if(!media_entry->getHomeURL().empty())
+ {
+ needs_navigate = (media_entry->getHomeURL() != previous_url);
+ }
+ }
+ }
+ else
+ {
+ media_impl = newMediaImpl(
+ media_entry->getMediaID(),
+ media_entry->getWidthPixels(),
+ media_entry->getHeightPixels(),
+ media_entry->getAutoScale(),
+ media_entry->getAutoLoop());
+
+ media_impl->setHomeURL(media_entry->getHomeURL());
+
+ if(media_entry->getAutoPlay())
+ {
+ needs_navigate = true;
+ }
+ }
+
+ if(media_impl && needs_navigate)
+ {
+ std::string url = media_entry->getCurrentURL();
+ if(url.empty())
+ url = media_entry->getHomeURL();
+
+ media_impl->navigateTo(url, "", true, true);
+ }
+
+ return media_impl;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
// static
LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id)
@@ -323,6 +397,36 @@ void LLViewerMedia::setVolume(F32 volume)
}
}
+// This is the predicate function used to sort sViewerMediaImplList by priority.
+static inline bool compare_impl_interest(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+{
+ if(i1->hasFocus())
+ {
+ // The item with user focus always comes to the front of the list, period.
+ return true;
+ }
+ else if(i2->hasFocus())
+ {
+ // The item with user focus always comes to the front of the list, period.
+ return false;
+ }
+ else if(i1->getUsedInUI() && !i2->getUsedInUI())
+ {
+ // i1 is a UI element, i2 is not. This makes i1 "less than" i2, so it sorts earlier in our list.
+ return true;
+ }
+ else if(i2->getUsedInUI() && !i1->getUsedInUI())
+ {
+ // i2 is a UI element, i1 is not. This makes i2 "less than" i1, so it sorts earlier in our list.
+ return false;
+ }
+ else
+ {
+ // The object with the larger interest value should be earlier in the list, so we reverse the sense of the comparison here.
+ return (i1->getInterest() > i2->getInterest());
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
// static
void LLViewerMedia::updateMedia()
@@ -334,32 +438,138 @@ void LLViewerMedia::updateMedia()
{
LLViewerMediaImpl* pimpl = *iter;
pimpl->update();
+ pimpl->calculateInterest();
}
+
+ // Sort the static instance list using our interest criteria
+ std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), compare_impl_interest);
+
+ // Go through the list again and adjust according to priority.
+ iter = sViewerMediaImplList.begin();
+ end = sViewerMediaImplList.end();
+
+ F64 total_cpu = 0.0f;
+ int impl_count_total = 0;
+ int impl_count_interest_low = 0;
+ int impl_count_interest_normal = 0;
+
+#if 0
+ LL_DEBUGS("PluginPriority") << "Sorted impls:" << llendl;
+#endif
+
+ U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal");
+ U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal");
+ U32 max_low = gSavedSettings.getU32("PluginInstancesLow");
+ F32 max_cpu = gSavedSettings.getF32("PluginInstancesCPULimit");
+ // Setting max_cpu to 0.0 disables CPU usage checking.
+ bool check_cpu_usage = (max_cpu != 0.0f);
+
+ // Notes on tweakable params:
+ // max_instances must be set high enough to allow the various instances used in the UI (for the help browser, search, etc.) to be loaded.
+ // If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow.
+
+ for(; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+
+ LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+
+ if(impl_count_total > (int)max_instances)
+ {
+ // Hard limit on the number of instances that will be loaded at one time
+ new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
+ }
+ else if(!pimpl->getVisible())
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
+ }
+ else if(pimpl->hasFocus())
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_HIGH;
+ }
+ else if(pimpl->getUsedInUI())
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+ }
+ else
+ {
+ // Look at interest and CPU usage for instances that aren't in any of the above states.
+
+ // Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture,
+ // turn it down to low instead of normal. This may downsample for plugins that support it.
+ bool media_is_small = pimpl->getInterest() < (pimpl->getApproximateTextureInterest() / 4);
+
+ if(pimpl->getInterest() == 0.0f)
+ {
+ // This media is completely invisible, due to being outside the view frustrum or out of range.
+ new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
+ }
+ else if(check_cpu_usage && (total_cpu > max_cpu))
+ {
+ // Higher priority plugins have already used up the CPU budget. Set remaining ones to slideshow priority.
+ new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
+ }
+ else if((impl_count_interest_normal < (int)max_normal) && !media_is_small)
+ {
+ // Up to max_normal inworld get normal priority
+ new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+ impl_count_interest_normal++;
+ }
+ else if (impl_count_interest_low + impl_count_interest_normal < (int)max_low + (int)max_normal)
+ {
+ // The next max_low inworld get turned down
+ new_priority = LLPluginClassMedia::PRIORITY_LOW;
+ impl_count_interest_low++;
+
+ // Set the low priority size for downsampling to approximately the size the texture is displayed at.
+ {
+ F32 approximate_interest_dimension = fsqrtf(pimpl->getInterest());
+
+ pimpl->setLowPrioritySizeLimit(llround(approximate_interest_dimension));
+ }
+ }
+ else
+ {
+ // Any additional impls (up to max_instances) get very infrequent time
+ new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
+ }
+ }
+
+ pimpl->setPriority(new_priority);
+
+#if 0
+ LL_DEBUGS("PluginPriority") << " " << pimpl
+ << ", setting priority to " << new_priority
+ << (pimpl->hasFocus()?", HAS FOCUS":"")
+ << (pimpl->getUsedInUI()?", is UI":"")
+ << ", cpu " << pimpl->getCPUUsage()
+ << ", interest " << pimpl->getInterest()
+ << ", media url " << pimpl->getMediaURL() << llendl;
+#endif
+
+ total_cpu += pimpl->getCPUUsage();
+ impl_count_total++;
+ }
+
+ LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
+
}
//////////////////////////////////////////////////////////////////////////////////////////
// static
void LLViewerMedia::cleanupClass()
{
- // This is no longer necessary, since the list is no longer smart pointers.
-#if 0
- while(!sViewerMediaImplList.empty())
- {
- sViewerMediaImplList.pop_back();
- }
-#endif
+ // This is no longer necessary, since sViewerMediaImplList is no longer smart pointers.
}
//////////////////////////////////////////////////////////////////////////////////////////
// LLViewerMediaImpl
//////////////////////////////////////////////////////////////////////////////////////////
-LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url,
- const LLUUID& texture_id,
+LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
S32 media_width,
S32 media_height,
U8 media_auto_scale,
- U8 media_loop,
- const std::string& mime_type)
+ U8 media_loop)
:
mMediaSource( NULL ),
mMovieImageHasMips(false),
@@ -368,13 +578,30 @@ LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url,
mMediaHeight(media_height),
mMediaAutoScale(media_auto_scale),
mMediaLoop(media_loop),
- mMediaURL(media_url),
- mMimeType(mime_type),
mNeedsNewTexture(true),
mSuspendUpdates(false),
- mVisible(true)
+ mVisible(true),
+ mLastSetCursor( UI_CURSOR_ARROW ),
+ mMediaNavState( MEDIANAVSTATE_NONE ),
+ mInterest(0.0f),
+ mUsedInUI(false),
+ mHasFocus(false),
+ mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
+ mDoNavigateOnLoad(false),
+ mDoNavigateOnLoadServerRequest(false),
+ mIsUpdated(false)
{
- createMediaSource();
+
+ add_media_impl(this);
+
+ // connect this media_impl to the media texture, creating it if it doesn't exist.0
+ // This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded.
+ LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId);
+ if(media_tex)
+ {
+ media_tex->setMediaImpl();
+ }
+
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -386,7 +613,26 @@ LLViewerMediaImpl::~LLViewerMediaImpl()
}
destroyMediaSource();
- LLViewerMedia::removeMedia(this);
+
+ LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ;
+
+ remove_media_impl(this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
+{
+ // Broadcast to observers using the superclass version
+ LLViewerMediaEventEmitter::emitEvent(plugin, event);
+
+ // If this media is on one or more LLVOVolume objects, tell them about the event as well.
+ std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+ while(iter != mObjectList.end())
+ {
+ LLVOVolume *self = *iter;
+ ++iter;
+ self->mediaEvent(this, plugin, event);
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -396,11 +642,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
{
if(! initializePlugin(mime_type))
{
- LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << mime_type << LL_ENDL;
- LLSD args;
- args["MIME_TYPE"] = mime_type;
- LLNotifications::instance().add("NoPlugin", args);
-
+ // This may be the case where the plugin's priority is PRIORITY_UNLOADED
return false;
}
}
@@ -412,29 +654,42 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::createMediaSource()
{
- if(! mMediaURL.empty())
+ if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
{
- navigateTo(mMediaURL, mMimeType, true);
- }
- else if(! mMimeType.empty())
- {
- initializeMedia(mMimeType);
+ // This media shouldn't be created yet.
+ return;
}
+ if(mDoNavigateOnLoad)
+ {
+ if(! mMediaURL.empty())
+ {
+ navigateTo(mMediaURL, mMimeType, false, mDoNavigateOnLoadServerRequest);
+ }
+ else if(! mMimeType.empty())
+ {
+ initializeMedia(mMimeType);
+ }
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::destroyMediaSource()
{
mNeedsNewTexture = true;
- if(! mMediaSource)
+
+ // Tell the viewer media texture it's no longer active
+ LLViewerMediaTexture* oldImage = LLViewerTextureManager::findMediaTexture( mTextureId );
+ if (oldImage)
{
- return;
+ oldImage->setPlaying(FALSE) ;
}
- // Restore the texture
- updateMovieImage(LLUUID::null, false);
- delete mMediaSource;
- mMediaSource = NULL;
+
+ if(mMediaSource)
+ {
+ delete mMediaSource;
+ mMediaSource = NULL;
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -487,6 +742,11 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
}
}
+ LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
+ LLSD args;
+ args["MIME_TYPE"] = media_type;
+ LLNotifications::instance().add("NoPlugin", args);
+
return NULL;
}
@@ -506,7 +766,15 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
// and unconditionally set the mime type
mMimeType = media_type;
- LLPluginClassMedia* media_source = newSourceFromMediaType(media_type, this, mMediaWidth, mMediaHeight);
+ if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ // This impl should not be loaded at this time.
+ LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
+
+ return false;
+ }
+
+ LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight);
if (media_source)
{
@@ -543,13 +811,11 @@ void LLViewerMediaImpl::play()
{
if(!initializePlugin(mMimeType))
{
- // Plugin failed initialization... should assert or something
+ // This may be the case where the plugin's priority is PRIORITY_UNLOADED
return;
}
}
- // updateMovieImage(mTextureId, true);
-
mMediaSource->loadURI( mMediaURL );
if(/*mMediaSource->pluginSupportsMediaTime()*/ true)
{
@@ -606,6 +872,8 @@ void LLViewerMediaImpl::setVolume(F32 volume)
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::focus(bool focus)
{
+ mHasFocus = focus;
+
if (mMediaSource)
{
// call focus just for the hell of it, even though this apopears to be a nop
@@ -620,12 +888,20 @@ void LLViewerMediaImpl::focus(bool focus)
}
}
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::hasFocus() const
+{
+ // FIXME: This might be able to be a bit smarter by hooking into LLViewerMediaFocus, etc.
+ return mHasFocus;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::mouseDown(S32 x, S32 y)
{
scaleMouse(&x, &y);
mLastMouseX = x;
mLastMouseY = y;
+// llinfos << "mouse down (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, x, y, 0);
@@ -638,6 +914,7 @@ void LLViewerMediaImpl::mouseUp(S32 x, S32 y)
scaleMouse(&x, &y);
mLastMouseX = x;
mLastMouseY = y;
+// llinfos << "mouse up (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, x, y, 0);
@@ -647,15 +924,47 @@ void LLViewerMediaImpl::mouseUp(S32 x, S32 y)
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::mouseMove(S32 x, S32 y)
{
- scaleMouse(&x, &y);
+ scaleMouse(&x, &y);
mLastMouseX = x;
mLastMouseY = y;
+// llinfos << "mouse move (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, x, y, 0);
}
}
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords)
+{
+ if(mMediaSource)
+ {
+ mouseDown(
+ llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ }
+}
+
+void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords)
+{
+ if(mMediaSource)
+ {
+ mouseUp(
+ llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ }
+}
+
+void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords)
+{
+ if(mMediaSource)
+ {
+ mouseMove(
+ llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y)
{
@@ -694,6 +1003,10 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::navigateHome()
{
+ mMediaURL = mHomeURL;
+ mDoNavigateOnLoad = !mMediaURL.empty();
+ mDoNavigateOnLoadServerRequest = false;
+
if(mMediaSource)
{
mMediaSource->loadURI( mHomeURL );
@@ -701,17 +1014,43 @@ void LLViewerMediaImpl::navigateHome()
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type)
+void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
{
+ if(server_request)
+ {
+ setNavState(MEDIANAVSTATE_SERVER_SENT);
+ }
+ else
+ {
+ setNavState(MEDIANAVSTATE_NONE);
+ }
+
+ // Always set the current URL.
+ mMediaURL = url;
+
+ // If the current URL is not null, make the instance do a navigate on load.
+ mDoNavigateOnLoad = !mMediaURL.empty();
+
+ // and if this was a server request, the navigate on load will also need to be one.
+ mDoNavigateOnLoadServerRequest = server_request;
+
+ if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ // This impl should not be loaded at this time.
+ LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
+
+ return;
+ }
+
if(rediscover_type)
{
- LLURI uri(url);
+ LLURI uri(mMediaURL);
std::string scheme = uri.scheme();
if(scheme.empty() || "http" == scheme || "https" == scheme)
{
- LLHTTPClient::getHeaderOnly( url, new LLMimeDiscoveryResponder(this));
+ LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this));
}
else if("data" == scheme || "file" == scheme || "about" == scheme)
{
@@ -719,7 +1058,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
// We use "data" internally for a text/html url for loading the login screen
if(initializeMedia("text/html"))
{
- mMediaSource->loadURI( url );
+ mMediaSource->loadURI( mMediaURL );
}
}
else
@@ -727,24 +1066,23 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
// This catches 'rtsp://' urls
if(initializeMedia(scheme))
{
- mMediaSource->loadURI( url );
+ mMediaSource->loadURI( mMediaURL );
}
}
}
else if (mMediaSource)
{
- mMediaSource->loadURI( url );
+ mMediaSource->loadURI( mMediaURL );
}
else if(initializeMedia(mime_type) && mMediaSource)
{
- mMediaSource->loadURI( url );
+ mMediaSource->loadURI( mMediaURL );
}
else
{
LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL;
return;
}
- mMediaURL = url;
}
@@ -806,49 +1144,27 @@ bool LLViewerMediaImpl::canNavigateBack()
return result;
}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active)
-{
- // IF the media image hasn't changed, do nothing
- if (mTextureId == uuid)
- {
- return;
- }
- // If we have changed media uuid, restore the old one
- if (!mTextureId.isNull())
- {
- LLViewerMediaTexture* old_image = LLViewerTextureManager::findMediaTexture( mTextureId );
- if (old_image)
- {
- old_image->setPlaying(FALSE);
- LLViewerTexture* original_texture = old_image->getOldTexture();
- if(original_texture)
- {
- old_image->switchToTexture(original_texture);
- }
- }
- }
- // If the movie is playing, set the new media image
- if (active && !uuid.isNull())
- {
- LLViewerMediaTexture* viewerImage = LLViewerTextureManager::findMediaTexture( uuid );
- if( viewerImage )
- {
- mTextureId = uuid;
-
- // Can't use mipmaps for movies because they don't update the full image
- mMovieImageHasMips = viewerImage->getUseMipMaps();
- viewerImage->reinit(FALSE);
- // FIXME
-// viewerImage->mIsMediaTexture = TRUE;
- }
- }
-}
-
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::update()
{
+ if(mMediaSource == NULL)
+ {
+ if(mPriority != LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ // This media may need to be loaded.
+ if(sMediaCreateTimer.hasExpired())
+ {
+ LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL;
+ createMediaSource();
+ sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY);
+ }
+ else
+ {
+ LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL;
+ }
+ }
+ }
+
if(mMediaSource == NULL)
{
return;
@@ -877,6 +1193,10 @@ void LLViewerMediaImpl::update()
if(placeholder_image)
{
LLRect dirty_rect;
+
+ // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered.
+ placeholder_image->setPlaying(TRUE);
+
if(mMediaSource->getDirty(&dirty_rect))
{
// Constrain the dirty rect to be inside the texture
@@ -930,12 +1250,11 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
if (mNeedsNewTexture
|| placeholder_image->getUseMipMaps()
-// || ! placeholder_image->getType() == LLViewerTexture::MEDIA_TEXTURE
|| placeholder_image->getWidth() != mMediaSource->getTextureWidth()
|| placeholder_image->getHeight() != mMediaSource->getTextureHeight())
{
- llinfos << "initializing media placeholder" << llendl;
- llinfos << "movie image id " << mTextureId << llendl;
+ LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL;
+ LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL;
int texture_width = mMediaSource->getTextureWidth();
int texture_height = mMediaSource->getTextureHeight();
@@ -960,9 +1279,6 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
placeholder_image->createGLTexture(discard_level, raw);
- // placeholder_image->setExplicitFormat()
- placeholder_image->setUseMipMaps(FALSE);
-
// MEDIAOPT: set this dynamically on play/stop
// FIXME
// placeholder_image->mIsMediaTexture = true;
@@ -996,11 +1312,6 @@ void LLViewerMediaImpl::setVisible(bool visible)
createMediaSource();
}
}
-
- if(mMediaSource)
- {
- mMediaSource->setPriority(mVisible?LLPluginClassMedia::PRIORITY_NORMAL:LLPluginClassMedia::PRIORITY_HIDDEN);
- }
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1059,7 +1370,7 @@ bool LLViewerMediaImpl::hasMedia()
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event)
+void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
{
switch(event)
{
@@ -1070,11 +1381,77 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClass
LLNotifications::instance().add("MediaPluginFailed", args);
}
break;
+
+ case MEDIA_EVENT_CURSOR_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << plugin->getCursorName() << LL_ENDL;
+
+ std::string cursor = plugin->getCursorName();
+
+ if(cursor == "arrow")
+ mLastSetCursor = UI_CURSOR_ARROW;
+ else if(cursor == "ibeam")
+ mLastSetCursor = UI_CURSOR_IBEAM;
+ else if(cursor == "splith")
+ mLastSetCursor = UI_CURSOR_SIZEWE;
+ else if(cursor == "splitv")
+ mLastSetCursor = UI_CURSOR_SIZENS;
+ else if(cursor == "hand")
+ mLastSetCursor = UI_CURSOR_HAND;
+ else // for anything else, default to the arrow
+ mLastSetCursor = UI_CURSOR_ARROW;
+ }
+ break;
+
+ case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN:
+ {
+ LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL;
+
+ if(getNavState() == MEDIANAVSTATE_SERVER_SENT)
+ {
+ setNavState(MEDIANAVSTATE_SERVER_BEGUN);
+ }
+ else
+ {
+ setNavState(MEDIANAVSTATE_BEGUN);
+ }
+ }
+ break;
+
+ case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
+ {
+ LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL;
+ setNavState(MEDIANAVSTATE_NONE);
+ }
+ break;
+
+ case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED:
+ {
+ LL_DEBUGS("Media") << "MEDIA_EVENT_LOCATION_CHANGED, uri is: " << plugin->getLocation() << LL_ENDL;
+
+ if(getNavState() == MEDIANAVSTATE_BEGUN)
+ {
+ setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED);
+ }
+ else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
+ {
+ setNavState(MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED);
+ }
+ else
+ {
+ // Don't track redirects.
+ setNavState(MEDIANAVSTATE_NONE);
+ }
+ }
+ break;
+
+
default:
break;
}
+
// Just chain the event to observers.
- emitEvent(self, event);
+ emitEvent(plugin, event);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1137,6 +1514,146 @@ LLViewerMediaImpl::canPaste() const
return FALSE;
}
+void LLViewerMediaImpl::setUpdated(BOOL updated)
+{
+ mIsUpdated = updated ;
+}
+
+BOOL LLViewerMediaImpl::isUpdated()
+{
+ return mIsUpdated ;
+}
+
+void LLViewerMediaImpl::calculateInterest()
+{
+ LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId );
+
+ if(texture != NULL)
+ {
+ mInterest = texture->getMaxVirtualSize();
+ }
+ else
+ {
+ // I don't think this case should ever be hit.
+ LL_WARNS("Plugin") << "no texture!" << LL_ENDL;
+ mInterest = 0.0f;
+ }
+}
+
+F64 LLViewerMediaImpl::getApproximateTextureInterest()
+{
+ F64 result = 0.0f;
+
+ if(mMediaSource)
+ {
+ result = mMediaSource->getFullWidth();
+ result *= mMediaSource->getFullHeight();
+ }
+
+ return result;
+}
+
+void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
+{
+ mUsedInUI = used_in_ui;
+
+ // HACK: Force elements used in UI to load right away.
+ // This fixes some issues where UI code that uses the browser instance doesn't expect it to be unloaded.
+ if(mUsedInUI && (mPriority == LLPluginClassMedia::PRIORITY_UNLOADED))
+ {
+ if(getVisible())
+ {
+ mPriority = LLPluginClassMedia::PRIORITY_NORMAL;
+ }
+ else
+ {
+ mPriority = LLPluginClassMedia::PRIORITY_HIDDEN;
+ }
+
+ createMediaSource();
+ }
+};
+
+F64 LLViewerMediaImpl::getCPUUsage() const
+{
+ F64 result = 0.0f;
+
+ if(mMediaSource)
+ {
+ result = mMediaSource->getCPUUsage();
+ }
+
+ return result;
+}
+
+void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
+{
+ mPriority = priority;
+
+ if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ if(mMediaSource)
+ {
+ // Need to unload the media source
+ destroyMediaSource();
+ }
+ }
+
+ if(mMediaSource)
+ {
+ mMediaSource->setPriority(mPriority);
+ }
+
+ // NOTE: loading (or reloading) media sources whose priority has risen above PRIORITY_UNLOADED is done in update().
+}
+
+void LLViewerMediaImpl::setLowPrioritySizeLimit(int size)
+{
+ if(mMediaSource)
+ {
+ mMediaSource->setLowPrioritySizeLimit(size);
+ }
+}
+
+void LLViewerMediaImpl::setNavState(EMediaNavState state)
+{
+ mMediaNavState = state;
+
+ switch (state)
+ {
+ case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << llendl; break;
+ case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << llendl; break;
+ case MEDIANAVSTATE_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED" << llendl; break;
+ case MEDIANAVSTATE_SERVER_SENT: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_SENT" << llendl; break;
+ case MEDIANAVSTATE_SERVER_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_BEGUN" << llendl; break;
+ case MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED" << llendl; break;
+ }
+}
+
+
+void LLViewerMediaImpl::addObject(LLVOVolume* obj)
+{
+ std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+ for(; iter != mObjectList.end() ; ++iter)
+ {
+ if(*iter == obj)
+ {
+ return ; //already in the list.
+ }
+ }
+
+ mObjectList.push_back(obj) ;
+}
+
+void LLViewerMediaImpl::removeObject(LLVOVolume* obj)
+{
+ mObjectList.remove(obj) ;
+}
+
+const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const
+{
+ return &mObjectList ;
+}
//////////////////////////////////////////////////////////////////////////////////////////
//static
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 9a61394383..775f72d56f 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -41,9 +41,13 @@
#include "llviewermediaobserver.h"
+#include "llpluginclassmedia.h"
+
class LLViewerMediaImpl;
class LLUUID;
class LLViewerMediaTexture;
+class LLMediaEntry;
+class LLVOVolume ;
typedef LLPointer viewer_media_t;
///////////////////////////////////////////////////////////////////////////////
@@ -55,7 +59,7 @@ public:
bool addObserver( LLViewerMediaObserver* subject );
bool remObserver( LLViewerMediaObserver* subject );
- void emitEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event);
+ virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event);
private:
typedef std::list< LLViewerMediaObserver* > observerListType;
@@ -69,15 +73,13 @@ class LLViewerMedia
// Special case early init for just web browser component
// so we can show login screen. See .cpp file for details. JC
- static viewer_media_t newMediaImpl(const std::string& media_url,
- const LLUUID& texture_id,
- S32 media_width,
- S32 media_height,
- U8 media_auto_scale,
- U8 media_loop,
- std::string mime_type = "none/none");
+ static viewer_media_t newMediaImpl(const LLUUID& texture_id,
+ S32 media_width = 0,
+ S32 media_height = 0,
+ U8 media_auto_scale = false,
+ U8 media_loop = false);
- static void removeMedia(LLViewerMediaImpl* media);
+ static viewer_media_t updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self);
static LLViewerMediaImpl* getMediaImplFromTextureID(const LLUUID& texture_id);
static std::string getCurrentUserAgent();
static void updateBrowserUserAgent();
@@ -102,15 +104,18 @@ class LLViewerMediaImpl
LOG_CLASS(LLViewerMediaImpl);
public:
- LLViewerMediaImpl(const std::string& media_url,
+ LLViewerMediaImpl(
const LLUUID& texture_id,
S32 media_width,
S32 media_height,
U8 media_auto_scale,
- U8 media_loop,
- const std::string& mime_type);
+ U8 media_loop);
~LLViewerMediaImpl();
+
+ // Override inherited version from LLViewerMediaEventEmitter
+ virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event);
+
void createMediaSource();
void destroyMediaSource();
void setMediaType(const std::string& media_type);
@@ -126,36 +131,44 @@ public:
void seek(F32 time);
void setVolume(F32 volume);
void focus(bool focus);
+ // True if the impl has user focus.
+ bool hasFocus() const;
void mouseDown(S32 x, S32 y);
void mouseUp(S32 x, S32 y);
void mouseMove(S32 x, S32 y);
+ void mouseDown(const LLVector2& texture_coords);
+ void mouseUp(const LLVector2& texture_coords);
+ void mouseMove(const LLVector2& texture_coords);
void mouseLeftDoubleClick(S32 x,S32 y );
void mouseCapture();
void navigateHome();
- void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false);
+ void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);
void navigateStop();
bool handleKeyHere(KEY key, MASK mask);
bool handleUnicodeCharHere(llwchar uni_char);
bool canNavigateForward();
bool canNavigateBack();
std::string getMediaURL() { return mMediaURL; }
- std::string getMediaHomeURL() { return mHomeURL; }
+ std::string getHomeURL() { return mHomeURL; }
+ void setHomeURL(const std::string& home_url) { mHomeURL = home_url; };
std::string getMimeType() { return mMimeType; }
void scaleMouse(S32 *mouse_x, S32 *mouse_y);
void update();
- void updateMovieImage(const LLUUID& image_id, BOOL active);
void updateImagesMediaStreams();
LLUUID getMediaTextureID();
void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; };
void setVisible(bool visible);
+ bool getVisible() const { return mVisible; };
bool isMediaPlaying();
bool isMediaPaused();
bool hasMedia();
+ ECursorType getLastSetCursor() { return mLastSetCursor; };
+
// utility function to create a ready-to-use media instance from a desired media type.
static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height);
@@ -191,7 +204,7 @@ public:
/*virtual*/ BOOL hasMouseCapture() { return gFocusMgr.getMouseCapture() == this; };
// Inherited from LLPluginClassMediaOwner
- /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent);
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent);
// LLEditMenuHandler overrides
/*virtual*/ void cut();
@@ -203,6 +216,45 @@ public:
/*virtual*/ void paste();
/*virtual*/ BOOL canPaste() const;
+ void addObject(LLVOVolume* obj) ;
+ void removeObject(LLVOVolume* obj) ;
+ const std::list< LLVOVolume* >* getObjectList() const ;
+ void setUpdated(BOOL updated) ;
+ BOOL isUpdated() ;
+
+ // Updates the "interest" value in this object
+ void calculateInterest();
+ F64 getInterest() const { return mInterest; };
+ F64 getApproximateTextureInterest();
+
+ // Mark this object as being used in a UI panel instead of on a prim
+ // This will be used as part of the interest sorting algorithm.
+ void setUsedInUI(bool used_in_ui);
+ bool getUsedInUI() const { return mUsedInUI; };
+
+ F64 getCPUUsage() const;
+
+ void setPriority(LLPluginClassMedia::EPriority priority);
+ LLPluginClassMedia::EPriority getPriority() { return mPriority; };
+
+ void setLowPrioritySizeLimit(int size);
+
+ typedef enum
+ {
+ MEDIANAVSTATE_NONE, // State is outside what we need to track for navigation.
+ MEDIANAVSTATE_BEGUN, // a MEDIA_EVENT_NAVIGATE_BEGIN has been received which was not server-directed
+ MEDIANAVSTATE_FIRST_LOCATION_CHANGED, // first LOCATION_CHANGED event after a non-server-directed BEGIN
+ MEDIANAVSTATE_SERVER_SENT, // server-directed nav has been requested, but MEDIA_EVENT_NAVIGATE_BEGIN hasn't been received yet
+ MEDIANAVSTATE_SERVER_BEGUN, // MEDIA_EVENT_NAVIGATE_BEGIN has been received which was server-directed
+ MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED // first LOCATION_CHANGED event after a server-directed BEGIN
+
+ }EMediaNavState;
+
+ // Returns the current nav state of the media.
+ // note that this will be updated BEFORE listeners and objects receive media messages
+ EMediaNavState getNavState() { return mMediaNavState; }
+ void setNavState(EMediaNavState state);
+
public:
// a single media url with some data and an impl.
LLPluginClassMedia* mMediaSource;
@@ -220,8 +272,20 @@ public:
bool mNeedsNewTexture;
bool mSuspendUpdates;
bool mVisible;
+ ECursorType mLastSetCursor;
+ EMediaNavState mMediaNavState;
+ F64 mInterest;
+ bool mUsedInUI;
+ bool mHasFocus;
+ LLPluginClassMedia::EPriority mPriority;
+ bool mDoNavigateOnLoad;
+ bool mDoNavigateOnLoadServerRequest;
+private:
+ BOOL mIsUpdated ;
+ std::list< LLVOVolume* > mObjectList ;
+
private:
LLViewerMediaTexture *updatePlaceholderImage();
};
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index e7576d5c76..f9377ab37b 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -47,6 +47,7 @@
#include "llparcel.h"
#include "llviewerparcelmgr.h"
#include "llweb.h"
+#include "llmediaentry.h"
//
// LLViewerMediaFocus
//
@@ -91,14 +92,38 @@ void LLViewerMediaFocus::cleanupClass()
void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer objectp, S32 face, viewer_media_t media_impl )
{
LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ if(mMediaImpl.notNull())
+ {
+ mMediaImpl->focus(false);
+ }
+
if (b && media_impl.notNull())
{
+ bool face_auto_zoom = false;
mMediaImpl = media_impl;
+ mMediaImpl->focus(true);
+
LLSelectMgr::getInstance()->deselectAll();
LLSelectMgr::getInstance()->selectObjectOnly(objectp, face);
+ if(objectp.notNull())
+ {
+ LLTextureEntry* tep = objectp->getTE(face);
+ if(! tep->hasMedia())
+ {
+ // Error condition
+ }
+ LLMediaEntry* mep = tep->getMediaData();
+ face_auto_zoom = mep->getAutoZoom();
+ if(! mep->getAutoPlay())
+ {
+ std::string url = mep->getCurrentURL().empty() ? mep->getHomeURL() : mep->getCurrentURL();
+ media_impl->navigateTo(url, "", true);
+ }
+ }
mFocus = LLSelectMgr::getInstance()->getSelection();
- if(mMediaHUD.get() && ! parcel->getMediaPreventCameraZoom())
+ if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
{
mMediaHUD.get()->resetZoomLevel();
mMediaHUD.get()->nextZoomLevel();
@@ -108,6 +133,7 @@ void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer objectp
gFocusMgr.setKeyboardFocus(this);
}
mObjectID = objectp->getID();
+ mObjectFace = face;
// LLViewerMedia::addObserver(this, mObjectID);
@@ -133,6 +159,8 @@ void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer objectp
// and null out the media impl
mMediaImpl = NULL;
+ mObjectID = LLUUID::null;
+ mObjectFace = 0;
}
if(mMediaHUD.get())
{
@@ -230,6 +258,12 @@ void LLViewerMediaFocus::setMouseOverFlag(bool b, viewer_media_t media_impl)
gHUDView->addChild(media_hud);
}
mMediaHUD.get()->setMediaImpl(media_impl);
+
+ if(mMediaImpl.notNull() && (mMediaImpl != media_impl))
+ {
+ mMediaImpl->focus(false);
+ }
+
mMediaImpl = media_impl;
}
mMouseOverFlag = b;
@@ -356,3 +390,8 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3&
// Return the aspect ratio.
return *width / *height;
}
+
+bool LLViewerMediaFocus::isFocusedOnFace(LLPointer objectp, S32 face)
+{
+ return objectp->getID() == mObjectID && face == mObjectFace;
+}
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index a078d24b6a..2688a8b708 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -72,6 +72,9 @@ public:
void setPickInfo(LLPickInfo pick_info) { mPickInfo = pick_info; }
F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth);
+ // TODO: figure out why selection mgr hates me
+ bool isFocusedOnFace(LLPointer objectp, S32 face);
+
protected:
/*virtual*/ void onFocusReceived();
/*virtual*/ void onFocusLost();
@@ -83,6 +86,7 @@ private:
LLPickInfo mPickInfo;
LLHandle mMediaHUD;
LLUUID mObjectID;
+ S32 mObjectFace;
viewer_media_t mMediaImpl;
};
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index d3d5f060e1..05011a1568 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -47,6 +47,7 @@
#include "llframetimer.h"
#include "llinventory.h"
#include "llmaterialtable.h"
+#include "llmediadataresponder.h"
#include "llmutelist.h"
#include "llnamevalue.h"
#include "llprimitive.h"
@@ -100,6 +101,8 @@
#include "llvowlsky.h"
#include "llmanip.h"
#include "lltrans.h"
+#include "llsdutil.h"
+#include "llmediaentry.h"
//#define DEBUG_UPDATE_TYPE
@@ -470,6 +473,7 @@ void LLViewerObject::cleanupVOClasses()
LLVOWater::cleanupClass();
LLVOTree::cleanupClass();
LLVOAvatar::cleanupClass();
+ LLVOVolume::cleanupClass();
}
// Replaces all name value pairs with data from \n delimited list
@@ -700,6 +704,42 @@ void LLViewerObject::hideExtraDisplayItems( BOOL hidden )
}
}
+U32 LLViewerObject::checkMediaURL(const std::string &media_url)
+{
+ U32 retval = (U32)0x0;
+ if (!mMedia && !media_url.empty())
+ {
+ retval |= MEDIA_URL_ADDED;
+ mMedia = new LLViewerObjectMedia;
+ mMedia->mMediaURL = media_url;
+ mMedia->mMediaType = LLViewerObject::MEDIA_SET;
+ mMedia->mPassedWhitelist = FALSE;
+ }
+ else if (mMedia)
+ {
+ if (media_url.empty())
+ {
+ retval |= MEDIA_URL_REMOVED;
+ delete mMedia;
+ mMedia = NULL;
+ }
+ else if (mMedia->mMediaURL != media_url) // <-- This is an optimization. If they are equal don't bother with below's test.
+ {
+ /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() &&
+ LLTextureEntry::getVersionFromMediaVersionString(media_url) ==
+ LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1))
+ */
+ {
+ // If the media URL is different and WE were not the one who
+ // changed it, mark dirty.
+ retval |= MEDIA_URL_UPDATED;
+ }
+ mMedia->mMediaURL = media_url;
+ mMedia->mPassedWhitelist = FALSE;
+ }
+ }
+ return retval;
+}
U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
@@ -1045,35 +1085,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
std::string media_url;
mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num);
- //if (!media_url.empty())
- //{
- // llinfos << "WEBONPRIM media_url " << media_url << llendl;
- //}
- if (!mMedia && !media_url.empty())
- {
- retval |= MEDIA_URL_ADDED;
- mMedia = new LLViewerObjectMedia;
- mMedia->mMediaURL = media_url;
- mMedia->mMediaType = LLViewerObject::MEDIA_TYPE_WEB_PAGE;
- mMedia->mPassedWhitelist = FALSE;
- }
- else if (mMedia)
- {
- if (media_url.empty())
- {
- retval |= MEDIA_URL_REMOVED;
- delete mMedia;
- mMedia = NULL;
- }
- else if (mMedia->mMediaURL != media_url)
- {
- // We just added or changed a web page.
- retval |= MEDIA_URL_UPDATED;
- mMedia->mMediaURL = media_url;
- mMedia->mPassedWhitelist = FALSE;
- }
- }
-
+ retval |= checkMediaURL(media_url);
+
//
// Unpack particle system data
//
@@ -1456,31 +1469,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
mText = NULL;
}
+ std::string media_url;
if (value & 0x200)
{
- std::string media_url;
dp->unpackString(media_url, "MediaURL");
- if (!mMedia)
- {
- retval |= MEDIA_URL_ADDED;
- mMedia = new LLViewerObjectMedia;
- mMedia->mMediaURL = media_url;
- mMedia->mMediaType = LLViewerObject::MEDIA_TYPE_WEB_PAGE;
- mMedia->mPassedWhitelist = FALSE;
- }
- else if (mMedia->mMediaURL != media_url)
- {
- retval |= MEDIA_URL_UPDATED;
- mMedia->mMediaURL = media_url;
- mMedia->mPassedWhitelist = FALSE;
- }
- }
- else if (mMedia)
- {
- retval |= MEDIA_URL_REMOVED;
- delete mMedia;
- mMedia = NULL;
}
+ retval |= checkMediaURL(media_url);
//
// Unpack particle system data
@@ -3472,7 +3466,7 @@ U8 LLViewerObject::getMediaType() const
}
else
{
- return LLViewerObject::MEDIA_TYPE_NONE;
+ return LLViewerObject::MEDIA_NONE;
}
}
@@ -3734,16 +3728,13 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos
}
-void LLViewerObject::changeTEImage(const LLViewerTexture* old_image, LLViewerTexture* new_image)
+void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image)
{
- U32 end = getNumTEs() ;
- for (U32 face = 0 ; face < end ; face++)
+ if(index < 0 || index >= getNumTEs())
{
- if(old_image == mTEImages[face])
- {
- mTEImages[face] = new_image ;
- }
+ return ;
}
+ mTEImages[index] = new_image ;
}
S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 08e2ec47cd..bec36f9da7 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -158,10 +158,16 @@ public:
virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
// Types of media we can associate
- enum { MEDIA_TYPE_NONE = 0, MEDIA_TYPE_WEB_PAGE = 1 };
+ enum { MEDIA_NONE = 0, MEDIA_SET = 1 };
// Return codes for processUpdateMessage
- enum { MEDIA_URL_REMOVED = 0x1, MEDIA_URL_ADDED = 0x2, MEDIA_URL_UPDATED = 0x4, INVALID_UPDATE = 0x80000000 };
+ enum {
+ MEDIA_URL_REMOVED = 0x1,
+ MEDIA_URL_ADDED = 0x2,
+ MEDIA_URL_UPDATED = 0x4,
+ MEDIA_FLAGS_CHANGED = 0x8,
+ INVALID_UPDATE = 0x80000000
+ };
virtual U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
@@ -318,7 +324,7 @@ public:
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
/*virtual*/ BOOL setMaterial(const U8 material);
virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive
- void changeTEImage(const LLViewerTexture* old_image, LLViewerTexture* new_image) ;
+ void changeTEImage(S32 index, LLViewerTexture* new_image) ;
LLViewerTexture *getTEImage(const U8 te) const;
void fitFaceTexture(const U8 face);
@@ -504,6 +510,10 @@ private:
ExtraParameter* getExtraParameterEntry(U16 param_type) const;
ExtraParameter* getExtraParameterEntryCreate(U16 param_type);
bool unpackParameterEntry(U16 param_type, LLDataPacker *dp);
+
+ // This function checks to see if the given media URL has changed its version
+ // and the update wasn't due to this agent's last action.
+ U32 checkMediaURL(const std::string &media_url);
public:
//
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index 86d51bfd4b..a3f9c839a0 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -46,6 +46,7 @@
#include "llnotifications.h"
#include "llfirstuse.h"
#include "llpluginclassmedia.h"
+#include "llviewertexture.h"
// Static Variables
@@ -219,17 +220,25 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
// Delete the old one first so they don't fight over the texture.
sMediaImpl->stop();
- sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id,
- media_width, media_height, media_auto_scale,
+ sMediaImpl = LLViewerMedia::newMediaImpl(
+ placeholder_texture_id,
+ media_width,
+ media_height,
+ media_auto_scale,
media_loop);
+ sMediaImpl->navigateTo(media_url);
}
}
else
{
// There is no media impl, make a new one
- sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id,
- media_width, media_height, media_auto_scale,
+ sMediaImpl = LLViewerMedia::newMediaImpl(
+ placeholder_texture_id,
+ media_width,
+ media_height,
+ media_auto_scale,
media_loop);
+ sMediaImpl->navigateTo(media_url);
}
LLFirstUse::useMedia();
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 2c68a106c3..7ea55b49e8 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1428,6 +1428,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("EventQueueGet");
capabilityNames.append("FetchInventory");
capabilityNames.append("WebFetchInventoryDescendents");
+ capabilityNames.append("ObjectMedia");
+ capabilityNames.append("ObjectMediaNavigate");
capabilityNames.append("FetchLib");
capabilityNames.append("FetchLibDescendents");
capabilityNames.append("GroupProposalBallot");
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index e3d657068f..a2f6b70006 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -62,6 +62,10 @@
#include "llappviewer.h"
#include "lltextureatlas.h"
#include "lltextureatlasmanager.h"
+#include "lltextureentry.h"
+#include "llmediaentry.h"
+#include "llvovolume.h"
+#include "llviewermedia.h"
///////////////////////////////////////////////////////////////////////////////
// statics
@@ -114,45 +118,18 @@ LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id)
LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id)
{
- LLViewerMediaTexture::media_map_t::iterator iter = LLViewerMediaTexture::sMediaMap.find(media_id);
- if(iter == LLViewerMediaTexture::sMediaMap.end())
- return NULL;
-
- ((LLViewerMediaTexture*)(iter->second))->getLastReferencedTimer()->reset() ;
- return iter->second;
+ return LLViewerMediaTexture::findMediaTexture(media_id) ;
}
LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image)
{
- LLViewerMediaTexture* tex = LLViewerTextureManager::findMediaTexture(id) ;
+ LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id) ;
if(!tex)
{
tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image) ;
}
- LLViewerTexture* old_tex = tex->getOldTexture() ;
- if(!old_tex)
- {
- //if there is a fetched texture with the same id, replace it by this media texture
- old_tex = gTextureList.findImage(id) ;
- if(old_tex)
- {
- tex->setOldTexture(old_tex) ;
- }
- }
-
- if (gSavedSettings.getBOOL("ParcelMediaAutoPlayEnable") && gSavedSettings.getBOOL("AudioStreamingVideo"))
- {
- if(!tex->isPlaying())
- {
- if(old_tex)
- {
- old_tex->switchToTexture(tex) ;
- }
- tex->setPlaying(TRUE) ;
- }
- }
- tex->getLastReferencedTimer()->reset() ;
+ tex->initVirtualSize() ;
return tex ;
}
@@ -303,7 +280,7 @@ void LLViewerTextureManager::cleanup()
LLViewerFetchedTexture::sMissingAssetImagep = NULL;
LLViewerFetchedTexture::sWhiteImagep = NULL;
- LLViewerMediaTexture::sMediaMap.clear() ;
+ LLViewerMediaTexture::cleanup() ;
}
//----------------------------------------------------------------------------------------------
@@ -437,6 +414,7 @@ void LLViewerTexture::init(bool firstinit)
mTextureState = NO_DELETE ;
mDontDiscard = FALSE;
mMaxVirtualSize = 0.f;
+ mNeedsResetMaxVirtualSize = FALSE ;
}
//virtual
@@ -538,33 +516,24 @@ void LLViewerTexture::resetTextureStats(BOOL zero)
}
}
+//virtual
+F32 LLViewerTexture::getMaxVirtualSize()
+{
+ return mMaxVirtualSize ;
+}
+
+//virtual
void LLViewerTexture::addFace(LLFace* facep)
{
mFaceList.push_back(facep) ;
}
+
+//virtual
void LLViewerTexture::removeFace(LLFace* facep)
{
mFaceList.remove(facep) ;
}
-void LLViewerTexture::switchToTexture(LLViewerTexture* new_texture)
-{
- if(this == new_texture)
- {
- return ;
- }
-
- new_texture->addTextureStats(getMaxVirtualSize()) ;
-
- for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); )
- {
- LLFace* facep = *iter++ ;
- facep->setTexture(new_texture) ;
- facep->getViewerObject()->changeTEImage(this, new_texture) ;
- gPipeline.markTextured(facep->getDrawable());
- }
-}
-
void LLViewerTexture::forceActive()
{
mTextureState = ACTIVE ;
@@ -613,7 +582,16 @@ BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* image
{
llassert_always(mGLTexturep.notNull()) ;
- return mGLTexturep->createGLTexture(discard_level, imageraw, usename) ;
+ BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename) ;
+
+ if(ret)
+ {
+ mFullWidth = mGLTexturep->getCurrentWidth() ;
+ mFullHeight = mGLTexturep->getCurrentHeight() ;
+ mComponents = mGLTexturep->getComponents() ;
+ }
+
+ return ret ;
}
void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
@@ -2142,18 +2120,59 @@ void LLViewerMediaTexture::updateClass()
for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); )
{
- LLViewerMediaTexture* mediap = iter->second;
- ++iter ;
+ LLViewerMediaTexture* mediap = iter->second;
+ //
+ //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture.
+ //
if(mediap->getNumRefs() == 1 && mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) //one by sMediaMap
{
- sMediaMap.erase(mediap->getID()) ;
+ media_map_t::iterator cur = iter++ ;
+ sMediaMap.erase(cur) ;
+ }
+ else
+ {
+ ++iter ;
}
}
}
+//static
+void LLViewerMediaTexture::removeMediaImplFromTexture(const LLUUID& media_id)
+{
+ LLViewerMediaTexture* media_tex = findMediaTexture(media_id) ;
+ if(media_tex)
+ {
+ media_tex->invalidateMediaImpl() ;
+ }
+}
+
+//static
+void LLViewerMediaTexture::cleanup()
+{
+ sMediaMap.clear() ;
+}
+
+//static
+LLViewerMediaTexture* LLViewerMediaTexture::findMediaTexture(const LLUUID& media_id)
+{
+ media_map_t::iterator iter = sMediaMap.find(media_id);
+ if(iter == sMediaMap.end())
+ {
+ return NULL;
+ }
+
+ LLViewerMediaTexture* media_tex = iter->second ;
+ media_tex->setMediaImpl() ;
+ media_tex->getLastReferencedTimer()->reset() ;
+
+ return media_tex;
+}
+
LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image)
- : LLViewerTexture(id, usemipmaps)
+ : LLViewerTexture(id, usemipmaps),
+ mMediaImplp(NULL),
+ mUpdateVirtualSizeTime(0)
{
sMediaMap.insert(std::make_pair(id, this));
@@ -2165,6 +2184,13 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL
mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ;
mIsPlaying = FALSE ;
+
+ setMediaImpl() ;
+}
+
+//virtual
+LLViewerMediaTexture::~LLViewerMediaTexture()
+{
}
void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */)
@@ -2172,7 +2198,6 @@ void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */)
mGLTexturep = NULL ;
init(false);
mUseMipMaps = usemipmaps ;
- mIsPlaying = FALSE ;
getLastReferencedTimer()->reset() ;
generateGLTexture() ;
@@ -2195,14 +2220,336 @@ S8 LLViewerMediaTexture::getType() const
return LLViewerTexture::MEDIA_TEXTURE ;
}
-void LLViewerMediaTexture::setOldTexture(LLViewerTexture* tex)
+void LLViewerMediaTexture::invalidateMediaImpl()
{
- mOldTexturep = tex ;
+ mMediaImplp = NULL ;
+}
+
+void LLViewerMediaTexture::setMediaImpl()
+{
+ if(!mMediaImplp)
+ {
+ mMediaImplp = LLViewerMedia::getMediaImplFromTextureID(mID) ;
+ }
+}
+
+//return true if all faces to reference to this media texture are found
+//Note: mMediaFaceList is valid only for the current instant
+// because it does not check the face validity after the current frame.
+BOOL LLViewerMediaTexture::findFaces()
+{
+ mMediaFaceList.clear() ;
+
+ BOOL ret = TRUE ;
+
+ //for parcel media
+ LLViewerTexture* tex = gTextureList.findImage(mID) ;
+ if(tex)
+ {
+ const ll_face_list_t* face_list = tex->getFaceList() ;
+ for(ll_face_list_t::const_iterator iter = face_list->begin(); iter != face_list->end(); ++iter)
+ {
+ mMediaFaceList.push_back(*iter) ;
+ }
+ }
+
+ if(!mMediaImplp)
+ {
+ return TRUE ;
+ }
+
+ //for media on a face.
+ const std::list< LLVOVolume* >* obj_list = mMediaImplp->getObjectList() ;
+ std::list< LLVOVolume* >::const_iterator iter = obj_list->begin() ;
+ for(; iter != obj_list->end(); ++iter)
+ {
+ LLVOVolume* obj = *iter ;
+ if(obj->mDrawable.isNull())
+ {
+ ret = FALSE ;
+ continue ;
+ }
+
+ S32 face_id = -1 ;
+ while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1)
+ {
+ LLFace* facep = obj->mDrawable->getFace(face_id) ;
+ if(facep)
+ {
+ mMediaFaceList.push_back(facep) ;
+ }
+ else
+ {
+ ret = FALSE ;
+ }
+ }
+ }
+
+ return ret ;
+}
+
+void LLViewerMediaTexture::initVirtualSize()
+{
+ if(mIsPlaying)
+ {
+ return ;
+ }
+
+ findFaces() ;
+ for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
+ {
+ addTextureStats((*iter)->getVirtualSize()) ;
+ }
+}
+
+void LLViewerMediaTexture::addMediaToFace(LLFace* facep)
+{
+ if(!mIsPlaying)
+ {
+ return ; //no need to add the face because the media is not in playing.
+ }
+
+ switchTexture(facep) ;
}
-LLViewerTexture* LLViewerMediaTexture::getOldTexture() const
+void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep)
{
- return mOldTexturep ;
+ if(!mIsPlaying)
+ {
+ return ; //no need to remove the face because the media is not in playing.
+ }
+ if(!facep)
+ {
+ return ;
+ }
+
+ mIsPlaying = FALSE ; //set to remove the media from the face.
+ switchTexture(facep) ;
+ mIsPlaying = TRUE ; //set the flag back.
+
+ if(mFaceList.empty()) //no face referencing to this media
+ {
+ stopPlaying() ;
+ }
+}
+
+//virtual
+void LLViewerMediaTexture::addFace(LLFace* facep)
+{
+ LLViewerTexture::addFace(facep) ;
+
+ const LLTextureEntry* te = facep->getTextureEntry() ;
+ if(te)
+ {
+ LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
+ if(tex)
+ {
+ mTextureList.push_back(tex) ;//increase the reference number by one for tex to avoid deleting it.
+ return ;
+ }
+ }
+ llerrs << "The face does not have a valid texture before media texture." << llendl ;
+}
+
+//virtual
+void LLViewerMediaTexture::removeFace(LLFace* facep)
+{
+ LLViewerTexture::removeFace(facep) ;
+
+ const LLTextureEntry* te = facep->getTextureEntry() ;
+ if(te)
+ {
+ LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
+ if(tex)
+ {
+ for(std::list< LLPointer >::iterator iter = mTextureList.begin();
+ iter != mTextureList.end(); ++iter)
+ {
+ if(*iter == tex)
+ {
+ mTextureList.erase(iter) ; //decrease the reference number for tex by one.
+ return ;
+ }
+ }
+
+ //
+ //we have some trouble here: the texture of the face is changed.
+ //we need to find the former texture, and remove it from the list to avoid memory leaking.
+ if(mFaceList.empty())
+ {
+ mTextureList.clear() ;
+ return ;
+ }
+ S32 end = mFaceList.size() ;
+ std::vector te_list(end) ;
+ S32 i = 0 ;
+ for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter)
+ {
+ te_list[i++] = (*iter)->getTextureEntry() ;//all textures are in use.
+ }
+ for(std::list< LLPointer >::iterator iter = mTextureList.begin();
+ iter != mTextureList.end(); ++iter)
+ {
+ for(i = 0 ; i < end ; i++)
+ {
+ if(te_list[i] && te_list[i]->getID() == (*iter)->getID())//the texture is in use.
+ {
+ te_list[i] = NULL ;
+ break ;
+ }
+ }
+ if(i == end) //no hit for this texture, remove it.
+ {
+ mTextureList.erase(iter) ; //decrease the reference number for tex by one.
+ return ;
+ }
+ }
+ }
+ }
+ llerrs << "mTextureList texture reference number is corrupted." << llendl ;
+}
+
+void LLViewerMediaTexture::stopPlaying()
+{
+ if(mMediaImplp)
+ {
+ mMediaImplp->stop() ;
+ }
+ mIsPlaying = FALSE ;
+}
+
+void LLViewerMediaTexture::switchTexture(LLFace* facep)
+{
+ if(facep)
+ {
+ //check if another media is playing on this face.
+ if(facep->getTexture() && facep->getTexture() != this
+ && facep->getTexture()->getType() == LLViewerTexture::MEDIA_TEXTURE)
+ {
+ if(mID == facep->getTexture()->getID()) //this is a parcel media
+ {
+ return ; //let the prim media win.
+ }
+ }
+
+ if(mIsPlaying) //old textures switch to the media texture
+ {
+ facep->switchTexture(this) ;
+ }
+ else //switch to old textures.
+ {
+ const LLTextureEntry* te = facep->getTextureEntry() ;
+ if(te)
+ {
+ LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
+ facep->switchTexture(tex) ;
+ }
+ }
+ }
+}
+
+void LLViewerMediaTexture::setPlaying(BOOL playing)
+{
+ if(!mMediaImplp)
+ {
+ return ;
+ }
+ if(!playing && !mIsPlaying)
+ {
+ return ; //media is already off
+ }
+
+ if(playing == mIsPlaying && !mMediaImplp->isUpdated())
+ {
+ return ; //nothing has changed since last time.
+ }
+
+ mIsPlaying = playing ;
+ if(mIsPlaying) //is about to play this media
+ {
+ if(findFaces())
+ {
+ //about to update all faces.
+ mMediaImplp->setUpdated(FALSE) ;
+ }
+
+ if(mMediaFaceList.empty())//no face pointing to this media
+ {
+ stopPlaying() ;
+ return ;
+ }
+
+ for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
+ {
+ switchTexture(*iter) ;
+ }
+ }
+ else //stop playing this media
+ {
+ if(mFaceList.empty())
+ {
+ return ;
+ }
+
+ ll_face_list_t::iterator cur ;
+ for(ll_face_list_t::iterator iter = mFaceList.begin(); iter!= mFaceList.end(); )
+ {
+ cur = iter++ ;
+ switchTexture(*cur) ; //cur could be removed in this function.
+ }
+ }
+ return ;
+}
+
+//virtual
+F32 LLViewerMediaTexture::getMaxVirtualSize()
+{
+ if(LLFrameTimer::getFrameCount() == mUpdateVirtualSizeTime)
+ {
+ return mMaxVirtualSize ;
+ }
+ mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount() ;
+
+ if(mNeedsResetMaxVirtualSize)
+ {
+ mMaxVirtualSize = 0.f ;//reset
+ mNeedsResetMaxVirtualSize = FALSE ;
+ }
+
+ if(mIsPlaying) //media is playing
+ {
+ if(mFaceList.size() > 0)
+ {
+ for(std::list::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter)
+ {
+ LLFace* facep = *iter ;
+ if(facep->getDrawable()->isRecentlyVisible())
+ {
+ addTextureStats(facep->getVirtualSize()) ;
+ }
+ }
+ }
+ }
+ else //media is not in playing
+ {
+ findFaces() ;
+
+ if(!mMediaFaceList.empty())
+ {
+ for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
+ {
+ LLFace* facep = *iter ;
+ if(facep->getDrawable()->isRecentlyVisible())
+ {
+ addTextureStats(facep->getVirtualSize()) ;
+ }
+ }
+ }
+ }
+
+ mNeedsResetMaxVirtualSize = TRUE ;
+
+ return mMaxVirtualSize ;
}
//----------------------------------------------------------------------------------------------
//end of LLViewerMediaTexture
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 0be1bf81de..596bfea670 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -49,6 +49,7 @@
class LLFace;
class LLImageGL ;
+class LLViewerObject;
class LLViewerTexture;
class LLViewerFetchedTexture ;
class LLViewerMediaTexture ;
@@ -58,7 +59,9 @@ typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_
class LLVFile;
class LLMessageSystem;
-
+class LLViewerMediaImpl ;
+class LLVOVolume ;
+
class LLLoadedCallbackEntry
{
public:
@@ -123,6 +126,8 @@ public:
BOOST_MAX_LEVEL
};
+ typedef std::list ll_face_list_t ;
+
protected:
virtual ~LLViewerTexture();
LOG_CLASS(LLViewerTexture);
@@ -152,16 +157,17 @@ public:
//maxVirtualSize of the texture
void addTextureStats(F32 virtual_size) const ;
void resetTextureStats(BOOL zero = FALSE);
- F32 getMaxVirtualSize()const {return mMaxVirtualSize ;}
+ virtual F32 getMaxVirtualSize() ;
LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
S32 getFullWidth() const { return mFullWidth; }
S32 getFullHeight() const { return mFullHeight; }
- void addFace(LLFace* facep) ;
- void removeFace(LLFace* facep) ;
-
+ virtual void addFace(LLFace* facep) ;
+ virtual void removeFace(LLFace* facep) ;
+ const ll_face_list_t* getFaceList() const {return &mFaceList ;}
+
void generateGLTexture() ;
void destroyGLTexture() ;
@@ -206,8 +212,6 @@ public:
//end of functions to access LLImageGL
//---------------------------------------------------------------------------------------------
- void switchToTexture(LLViewerTexture* new_texture) ; //make all faces pointing to this texture to point to new_texture.
-
//-----------------
/*virtual*/ void setActive() ;
void forceActive() ;
@@ -233,10 +237,9 @@ protected:
BOOL mUseMipMaps ;
S8 mComponents;
mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
-
+ mutable BOOL mNeedsResetMaxVirtualSize ;
LLFrameTimer mLastReferencedTimer;
- typedef std::list ll_face_list_t ;
ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture
//GL texture
@@ -498,34 +501,61 @@ private:
class LLViewerMediaTexture : public LLViewerTexture
{
protected:
- /*virtual*/ ~LLViewerMediaTexture() {}
+ /*virtual*/ ~LLViewerMediaTexture() ;
public:
LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
/*virtual*/ S8 getType() const;
-
void reinit(BOOL usemipmaps = TRUE);
BOOL getUseMipMaps() {return mUseMipMaps ; }
- void setUseMipMaps(BOOL mipmap) ;
-
- void setOldTexture(LLViewerTexture* tex) ;
- LLViewerTexture* getOldTexture() const ;
-
- void setPlaying(BOOL playing) {mIsPlaying = playing ;}
+ void setUseMipMaps(BOOL mipmap) ;
+
+ void setPlaying(BOOL playing) ;
BOOL isPlaying() const {return mIsPlaying;}
+ void setMediaImpl() ;
+
+ void initVirtualSize() ;
+ void invalidateMediaImpl() ;
+
+ void addMediaToFace(LLFace* facep) ;
+ void removeMediaFromFace(LLFace* facep) ;
+
+ /*virtual*/ void addFace(LLFace* facep) ;
+ /*virtual*/ void removeFace(LLFace* facep) ;
+
+ /*virtual*/ F32 getMaxVirtualSize() ;
+private:
+ void switchTexture(LLFace* facep) ;
+ BOOL findFaces() ;
+ void stopPlaying() ;
private:
- LLPointer mOldTexturep ; //the texture this media texture replaces.
+ //
+ //an instant list, recording all faces referencing or can reference to this media texture.
+ //NOTE: it is NOT thread safe.
+ //
+ std::list< LLFace* > mMediaFaceList ;
+
+ //an instant list keeping all textures which are replaced by the current media texture,
+ //is only used to avoid the removal of those textures from memory.
+ std::list< LLPointer > mTextureList ;
+
+ LLViewerMediaImpl* mMediaImplp ;
BOOL mIsPlaying ;
+ U32 mUpdateVirtualSizeTime ;
public:
static void updateClass() ;
+ static void cleanup() ;
-public:
+ static LLViewerMediaTexture* findMediaTexture(const LLUUID& media_id) ;
+ static void removeMediaImplFromTexture(const LLUUID& media_id) ;
+
+private:
typedef std::map< LLUUID, LLPointer > media_map_t ;
- static media_map_t sMediaMap ;
+ static media_map_t sMediaMap ;
};
//just an interface class, do not create instance from this class.
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 93cb0f0f45..e69779b2dc 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -46,6 +46,8 @@
#include "llvolumemessage.h"
#include "material_codes.h"
#include "message.h"
+#include "llmediadataresponder.h"
+#include "llpluginclassmedia.h" // for code in the mediaEvent handler
#include "object_flags.h"
#include "llagentconstants.h"
#include "lldrawable.h"
@@ -65,6 +67,10 @@
#include "llworld.h"
#include "llselectmgr.h"
#include "pipeline.h"
+#include "llsdutil.h"
+#include "llmediaentry.h"
+#include "llmediadatafetcher.h"
+#include "llagent.h"
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
@@ -100,6 +106,8 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mLODChanged = FALSE;
mSculptChanged = FALSE;
mSpotLightPriority = 0.f;
+
+ mMediaImplList.resize(getNumTEs());
}
LLVOVolume::~LLVOVolume()
@@ -108,14 +116,31 @@ LLVOVolume::~LLVOVolume()
mTextureAnimp = NULL;
delete mVolumeImpl;
mVolumeImpl = NULL;
+
+ if(!mMediaImplList.empty())
+ {
+ for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
+ {
+ if(mMediaImplList[i].notNull())
+ {
+ mMediaImplList[i]->removeObject(this) ;
+ }
+ }
+ }
}
// static
void LLVOVolume::initClass()
{
+ LLMediaDataFetcher::initClass();
}
+// static
+void LLVOVolume::cleanupClass()
+{
+ LLMediaDataFetcher::cleanupClass();
+}
U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
@@ -123,6 +148,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
LLDataPacker *dp)
{
LLColor4U color;
+ const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA);
// Do base class updates...
U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
@@ -190,10 +216,15 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
//
// Unpack texture entry data
//
- if (unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
+ S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
+ if (result & teDirtyBits)
{
updateTEData();
}
+ if (result & TEM_CHANGE_MEDIA)
+ {
+ retval |= MEDIA_FLAGS_CHANGED;
+ }
}
else
{
@@ -226,9 +257,16 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
// llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl;
llwarns << "Bogus TE data in " << getID() << llendl;
}
- else if (res2 & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
+ else
{
- updateTEData();
+ if (res2 & teDirtyBits)
+ {
+ updateTEData();
+ }
+ if (res2 & TEM_CHANGE_MEDIA)
+ {
+ retval |= MEDIA_FLAGS_CHANGED;
+ }
}
U32 value = dp->getPassFlags();
@@ -266,14 +304,29 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
U8 tdpbuffer[1024];
LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num);
- if ( unpackTEMessage(tdp) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
+ S32 result = unpackTEMessage(tdp);
+ if (result & teDirtyBits)
{
updateTEData();
}
+ if (result & TEM_CHANGE_MEDIA)
+ {
+ retval |= MEDIA_FLAGS_CHANGED;
+ }
}
}
}
-
+ if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) {
+ // If the media changed at all, request new media data
+ if(mMedia)
+ {
+ llinfos << "Media URL: " << mMedia->mMediaURL << llendl;
+ }
+ requestMediaDataUpdate();
+ }
+ // ...and clean up any media impls
+ cleanUpMediaImpls();
+
return retval;
}
@@ -1327,6 +1380,46 @@ BOOL LLVOVolume::isRootEdit() const
return TRUE;
}
+//virtual
+void LLVOVolume::setNumTEs(const U8 num_tes)
+{
+ const U8 old_num_tes = getNumTEs() ;
+
+ if(old_num_tes && old_num_tes < num_tes) //new faces added
+ {
+ LLViewerObject::setNumTEs(num_tes) ;
+
+ if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists.
+ {
+ mMediaImplList.resize(num_tes) ;
+ const LLTextureEntry* te = getTE(old_num_tes - 1) ;
+ for(U8 i = old_num_tes; i < num_tes ; i++)
+ {
+ setTE(i, *te) ;
+ mMediaImplList[i] = mMediaImplList[old_num_tes -1] ;
+ }
+ mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ;
+ }
+ }
+ else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed
+ {
+ U8 end = mMediaImplList.size() ;
+ for(U8 i = num_tes; i < end ; i++)
+ {
+ removeMediaImpl(i) ;
+ }
+ mMediaImplList.resize(num_tes) ;
+
+ LLViewerObject::setNumTEs(num_tes) ;
+ }
+ else
+ {
+ LLViewerObject::setNumTEs(num_tes) ;
+ }
+
+ return ;
+}
+
void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep)
{
BOOL changed = (mTEImages[te] != imagep);
@@ -1510,6 +1603,321 @@ void LLVOVolume::updateTEData()
}*/
}
+bool LLVOVolume::hasMedia() const
+{
+ bool result = false;
+ const U8 numTEs = getNumTEs();
+ for (U8 i = 0; i < numTEs; i++)
+ {
+ const LLTextureEntry* te = getTE(i);
+ if(te->hasMedia())
+ {
+ result = true;
+ break;
+ }
+ }
+ return result;
+}
+
+void LLVOVolume::requestMediaDataUpdate()
+{
+ LLMediaDataFetcher::fetchMedia(this);
+}
+
+void LLVOVolume::cleanUpMediaImpls()
+{
+ // Iterate through our TEs and remove any Impls that are no longer used
+ const U8 numTEs = getNumTEs();
+ for (U8 i = 0; i < numTEs; i++)
+ {
+ const LLTextureEntry* te = getTE(i);
+ if( ! te->hasMedia())
+ {
+ // Delete the media IMPL!
+ removeMediaImpl(i) ;
+ }
+ }
+}
+
+void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array)
+{
+ // media_data_array is an array of media entry maps
+
+ //llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl;
+
+ LLSD::array_const_iterator iter = media_data_array.beginArray();
+ LLSD::array_const_iterator end = media_data_array.endArray();
+ U8 texture_index = 0;
+ for (; iter != end; ++iter, ++texture_index)
+ {
+ syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/);
+ }
+}
+
+void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent)
+{
+ LLTextureEntry *te = getTE(texture_index);
+ //llinfos << "BEFORE: texture_index = " << texture_index
+ // << " hasMedia = " << te->hasMedia() << " : "
+ // << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl;
+
+ std::string previous_url;
+ LLMediaEntry* mep = te->getMediaData();
+ if(mep)
+ {
+ // Save the "current url" from before the update so we can tell if
+ // it changes.
+ previous_url = mep->getCurrentURL();
+ }
+
+ if (merge)
+ {
+ te->mergeIntoMediaData(media_data);
+ }
+ else {
+ // XXX Question: what if the media data is undefined LLSD, but the
+ // update we got above said that we have media flags?? Here we clobber
+ // that, assuming the data from the service is more up-to-date.
+ te->updateMediaData(media_data);
+ }
+
+ mep = te->getMediaData();
+ if(mep)
+ {
+ bool update_from_self = false;
+ if (!ignore_agent)
+ {
+ LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL());
+ update_from_self = (updating_agent == gAgent.getID());
+ }
+ viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self);
+
+ addMediaImpl(media_impl, texture_index) ;
+ }
+
+ //llinfos << "AFTER: texture_index = " << texture_index
+ // << " hasMedia = " << te->hasMedia() << " : "
+ // << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl;
+}
+
+void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
+{
+ switch(event)
+ {
+
+ case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED:
+ {
+ switch(impl->getNavState())
+ {
+ case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED:
+ {
+ // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast.
+
+ bool block_navigation = false;
+ // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed
+ // to deal with multiple face indices.
+ int face_index = getFaceIndexWithMediaImpl(impl, -1);
+ std::string new_location = plugin->getLocation();
+
+ // Find the media entry for this navigate
+ LLMediaEntry* mep = NULL;
+ LLTextureEntry *te = getTE(face_index);
+ if(te)
+ {
+ mep = te->getMediaData();
+ }
+
+ if(mep)
+ {
+ if(!mep->checkCandidateUrl(new_location))
+ {
+ block_navigation = true;
+ }
+ }
+ else
+ {
+ llwarns << "Couldn't find media entry!" << llendl;
+ }
+
+ if(block_navigation)
+ {
+ llinfos << "blocking navigate to URI " << new_location << llendl;
+
+ // "bounce back" to the current URL from the media entry
+ // NOTE: the only way block_navigation can be true is if we found the media entry, so we're guaranteed here that mep is not NULL.
+ impl->navigateTo(mep->getCurrentURL());
+ }
+ else
+ {
+
+ llinfos << "broadcasting navigate with URI " << new_location << llendl;
+
+ // Post the navigate to the cap
+ std::string cap = getRegion()->getCapability("ObjectMediaNavigate");
+ if(cap.empty())
+ {
+ // XXX *TODO: deal with no cap! It may happen! (retry?)
+ LL_WARNS("Media") << "Can't broadcast navigate event -- ObjectMediaNavigate cap is not available" << LL_ENDL;
+ return;
+ }
+
+ // If we got here, the cap is available. Index through all faces that have this media and send the navigate message.
+ LLSD sd;
+ sd["object_id"] = mID;
+ sd["current_url"] = new_location;
+ sd["texture_index"] = face_index;
+ LLHTTPClient::post(cap, sd, new LLMediaDataResponder("ObjectMediaNavigate", sd, this));
+ }
+ }
+ break;
+
+ case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED:
+ // This is the first location changed event after the start of a server-directed nav. Don't broadcast it.
+ llinfos << " NOT broadcasting navigate (server-directed)" << llendl;
+ break;
+
+ default:
+ // This is a subsequent location-changed due to a redirect. Don't broadcast.
+ llinfos << " NOT broadcasting navigate (redirect)" << llendl;
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+void LLVOVolume::sendMediaDataUpdate() const
+{
+ std::string url = getRegion()->getCapability("ObjectMedia");
+ if (!url.empty())
+ {
+ LLSD sd_payload;
+ sd_payload["verb"] = "UPDATE";
+ sd_payload[LLTextureEntry::OBJECT_ID_KEY] = mID;
+ LLSD object_media_data;
+ for (int i=0; i < getNumTEs(); i++) {
+ LLTextureEntry *texture_entry = getTE(i);
+ llassert((texture_entry->getMediaData() != NULL) == texture_entry->hasMedia());
+ const LLSD &media_data =
+ (texture_entry->getMediaData() == NULL) ? LLSD() : texture_entry->getMediaData()->asLLSD();
+ object_media_data.append(media_data);
+ }
+ sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
+
+ llinfos << "Sending media data: " << getID() << " " << ll_pretty_print_sd(sd_payload) << llendl;
+
+ LLHTTPClient::post(url, sd_payload, new LLMediaDataResponder("ObjectMedia", sd_payload, this));
+ }
+ // XXX *TODO: deal with no cap! It may happen! (retry?)
+}
+
+void LLVOVolume::removeMediaImpl(S32 texture_index)
+{
+ if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull())
+ {
+ return ;
+ }
+
+ //make the face referencing to mMediaImplList[texture_index] to point back to the old texture.
+ if(mDrawable)
+ {
+ LLFace* facep = mDrawable->getFace(texture_index) ;
+ if(facep)
+ {
+ LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ;
+ if(media_tex)
+ {
+ media_tex->removeMediaFromFace(facep) ;
+ }
+ }
+ }
+
+ //check if some other face(s) of this object reference(s)to this media impl.
+ S32 i ;
+ S32 end = (S32)mMediaImplList.size() ;
+ for(i = 0; i < end ; i++)
+ {
+ if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index])
+ {
+ break ;
+ }
+ }
+
+ if(i == end) //this object does not need this media impl.
+ {
+ mMediaImplList[texture_index]->removeObject(this) ;
+ }
+
+ mMediaImplList[texture_index] = NULL ;
+ return ;
+}
+
+void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index)
+{
+ if((S32)mMediaImplList.size() < texture_index + 1)
+ {
+ mMediaImplList.resize(texture_index + 1) ;
+ }
+
+ if(mMediaImplList[texture_index].notNull())
+ {
+ if(mMediaImplList[texture_index] == media_impl)
+ {
+ return ;
+ }
+
+ removeMediaImpl(texture_index) ;
+ }
+
+ mMediaImplList[texture_index] = media_impl;
+ media_impl->addObject(this) ;
+
+ //add the face to show the media if it is in playing
+ if(mDrawable)
+ {
+ LLFace* facep = mDrawable->getFace(texture_index) ;
+ if(facep)
+ {
+ LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ;
+ if(media_tex)
+ {
+ media_tex->addMediaToFace(facep) ;
+ }
+ }
+ else //the face is not available now, start media on this face later.
+ {
+ media_impl->setUpdated(TRUE) ;
+ }
+ }
+ return ;
+}
+
+viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const
+{
+ if(mMediaImplList.size() > face_id)
+ {
+ return mMediaImplList[face_id];
+ }
+ return NULL;
+}
+
+S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id)
+{
+ S32 end = (S32)mMediaImplList.size() ;
+ for(S32 face_id = start_face_id + 1; face_id < end; face_id++)
+ {
+ if(mMediaImplList[face_id] == media_impl)
+ {
+ return face_id ;
+ }
+ }
+ return -1 ;
+}
+
//----------------------------------------------------------------------------
void LLVOVolume::setLightTextureID(LLUUID id)
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 1b90219836..9a79b620d5 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -35,6 +35,7 @@
#include "llviewerobject.h"
#include "llviewertexture.h"
+#include "llviewermedia.h"
#include "llframetimer.h"
#include "llapr.h"
#include "m3math.h" // LLMatrix3
@@ -45,6 +46,8 @@ class LLViewerTextureAnim;
class LLDrawPool;
class LLSelectNode;
+typedef std::vector media_list_t;
+
enum LLVolumeInterfaceType
{
INTERFACE_FLEXIBLE = 1,
@@ -75,12 +78,14 @@ public:
// Class which embodies all Volume objects (with pcode LL_PCODE_VOLUME)
class LLVOVolume : public LLViewerObject
{
+ LOG_CLASS(LLVOVolume);
protected:
virtual ~LLVOVolume();
public:
static void initClass();
- static void preUpdateGeom();
+ static void cleanupClass();
+ static void preUpdateGeom();
enum
{
@@ -153,6 +158,7 @@ public:
/*virtual*/ void setScale(const LLVector3 &scale, BOOL damped);
+ /*virtual*/ void setNumTEs(const U8 num_tes);
/*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep);
/*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid);
/*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color);
@@ -224,13 +230,31 @@ public:
BOOL isVolumeGlobal() const;
BOOL canBeFlexible() const;
BOOL setIsFlexible(BOOL is_flexible);
-
+
+ void updateObjectMediaData(const LLSD &media_data_duples);
+ void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event);
+
+ // Sync the given media data with the impl and the given te
+ void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent);
+
+ // Send media data update to the simulator.
+ void sendMediaDataUpdate() const;
+
+ viewer_media_t getMediaImpl(U8 face_id) const;
+ S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id);
+
+ bool hasMedia() const;
+
protected:
S32 computeLODDetail(F32 distance, F32 radius);
BOOL calcLOD();
LLFace* addFace(S32 face_index);
void updateTEData();
+ void requestMediaDataUpdate();
+ void cleanUpMediaImpls();
+ void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
+ void removeMediaImpl(S32 texture_index) ;
public:
LLViewerTextureAnim *mTextureAnimp;
U8 mTexAnimMode;
@@ -251,6 +275,7 @@ private:
LLVolumeInterface *mVolumeImpl;
LLPointer mSculptTexture;
LLPointer mLightTexture;
+ media_list_t mMediaImplList;
// statics
public:
diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml
new file mode 100644
index 0000000000..6ba26f938d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index edbd28cd2d..053215f8ae 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -74,7 +74,11 @@
name="button focus"
picture_style="true"
tool_tip="Focus"
- width="20" />
+ width="20">
+
+
+ width="20">
+
+
+ width="20">
+
+
+ width="20">
+
+
+ width="20">
+
+
+
+ width="134">
+
+
+
+
+ name="checkbox edit linked parts" >
+
+
+
+ height="22" >
+
+
+
-
+ width="80" >
+
+
+ width="78">
+
+
Transparency %
@@ -2261,7 +2306,7 @@
layout="topleft"
left_delta="0"
name="glow label"
- top_pad="4"
+ top_pad="2"
width="80">
Glow
@@ -2281,7 +2326,7 @@
layout="topleft"
left_delta="0"
name="checkbox fullbright"
- top_pad="7"
+ top_pad="4"
width="81" />
Mapping
@@ -2439,6 +2484,40 @@
name="weave"
value="weave" />
+
Repeats per Face
@@ -2461,7 +2540,7 @@
left="20"
max_val="100"
name="TexScaleU"
- top_pad="10"
+ top_pad="6"
width="160" />
-
- Rotation (degrees)
-
+
-
- Repeats Per Meter
-
+ top_delta="25"
+ width="170" />
+
+ top_delta="20"
+ width="170" />