summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRider Linden <rider@lindenlab.com>2018-07-03 14:18:24 -0700
committerRider Linden <rider@lindenlab.com>2018-07-03 14:18:24 -0700
commita4137d72ebc9f49dfd8bd124b255da0dfbc4ba92 (patch)
tree5781b8ad54f1c26674a3e5085a76c77450c5261e
parentab159f7c4a35196003add5592df95fe2c139984e (diff)
MAINT-8821: New "My Environments" floater. First pass.
-rw-r--r--indra/llinventory/llsettingsbase.h1
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llenvironment.h1
-rw-r--r--indra/newview/llfloatereditextdaycycle.cpp1
-rw-r--r--indra/newview/llfloaterfixedenvironment.cpp6
-rw-r--r--indra/newview/llfloatermyenvironment.cpp769
-rw-r--r--indra/newview/llfloatermyenvironment.h122
-rw-r--r--indra/newview/llsettingsvo.cpp7
-rw-r--r--indra/newview/llviewerfloaterreg.cpp3
-rw-r--r--indra/newview/llviewermenu.cpp55
-rw-r--r--indra/newview/skins/default/xui/en/floater_my_environments.xml184
-rw-r--r--indra/newview/skins/default/xui/en/menu_settings_gear.xml57
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml16
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml10
14 files changed, 1204 insertions, 30 deletions
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index caae2dcd23..6c3b9e23ee 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -242,6 +242,7 @@ public:
inline void setAssetId(LLUUID value)
{ // note that this skips setLLSD
+ LL_WARNS("LAPRAS") << "Settings asset id set to:{" << value << "}" << LL_ENDL;
mSettings[SETTING_ASSETID] = value;
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 17a0e8d177..5dd0c15a5f 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -260,6 +260,7 @@ set(viewer_SOURCE_FILES
llfloatermemleak.cpp
llfloatermodelpreview.cpp
llfloatermodeluploadbase.cpp
+ llfloatermyenvironment.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
llfloaternotificationstabbed.cpp
@@ -881,6 +882,7 @@ set(viewer_HEADER_FILES
llfloatermemleak.h
llfloatermodelpreview.h
llfloatermodeluploadbase.h
+ llfloatermyenvironment.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
llfloaternotificationstabbed.h
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index d2664717dd..d9a1494424 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -152,6 +152,7 @@ public:
bool canAgentUpdateParcelEnvironment(bool useselected = false) const;
bool canAgentUpdateRegionEnvironment() const;
+ LLSettingsDay::ptr_t getCurrentDay() const { return mCurrentEnvironment->getDayCycle(); }
LLSettingsSky::ptr_t getCurrentSky() const { return mCurrentEnvironment->getSky(); }
LLSettingsWater::ptr_t getCurrentWater() const { return mCurrentEnvironment->getWater(); }
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index 6b748a9103..ba524c4dc5 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -1023,6 +1023,7 @@ void LLFloaterEditExtDayCycle::doApplyEnvironment(const std::string &where)
if ((!parcel) || (parcel->getLocalID() == INVALID_PARCEL_ID))
{
LL_WARNS("ENVIRONMENT") << "Can not identify parcel. Not applying." << LL_ENDL;
+ LLNotificationsUtil::add("WLParcelApplyFail");
return;
}
diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index 7efd45ca56..fd72bb3624 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -317,8 +317,12 @@ void LLFloaterFixedEnvironment::doApplyEnvironment(const std::string &where)
if (!parcel)
parcel = LLViewerParcelMgr::instance().getAgentParcel();
- if (!parcel)
+ if ((!parcel) || (parcel->getLocalID() == INVALID_PARCEL_ID))
+ {
+ LL_WARNS("ENVIRONMENT") << "Can not identify parcel. Not applying." << LL_ENDL;
+ LLNotificationsUtil::add("WLParcelApplyFail");
return;
+ }
if (mSettings->getSettingsType() == "sky")
LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast<LLSettingsSky>(mSettings), -1, -1);
diff --git a/indra/newview/llfloatermyenvironment.cpp b/indra/newview/llfloatermyenvironment.cpp
new file mode 100644
index 0000000000..83cd726eb8
--- /dev/null
+++ b/indra/newview/llfloatermyenvironment.cpp
@@ -0,0 +1,769 @@
+/**
+ * @file llfloatergesture.cpp
+ * @brief Read-only list of gestures from your inventory.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatermyenvironment.h"
+
+#include "llinventory.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llclipboard.h"
+
+#include "llagent.h"
+#include "llclipboard.h"
+#include "llkeyboard.h"
+#include "llmenugl.h"
+#include "llmultigesture.h"
+#include "llscrolllistctrl.h"
+#include "llcheckboxctrl.h"
+#include "lltrans.h"
+#include "llviewergesture.h"
+#include "llviewermenu.h"
+#include "llviewerinventory.h"
+#include "llviewercontrol.h"
+#include "llfloaterperms.h"
+
+//=========================================================================
+namespace
+{
+ const std::string CHECK_DAYS("chk_days");
+ const std::string CHECK_SKIES("chk_skies");
+ const std::string CHECK_WATER("chk_water");
+ const std::string PANEL_SETTINGS("pnl_settings");
+ const std::string CHECK_SHOWFOLDERS("chk_showfolders");
+ const std::string BUTTON_NEWSETTINGS("btn_gear");
+ const std::string BUTTON_GEAR("btn_newsettings");
+ const std::string BUTTON_DELETE("btn_del");
+ const std::string BUTTON_EDIT("btn_edit");
+
+}
+
+//=========================================================================
+#if 0
+BOOL item_name_precedes( LLInventoryItem* a, LLInventoryItem* b )
+{
+ return LLStringUtil::precedesDict( a->getName(), b->getName() );
+}
+
+class LLFloaterGestureObserver : public LLGestureManagerObserver
+{
+public:
+ LLFloaterGestureObserver(LLFloaterGesture* floater) : mFloater(floater) {}
+ virtual ~LLFloaterGestureObserver() {}
+ virtual void changed() { mFloater->refreshAll(); }
+
+private:
+ LLFloaterGesture* mFloater;
+};
+//-----------------------------
+// GestureCallback
+//-----------------------------
+
+class GestureShowCallback : public LLInventoryCallback
+{
+public:
+ void fire(const LLUUID &inv_item)
+ {
+ LLPreviewGesture::show(inv_item, LLUUID::null);
+
+ LLInventoryItem* item = gInventory.getItem(inv_item);
+ if (item)
+ {
+ LLPermissions perm = item->getPermissions();
+ perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Gestures"));
+ perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures"));
+ perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures"));
+ item->setPermissions(perm);
+ item->updateServer(FALSE);
+ }
+ }
+};
+
+class GestureCopiedCallback : public LLInventoryCallback
+{
+private:
+ LLFloaterGesture* mFloater;
+
+public:
+ GestureCopiedCallback(LLFloaterGesture* floater): mFloater(floater)
+ {}
+ void fire(const LLUUID &inv_item)
+ {
+ if(mFloater)
+ {
+ mFloater->addGesture(inv_item,NULL,mFloater->getChild<LLScrollListCtrl>("gesture_list"));
+
+ // EXP-1909 (Pasted gesture displayed twice)
+ // The problem is that addGesture is called here for the second time for the same item (which is copied)
+ // First time addGesture is called from LLFloaterGestureObserver::changed(), which is a callback for inventory
+ // change. So we need to refresh the gesture list to avoid duplicates.
+ mFloater->refreshAll();
+ }
+ }
+};
+
+#endif
+
+//=========================================================================
+LLFloaterMyEnvironment::LLFloaterMyEnvironment(const LLSD& key) :
+ LLFloater(key),
+ mInventoryList(nullptr),
+ mShowFolders(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS),
+ mTypeFilter((0x01 << static_cast<U64>(LLSettingsType::ST_DAYCYCLE)) | (0x01 << static_cast<U64>(LLSettingsType::ST_SKY)) | (0x01 << static_cast<U64>(LLSettingsType::ST_WATER))),
+ mSelectedAsset()
+{
+
+#if 0
+ mObserver = new LLFloaterGestureObserver(this);
+ LLGestureMgr::instance().addObserver(mObserver);
+
+ mCommitCallbackRegistrar.add("Gesture.Action.ToogleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this));
+ mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this));
+ mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2));
+ mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this));
+
+ mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2));
+#endif
+}
+
+LLFloaterMyEnvironment::~LLFloaterMyEnvironment()
+{
+ // LLGestureMgr::instance().removeObserver(mObserver);
+ // delete mObserver;
+ // mObserver = NULL;
+ // gInventory.removeObserver(this);
+}
+
+
+BOOL LLFloaterMyEnvironment::postBuild()
+{
+ mInventoryList = getChild<LLInventoryPanel>(PANEL_SETTINGS);
+
+ if (mInventoryList)
+ {
+ U32 filter_types = 0x0;
+ filter_types |= 0x1 << LLInventoryType::IT_SETTINGS;
+
+ mInventoryList->setFilterTypes(filter_types);
+
+// mInventoryList->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
+ mInventoryList->setShowFolderState(mShowFolders);
+ mInventoryList->setFilterSettingsTypes(mTypeFilter);
+ }
+
+ childSetCommitCallback(CHECK_DAYS, [this](LLUICtrl*, void*) { onFilterCheckChange(); }, nullptr);
+ childSetCommitCallback(CHECK_SKIES, [this](LLUICtrl*, void*) { onFilterCheckChange(); }, nullptr);
+ childSetCommitCallback(CHECK_WATER, [this](LLUICtrl*, void*) { onFilterCheckChange(); }, nullptr);
+ childSetCommitCallback(CHECK_SHOWFOLDERS, [this](LLUICtrl*, void*) { onShowFoldersChange(); }, nullptr);
+
+ /*TODO: Enable these*/
+ getChild<LLUICtrl>(BUTTON_NEWSETTINGS)->setEnabled(false);
+ getChild<LLUICtrl>(BUTTON_GEAR)->setEnabled(false);
+ getChild<LLUICtrl>(BUTTON_DELETE)->setEnabled(false);
+ getChild<LLUICtrl>(BUTTON_EDIT)->setEnabled(false);
+
+ return TRUE;
+}
+
+void LLFloaterMyEnvironment::refresh()
+{
+ getChild<LLCheckBoxCtrl>(CHECK_SHOWFOLDERS)->setValue(LLSD::Boolean(mShowFolders == LLInventoryFilter::SHOW_ALL_FOLDERS));
+
+ getChild<LLCheckBoxCtrl>(CHECK_DAYS)->setValue(LLSD::Boolean(mTypeFilter & (0x01 << static_cast<U64>(LLSettingsType::ST_DAYCYCLE))));
+ getChild<LLCheckBoxCtrl>(CHECK_SKIES)->setValue(LLSD::Boolean(mTypeFilter & (0x01 << static_cast<U64>(LLSettingsType::ST_SKY))));
+ getChild<LLCheckBoxCtrl>(CHECK_WATER)->setValue(LLSD::Boolean(mTypeFilter & (0x01 << static_cast<U64>(LLSettingsType::ST_WATER))));
+
+// if (mInventoryList)
+// {
+// LLUUID obj_id = findItemByAssetId(mSelectedAsset, false, false);
+// mInventoryList->setSelection(obj_id, false);
+// }
+}
+
+void LLFloaterMyEnvironment::onOpen(const LLSD& key)
+{
+ LLFloater::onOpen(key);
+
+ if (key.has("asset_id") && mInventoryList)
+ {
+ mSelectedAsset = key["asset_id"].asUUID();
+ }
+ else
+ {
+ mSelectedAsset.setNull();
+ }
+
+ refresh();
+}
+
+//-------------------------------------------------------------------------
+void LLFloaterMyEnvironment::onShowFoldersChange()
+{
+ bool show_check (getChild<LLCheckBoxCtrl>(CHECK_SHOWFOLDERS)->getValue().asBoolean());
+
+ mShowFolders = (show_check) ? LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS;
+
+ if (mInventoryList)
+ mInventoryList->setShowFolderState(mShowFolders);
+}
+
+void LLFloaterMyEnvironment::onFilterCheckChange()
+{
+ mTypeFilter = 0x0;
+
+ if (getChild<LLCheckBoxCtrl>(CHECK_DAYS)->getValue().asBoolean())
+ mTypeFilter |= 0x01 << static_cast<U64>(LLSettingsType::ST_DAYCYCLE);
+ if (getChild<LLCheckBoxCtrl>(CHECK_SKIES)->getValue().asBoolean())
+ mTypeFilter |= 0x01 << static_cast<U64>(LLSettingsType::ST_SKY);
+ if (getChild<LLCheckBoxCtrl>(CHECK_WATER)->getValue().asBoolean())
+ mTypeFilter |= 0x01 << static_cast<U64>(LLSettingsType::ST_WATER);
+
+ if (mInventoryList)
+ mInventoryList->setFilterSettingsTypes(mTypeFilter);
+}
+
+//-------------------------------------------------------------------------
+LLUUID LLFloaterMyEnvironment::findItemByAssetId(LLUUID asset_id, bool copyable_only, bool ignore_library)
+{
+ /*TODO: Rider: Move this to gInventory? */
+
+ LLViewerInventoryCategory::cat_array_t cats;
+ LLViewerInventoryItem::item_array_t items;
+ LLAssetIDMatches asset_id_matches(asset_id);
+
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cats,
+ items,
+ LLInventoryModel::INCLUDE_TRASH,
+ asset_id_matches);
+
+ if (!items.empty())
+ {
+ // search for copyable version first
+ for (auto & item : items)
+ {
+ const LLPermissions& item_permissions = item->getPermissions();
+ if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
+ {
+ if(!ignore_library || !gInventory.isObjectDescendentOf(item->getUUID(),gInventory.getLibraryRootFolderID()))
+ {
+ return item->getUUID();
+ }
+ }
+ }
+ // otherwise just return first instance, unless copyable requested
+ if (copyable_only)
+ {
+ return LLUUID::null;
+ }
+ else
+ {
+ if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID()))
+ {
+ return items[0]->getUUID();
+ }
+ }
+ }
+
+ return LLUUID::null;
+}
+
+#if 0
+void LLFloaterGesture::done()
+{
+ //this method can be called twice: for GestureFolder and once after loading all sudir of GestureFolder
+ if (gInventory.isCategoryComplete(mGestureFolderID))
+ {
+ LL_DEBUGS("Gesture")<< "mGestureFolderID loaded" << LL_ENDL;
+ // we load only gesture folder without childred.
+ LLInventoryModel::cat_array_t* categories;
+ LLInventoryModel::item_array_t* items;
+ uuid_vec_t unloaded_folders;
+ LL_DEBUGS("Gesture")<< "Get subdirs of Gesture Folder...." << LL_ENDL;
+ gInventory.getDirectDescendentsOf(mGestureFolderID, categories, items);
+ if (categories->empty())
+ {
+ gInventory.removeObserver(this);
+ LL_INFOS("Gesture")<< "Gesture dos NOT contains sub-directories."<< LL_ENDL;
+ return;
+ }
+ LL_DEBUGS("Gesture")<< "There are " << categories->size() << " Folders "<< LL_ENDL;
+ for (LLInventoryModel::cat_array_t::iterator it = categories->begin(); it != categories->end(); it++)
+ {
+ if (!gInventory.isCategoryComplete(it->get()->getUUID()))
+ {
+ unloaded_folders.push_back(it->get()->getUUID());
+ LL_DEBUGS("Gesture")<< it->get()->getName()<< " Folder added to fetchlist"<< LL_ENDL;
+ }
+
+ }
+ if (!unloaded_folders.empty())
+ {
+ LL_DEBUGS("Gesture")<< "Fetching subdirectories....." << LL_ENDL;
+ setFetchIDs(unloaded_folders);
+ startFetch();
+ }
+ else
+ {
+ LL_DEBUGS("Gesture")<< "All Gesture subdirectories have been loaded."<< LL_ENDL;
+ gInventory.removeObserver(this);
+ buildGestureList();
+ }
+ }
+ else
+ {
+ LL_WARNS("Gesture")<< "Gesture list was NOT loaded"<< LL_ENDL;
+ }
+}
+
+// virtual
+
+void LLFloaterGesture::refreshAll()
+{
+ if (!mGestureList) return;
+
+ buildGestureList();
+
+ if (mSelectedID.isNull())
+ {
+ mGestureList->selectFirstItem();
+ }
+ else
+ {
+ if (! mGestureList->setCurrentByID(mSelectedID))
+ {
+ mGestureList->selectFirstItem();
+ }
+ }
+
+ // Update button labels
+ onCommitList();
+}
+
+void LLFloaterGesture::buildGestureList()
+{
+ S32 scroll_pos = mGestureList->getScrollPos();
+ uuid_vec_t selected_items;
+ getSelectedIds(selected_items);
+ LL_DEBUGS("Gesture")<< "Rebuilding gesture list "<< LL_ENDL;
+ mGestureList->deleteAllItems();
+
+ LLGestureMgr::item_map_t::const_iterator it;
+ const LLGestureMgr::item_map_t& active_gestures = LLGestureMgr::instance().getActiveGestures();
+ for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
+ {
+ addGesture(it->first,it->second, mGestureList);
+ }
+ if (gInventory.isCategoryComplete(mGestureFolderID))
+ {
+ LLIsType is_gesture(LLAssetType::AT_GESTURE);
+ LLInventoryModel::cat_array_t categories;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendentsIf(mGestureFolderID, categories, items,
+ LLInventoryModel::EXCLUDE_TRASH, is_gesture);
+
+ for (LLInventoryModel::item_array_t::iterator it = items.begin(); it!= items.end(); ++it)
+ {
+ LLInventoryItem* item = it->get();
+ if (active_gestures.find(item->getUUID()) == active_gestures.end())
+ {
+ // if gesture wasn't loaded yet, we can display only name
+ addGesture(item->getUUID(), NULL, mGestureList);
+ }
+ }
+ }
+
+ // attempt to preserve scroll position through re-builds
+ // since we do re-build whenever something gets dirty
+ for(uuid_vec_t::iterator it = selected_items.begin(); it != selected_items.end(); it++)
+ {
+ mGestureList->selectByID(*it);
+ }
+ mGestureList->setScrollPos(scroll_pos);
+}
+
+void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gesture,LLCtrlListInterface * list )
+{
+ // Note: Can have NULL item if inventory hasn't arrived yet.
+ static std::string item_name = getString("loading");
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (item)
+ {
+ item_name = item->getName();
+ }
+
+ static std::string font_style = "NORMAL";
+ // If gesture is playing, bold it
+
+ LLSD element;
+ element["id"] = item_id;
+
+ if (gesture)
+ {
+ if (gesture->mPlaying)
+ {
+ font_style = "BOLD";
+ }
+ item_name = gesture->mName;
+ element["columns"][0]["column"] = "trigger";
+ element["columns"][0]["value"] = gesture->mTrigger;
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = font_style;
+
+ std::string key_string;
+ std::string buffer;
+
+ if (gesture->mKey == KEY_NONE)
+ {
+ buffer = "---";
+ key_string = "~~~"; // alphabetize to end
+ }
+ else
+ {
+ key_string = LLKeyboard::stringFromKey(gesture->mKey);
+ buffer = LLKeyboard::stringFromAccelerator(gesture->mMask,
+ gesture->mKey);
+ }
+
+ element["columns"][1]["column"] = "shortcut";
+ element["columns"][1]["value"] = buffer;
+ element["columns"][1]["font"]["name"] = "SANSSERIF";
+ element["columns"][1]["font"]["style"] = font_style;
+
+ // hidden column for sorting
+ element["columns"][2]["column"] = "key";
+ element["columns"][2]["value"] = key_string;
+ element["columns"][2]["font"]["name"] = "SANSSERIF";
+ element["columns"][2]["font"]["style"] = font_style;
+
+ // Only add "playing" if we've got the name, less confusing. JC
+ if (item && gesture->mPlaying)
+ {
+ item_name += " " + getString("playing");
+ }
+ element["columns"][3]["column"] = "name";
+ element["columns"][3]["value"] = item_name;
+ element["columns"][3]["font"]["name"] = "SANSSERIF";
+ element["columns"][3]["font"]["style"] = font_style;
+ }
+ else
+ {
+ element["columns"][0]["column"] = "trigger";
+ element["columns"][0]["value"] = "";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = font_style;
+ element["columns"][1]["column"] = "shortcut";
+ element["columns"][1]["value"] = "---";
+ element["columns"][1]["font"]["name"] = "SANSSERIF";
+ element["columns"][1]["font"]["style"] = font_style;
+ element["columns"][2]["column"] = "key";
+ element["columns"][2]["value"] = "~~~";
+ element["columns"][2]["font"]["name"] = "SANSSERIF";
+ element["columns"][2]["font"]["style"] = font_style;
+ element["columns"][3]["column"] = "name";
+ element["columns"][3]["value"] = item_name;
+ element["columns"][3]["font"]["name"] = "SANSSERIF";
+ element["columns"][3]["font"]["style"] = font_style;
+ }
+
+ LL_DEBUGS("Gesture") << "Added gesture [" << item_name << "]" << LL_ENDL;
+
+ LLScrollListItem* sl_item = list->addElement(element, ADD_BOTTOM);
+ if(sl_item)
+ {
+ LLFontGL::StyleFlags style = LLGestureMgr::getInstance()->isGestureActive(item_id) ? LLFontGL::BOLD : LLFontGL::NORMAL;
+ // *TODO find out why ["font"]["style"] does not affect font style
+ ((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(style);
+ }
+}
+
+void LLFloaterGesture::getSelectedIds(uuid_vec_t& ids)
+{
+ std::vector<LLScrollListItem*> items = mGestureList->getAllSelected();
+ for(std::vector<LLScrollListItem*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ ids.push_back((*it)->getUUID());
+ }
+}
+
+bool LLFloaterGesture::isActionEnabled(const LLSD& command)
+{
+ // paste copy_uuid edit_gesture
+ std::string command_name = command.asString();
+ if("paste" == command_name)
+ {
+ if(!LLClipboard::instance().hasContents())
+ return false;
+
+ std::vector<LLUUID> ids;
+ LLClipboard::instance().pasteFromClipboard(ids);
+ for(std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ LLInventoryItem* item = gInventory.getItem(*it);
+
+ if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ else if("copy_uuid" == command_name || "edit_gesture" == command_name)
+ {
+ return mGestureList->getAllSelected().size() == 1;
+ }
+ return true;
+}
+
+void LLFloaterGesture::onClickPlay()
+{
+ const LLUUID& item_id = mGestureList->getCurrentID();
+ if(item_id.isNull()) return;
+
+ LL_DEBUGS("Gesture")<<" Trying to play gesture id: "<< item_id <<LL_ENDL;
+ if(!LLGestureMgr::instance().isGestureActive(item_id))
+ {
+ // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList.
+ BOOL inform_server = TRUE;
+ BOOL deactivate_similar = FALSE;
+ LLGestureMgr::instance().setGestureLoadedCallback(item_id, boost::bind(&LLFloaterGesture::playGesture, this, item_id));
+ LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ llassert(item);
+ if (item)
+ {
+ LLGestureMgr::instance().activateGestureWithAsset(item_id, item->getAssetUUID(), inform_server, deactivate_similar);
+ LL_DEBUGS("Gesture")<< "Activating gesture with inventory ID: " << item_id <<LL_ENDL;
+ }
+ }
+ else
+ {
+ playGesture(item_id);
+ }
+}
+
+void LLFloaterGesture::onClickNew()
+{
+ LLPointer<LLInventoryCallback> cb = new GestureShowCallback();
+ create_inventory_item(gAgent.getID(),
+ gAgent.getSessionID(),
+ LLUUID::null,
+ LLTransactionID::tnull,
+ "New Gesture",
+ "",
+ LLAssetType::AT_GESTURE,
+ LLInventoryType::IT_GESTURE,
+ NO_INV_SUBTYPE,
+ PERM_MOVE | LLFloaterPerms::getNextOwnerPerms("Gestures"),
+ cb);
+}
+
+void LLFloaterGesture::onActivateBtnClick()
+{
+ uuid_vec_t ids;
+ getSelectedIds(ids);
+ if(ids.empty())
+ return;
+
+ LLGestureMgr* gm = LLGestureMgr::getInstance();
+ uuid_vec_t::const_iterator it = ids.begin();
+ BOOL first_gesture_state = gm->isGestureActive(*it);
+ BOOL is_mixed = FALSE;
+ while( ++it != ids.end() )
+ {
+ if(first_gesture_state != gm->isGestureActive(*it))
+ {
+ is_mixed = TRUE;
+ break;
+ }
+ }
+ for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ if(is_mixed)
+ {
+ gm->activateGesture(*it);
+ }
+ else
+ {
+ if(first_gesture_state)
+ {
+ gm->deactivateGesture(*it);
+ }
+ else
+ {
+ gm->activateGesture(*it);
+ }
+ }
+ }
+}
+
+void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
+{
+ std::string command_name = command.asString();
+ // Since we select this command, the inventory items must have already arrived
+ if("copy_gesture" == command_name)
+ {
+ uuid_vec_t ids;
+ getSelectedIds(ids);
+ // Make sure the clipboard is empty
+ LLClipboard::instance().reset();
+ for(uuid_vec_t::iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ LLInventoryItem* item = gInventory.getItem(*it);
+ if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
+ {
+ LLWString item_name = utf8str_to_wstring(item->getName());
+ LLClipboard::instance().addToClipboard(item_name, 0, item_name.size());
+ }
+ }
+ }
+ else if ("paste" == command_name)
+ {
+ std::vector<LLUUID> ids;
+ LLClipboard::instance().pasteFromClipboard(ids);
+ if(ids.empty() || !gInventory.isCategoryComplete(mGestureFolderID))
+ return;
+ LLInventoryCategory* gesture_dir = gInventory.getCategory(mGestureFolderID);
+ llassert(gesture_dir);
+ LLPointer<GestureCopiedCallback> cb = new GestureCopiedCallback(this);
+
+ for(std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ LLInventoryItem* item = gInventory.getItem(*it);
+ if(gesture_dir && item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[COPY_NAME]"] = item->getName();
+ LL_DEBUGS("Gesture")<< "Copying gesture " << item->getName() << " "<< item->getUUID() << " into "
+ << gesture_dir->getName() << " "<< gesture_dir->getUUID() << LL_ENDL;
+ copy_inventory_item(gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(),
+ gesture_dir->getUUID(), getString("copy_name", string_args), cb);
+ }
+ }
+ LLClipboard::instance().reset();
+ }
+ else if ("copy_uuid" == command_name)
+ {
+ LLClipboard::instance().copyToClipboard(mGestureList->getCurrentID(),LLAssetType::AT_GESTURE);
+ }
+}
+
+void LLFloaterGesture::onClickEdit()
+{
+ const LLUUID& item_id = mGestureList->getCurrentID();
+
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (!item) return;
+
+ LLPreviewGesture* previewp = LLPreviewGesture::show(item_id, LLUUID::null);
+ if (!previewp->getHost())
+ {
+ previewp->setRect(gFloaterView->findNeighboringPosition(this, previewp));
+ }
+}
+
+void LLFloaterGesture::onCommitList()
+{
+ const LLUUID& item_id = mGestureList->getCurrentID();
+
+ mSelectedID = item_id;
+ if (LLGestureMgr::instance().isGesturePlaying(item_id))
+ {
+ getChildView("play_btn")->setVisible( false);
+ getChildView("stop_btn")->setVisible( true);
+ }
+ else
+ {
+ getChildView("play_btn")->setVisible( true);
+ getChildView("stop_btn")->setVisible( false);
+ }
+}
+
+void LLFloaterGesture::onDeleteSelected()
+{
+ uuid_vec_t ids;
+ getSelectedIds(ids);
+ if(ids.empty())
+ return;
+
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLGestureMgr* gm = LLGestureMgr::getInstance();
+ for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ const LLUUID& selected_item = *it;
+ LLInventoryItem* inv_item = gInventory.getItem(selected_item);
+ if (inv_item && inv_item->getInventoryType() == LLInventoryType::IT_GESTURE)
+ {
+ if(gm->isGestureActive(selected_item))
+ {
+ gm->deactivateGesture(selected_item);
+ }
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
+ new_item->setParent(trash_id);
+ // no need to restamp it though it's a move into trash because
+ // it's a brand new item already.
+ new_item->updateParentOnServer(FALSE);
+ gInventory.updateItem(new_item);
+ }
+ }
+ gInventory.notifyObservers();
+ buildGestureList();
+}
+
+void LLFloaterGesture::addToCurrentOutFit()
+{
+ uuid_vec_t ids;
+ getSelectedIds(ids);
+ LLAppearanceMgr* am = LLAppearanceMgr::getInstance();
+ LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
+ for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ am->addCOFItemLink(*it, cb);
+ }
+}
+
+void LLFloaterGesture::playGesture(LLUUID item_id)
+{
+ LL_DEBUGS("Gesture")<<"Playing gesture "<< item_id<<LL_ENDL;
+
+ if (LLGestureMgr::instance().isGesturePlaying(item_id))
+ {
+ LLGestureMgr::instance().stopGesture(item_id);
+ }
+ else
+ {
+ LLGestureMgr::instance().playGesture(item_id);
+ }
+}
+#endif
diff --git a/indra/newview/llfloatermyenvironment.h b/indra/newview/llfloatermyenvironment.h
new file mode 100644
index 0000000000..f3ff9f779d
--- /dev/null
+++ b/indra/newview/llfloatermyenvironment.h
@@ -0,0 +1,122 @@
+/**
+ * @file llfloatermyenvironment.h
+ * @brief Read-only list of gestures from your inventory.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+/**
+ * (Also has legacy gesture editor for testing.)
+ */
+
+#ifndef LL_LLFLOATERMYENVIRONMENT_H
+#define LL_LLFLOATERMYENVIRONMENT_H
+#include <vector>
+
+#include "llfloater.h"
+#include "llinventoryobserver.h"
+#include "llinventoryfilter.h"
+
+class LLView;
+class LLButton;
+class LLLineEditor;
+class LLComboBox;
+class LLViewerGesture;
+class LLGestureOptions;
+class LLMenuGL;
+class LLInventoryPanel;
+
+class LLFloaterMyEnvironment
+: public LLFloater, LLInventoryFetchDescendentsObserver
+{
+ LOG_CLASS(LLFloaterMyEnvironment);
+public:
+ LLFloaterMyEnvironment(const LLSD& key);
+ virtual ~LLFloaterMyEnvironment();
+
+ virtual BOOL postBuild() override;
+ virtual void refresh() override;
+
+ virtual void onOpen(const LLSD& key) override;
+
+private:
+ LLInventoryPanel * mInventoryList;
+
+ void onShowFoldersChange();
+ void onFilterCheckChange();
+
+ U64 mTypeFilter;
+ LLInventoryFilter::EFolderShow mShowFolders;
+ LLUUID mSelectedAsset;
+
+ static LLUUID findItemByAssetId(LLUUID asset_id, bool copyable_only, bool ignore_library);
+
+#if 0
+ virtual void done ();
+ void refreshAll();
+ /**
+ * @brief Add new scrolllistitem into gesture_list.
+ * @param item_id inventory id of gesture
+ * @param gesture can be NULL , if item was not loaded yet
+ */
+ void addGesture(const LLUUID& item_id, LLMultiGesture* gesture, LLCtrlListInterface * list);
+
+protected:
+ // Reads from the gesture manager's list of active gestures
+ // and puts them in this list.
+ void buildGestureList();
+ void playGesture(LLUUID item_id);
+private:
+ void addToCurrentOutFit();
+ /**
+ * @brief This method is using to collect selected items.
+ * In some places gesture_list can be rebuilt by gestureObservers during iterating data from LLScrollListCtrl::getAllSelected().
+ * Therefore we have to copy these items to avoid viewer crash.
+ * @see LLFloaterGesture::onActivateBtnClick
+ */
+ void getSelectedIds(uuid_vec_t& ids);
+ bool isActionEnabled(const LLSD& command);
+ /**
+ * @brief Activation rules:
+ * According to Gesture Spec:
+ * 1. If all selected gestures are active: set to inactive
+ * 2. If all selected gestures are inactive: set to active
+ * 3. If selected gestures are in a mixed state: set all to active
+ */
+ void onActivateBtnClick();
+ void onClickEdit();
+ void onClickPlay();
+ void onClickNew();
+ void onCommitList();
+ void onCopyPasteAction(const LLSD& command);
+ void onDeleteSelected();
+
+ LLUUID mSelectedID;
+ LLUUID mGestureFolderID;
+ LLScrollListCtrl* mGestureList;
+
+ LLFloaterGestureObserver* mObserver;
+#endif
+};
+
+
+#endif
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index e2c8652f47..5ea29fb609 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -162,7 +162,6 @@ void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings
std::stringstream buffer;
LLSD settingdata(settings->getSettings());
- LL_WARNS("LAPRAS") << "Sending '" << settingdata << "' for asset." << LL_ENDL;
LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
@@ -176,14 +175,16 @@ void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings
void LLSettingsVOBase::onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
{
- LL_WARNS("SETTINGS") << "itemId:" << itemId << " newAssetId:" << newAssetId << " newItemId:" << newItemId << " response:" << response << LL_ENDL;
+ LL_INFOS("SETTINGS") << "itemId:" << itemId << " newAssetId:" << newAssetId << " newItemId:" << newItemId << " response:" << response << LL_ENDL;
+ psettings->setAssetId(newAssetId);
if (callback)
callback( newAssetId, itemId, LLUUID::null, response );
}
void LLSettingsVOBase::onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
{
- LL_WARNS("SETTINGS") << "Upload to task complete!" << LL_ENDL;
+ LL_INFOS("SETTINGS") << "Upload to task complete!" << LL_ENDL;
+ psettings->setAssetId(newAssetId);
if (callback)
callback(newAssetId, itemId, taskId, response);
}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 7c5ccb1087..a57f5e1be0 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -87,6 +87,7 @@
#include "llfloatermediasettings.h"
#include "llfloatermemleak.h"
#include "llfloatermodelpreview.h"
+#include "llfloatermyenvironment.h"
#include "llfloaternamedesc.h"
#include "llfloaternotificationsconsole.h"
#include "llfloaternotificationstabbed.h"
@@ -224,7 +225,7 @@ void LLViewerFloaterReg::registerFloaters()
//LLFloaterReg::add("env_fixed_environmentent", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironment>);
LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditExtDayCycle>);
-
+ LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyEnvironment>);
LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index e992cce26e..745f441416 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -8398,42 +8398,63 @@ class LLWorldEnvSettings : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- std::string tod = userdata.asString();
+ std::string event_name = userdata.asString();
- if (tod == "sunrise")
+ if (event_name == "sunrise")
{
LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE);
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+ LLEnvironment::instance().updateEnvironment();
}
- else if (tod == "noon")
+ else if (event_name == "noon")
{
LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY);
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+ LLEnvironment::instance().updateEnvironment();
}
- else if (tod == "sunset")
+ else if (event_name == "sunset")
{
LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET);
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+ LLEnvironment::instance().updateEnvironment();
}
- else if (tod == "midnight")
+ else if (event_name == "midnight")
{
LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT);
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+ LLEnvironment::instance().updateEnvironment();
}
- else if (tod == "region")
+ else if (event_name == "region")
{
LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL);
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+ LLEnvironment::instance().updateEnvironment();
}
- else if (tod == "pauseclouds")
+ else if (event_name == "pause_clouds")
{
if (LLEnvironment::instance().isCloudScrollPaused())
LLEnvironment::instance().resumeCloudScroll();
else
LLEnvironment::instance().pauseCloudScroll();
}
+ else if (event_name == "my_environs")
+ {
+ LLUUID asset_id;
+
+ LLSettingsBase::ptr_t cur(LLEnvironment::instance().getCurrentDay());
+ if (!cur)
+ {
+ cur = LLEnvironment::instance().getCurrentSky();
+ }
+
+ if (cur)
+ {
+ asset_id = cur->getAssetId();
+ }
+
+ LLFloaterReg::showInstance("my_environments", LLSDMap("asset_id", LLSD::UUID(asset_id)));
+ }
- LLEnvironment::instance().updateEnvironment();
return true;
}
};
@@ -8443,9 +8464,9 @@ class LLWorldEnableEnvSettings : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
bool result = false;
- std::string tod = userdata.asString();
+ std::string event_name = userdata.asString();
- if (tod == "pauseclouds")
+ if (event_name == "pause_clouds")
{
return LLEnvironment::instance().isCloudScrollPaused();
}
@@ -8454,35 +8475,35 @@ class LLWorldEnableEnvSettings : public view_listener_t
if (!sky)
{
- return (tod == "region");
+ return (event_name == "region");
}
std::string skyname = (sky) ? sky->getName() : "";
LLUUID skyid = (sky) ? sky->getAssetId() : LLUUID::null;
- if (tod == "sunrise")
+ if (event_name == "sunrise")
{
result = (skyid == LLEnvironment::KNOWN_SKY_SUNRISE);
}
- else if (tod == "noon")
+ else if (event_name == "noon")
{
result = (skyid == LLEnvironment::KNOWN_SKY_MIDDAY);
}
- else if (tod == "sunset")
+ else if (event_name == "sunset")
{
result = (skyid == LLEnvironment::KNOWN_SKY_SUNSET);
}
- else if (tod == "midnight")
+ else if (event_name == "midnight")
{
result = (skyid == LLEnvironment::KNOWN_SKY_MIDNIGHT);
}
- else if (tod == "region")
+ else if (event_name == "region")
{
return false;
}
else
{
- LL_WARNS() << "Unknown time-of-day item: " << tod << LL_ENDL;
+ LL_WARNS() << "Unknown time-of-day item: " << event_name << LL_ENDL;
}
return result;
}
diff --git a/indra/newview/skins/default/xui/en/floater_my_environments.xml b/indra/newview/skins/default/xui/en/floater_my_environments.xml
new file mode 100644
index 0000000000..74921e8b64
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_my_environments.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<floater
+ positioning="cascading"
+ save_rect="true"
+ legacy_header_height="18"
+ can_resize="true"
+ height="465"
+ name="my_environments"
+ help_topic="my_environments"
+ title="MY ENVIRONMENTS"
+ background_visible="true"
+ label="Places"
+ layout="topleft"
+ min_height="350"
+ min_width="265"
+ width="313">
+ <layout_stack
+ follows="all"
+ layout="topleft"
+ left="5"
+ top="20"
+ right="-5"
+ bottom="-5"
+ orientation="vertical">
+ <layout_panel
+ border="true"
+ bevel_style="in"
+ auto_resize="false"
+ user_resize="true"
+ tab_group="1"
+ height="24"
+ name="filter_panel"
+ label="Filters"
+ font="SansSerifBold">
+ <icon
+ height="16"
+ image_name="Inv_SettingsDay"
+ layout="topleft"
+ mouse_opaque="true"
+ name="icon_settingsdays"
+ left="4"
+ width="16" />
+ <check_box
+ height="16"
+ label="Days"
+ layout="topleft"
+ left_pad="2"
+ name="chk_days"
+ top_delta="0"
+ width="60" />
+ <icon
+ height="16"
+ image_name="Inv_SettingsSky"
+ layout="topleft"
+ mouse_opaque="true"
+ name="icon_settingsskies"
+ left_pad="10"
+ width="16" />
+ <check_box
+ height="16"
+ label="Skies"
+ layout="topleft"
+ left_pad="2"
+ name="chk_skies"
+ top_delta="0"
+ width="60" />
+ <icon
+ height="16"
+ image_name="Inv_SettingsWater"
+ layout="topleft"
+ mouse_opaque="true"
+ name="icon_settingswater"
+ left_pad="10"
+ width="16" />
+ <check_box
+ height="16"
+ label="Water"
+ layout="topleft"
+ left_pad="2"
+ name="chk_water"
+ top_delta="0"
+ width="60" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="true"
+ user_resize="true"
+ tab_group="1"
+ name="list_panel"
+ label="Environments"
+ font="SansSerifBold">
+ <inventory_panel
+ allow_multi_select="false"
+ bg_visible="true"
+ bg_alpha_color="DkGray2"
+ border="true"
+ follows="left|top|right|bottom"
+ left="2"
+ name="pnl_settings"
+ top="2"
+ right="-2"
+ bottom="-36" />
+ <check_box
+ follows="left|bottom"
+ height="14"
+ initial_value="false"
+ label="Show Empty Folders"
+ layout="topleft"
+ name="chk_showfolders"
+ top="-20"
+ top_pad="0"
+ left_delta="-3"
+ width="200" />
+
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ user_resize="true"
+ tab_group="1"
+ height="62"
+ name="pnl_control"
+ font="SansSerifBold">
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ top_pad="0"
+ follows="top|left|right"
+ height="30"
+ label="bottom_panel"
+ layout="topleft"
+ left="0"
+ name="pnl_bottom">
+ <menu_button
+ follows="bottom|left"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ menu_filename="menu_settings_gear.xml"
+ name="btn_gear"
+ top="5"
+ tool_tip="More options"
+ width="18" />
+ <button
+ follows="bottom|left"
+ font="SansSerifBigBold"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="btn_newsettings"
+ tool_tip="Make new gesture"
+ top_delta="0"
+ width="18" />
+ <button
+ follows="bottom|right"
+ font="SansSerifBigBold"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ image_disabled="TrashItem_Disabled"
+ layout="topleft"
+ name="btn_del"
+ right="-5"
+ tool_tip="Delete this gesture"
+ top_delta="0"
+ width="18" />
+ </panel>
+ <button
+ follows="top|left"
+ height="23"
+ label="Edit"
+ layout="topleft"
+ left="6"
+ name="btn_edit"
+ top_pad="5"
+ width="83" />
+
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_settings_gear.xml b/indra/newview/skins/default/xui/en/menu_settings_gear.xml
new file mode 100644
index 0000000000..73fae4f693
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_settings_gear.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ layout="topleft"
+ mouse_opaque="false"
+ name="menu_settings_gear"
+ visible="false">
+ <menu_item_call
+ label="Apply Selected Setting to Myself"
+ layout="topleft"
+ name="activate">
+ <on_click
+ function="Gesture.Action.ToogleActiveState" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ layout="topleft"
+ name="copy_settings">
+ <on_click
+ function="Gesture.Action.CopyPaste"
+ parameter="copy_gesture" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="copy_gesture" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="paste_settings">
+ <on_click
+ function="Gesture.Action.CopyPaste"
+ parameter="paste" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="paste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy UUID"
+ layout="topleft"
+ name="copy_uuid">
+ <on_click
+ function="Gesture.Action.CopyPaste"
+ parameter="copy_uuid" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="copy_uuid" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="edit_settings">
+ <on_click
+ function="Gesture.Action.ShowPreview" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="edit_settings" />
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index b7a6cb9287..fe3f52ebcb 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -695,23 +695,23 @@
parameter="region" />
</menu_item_check>
<menu_item_separator/>
- <menu_item
+ <menu_item_call
label="My Environments..."
- name="My Environments">
- <menu_item_check.on_click
- function="World.MyEnvirons"
+ name="my_environs">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
parameter="my_environs" />
- </menu_item>
+ </menu_item_call>
<menu_item_separator/>
<menu_item_check
label="Pause Clouds"
- name="pauseclouds">
+ name="pause_clouds">
<menu_item_check.on_click
function="World.EnvSettings"
- parameter="pauseclouds" />
+ parameter="pause_clouds" />
<menu_item_check.on_check
function="World.EnableEnvSettings"
- parameter="pauseclouds" />
+ parameter="pause_clouds" />
</menu_item_check>
</menu>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index eb4f658495..6473ec9bc3 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -11140,5 +11140,15 @@ This Region does not support environmental settings.
Unable to import legacy Windlight settings from [FILE].
<tag>fail</tag>
</notification>
+
+ <notification
+ icon="notify.tga"
+ name="WLParcelApplyFail"
+ persist="true"
+ type="alertmodal">
+Unable to set the environment for this parcel.
+Please enter or select a parcel that you have rights to modify.
+ <tag>fail</tag>
+ </notification>
</notifications>