diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/llenvironment.h | 1 | ||||
-rw-r--r-- | indra/newview/llfloatereditextdaycycle.cpp | 1 | ||||
-rw-r--r-- | indra/newview/llfloaterfixedenvironment.cpp | 6 | ||||
-rw-r--r-- | indra/newview/llfloatermyenvironment.cpp | 769 | ||||
-rw-r--r-- | indra/newview/llfloatermyenvironment.h | 122 | ||||
-rw-r--r-- | indra/newview/llsettingsvo.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llviewerfloaterreg.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llviewermenu.cpp | 55 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_my_environments.xml | 184 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_settings_gear.xml | 57 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 16 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 10 |
13 files changed, 1203 insertions, 30 deletions
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> |