FIRE-20809: Improve HUD management

master
Ansariel 2018-01-10 23:07:02 +01:00
parent 2e3d7676f5
commit 50d1556d3b
21 changed files with 725 additions and 7 deletions

View File

@ -166,6 +166,7 @@ set(viewer_SOURCE_FILES
fsfloatervoicecontrols.cpp
fsfloatervolumecontrols.cpp
fsfloatervramusage.cpp
fsfloaterwearablefavorites.cpp
fskeywords.cpp
fslightshare.cpp
fslslbridge.cpp
@ -914,6 +915,7 @@ set(viewer_HEADER_FILES
fsfloatervoicecontrols.h
fsfloatervolumecontrols.h
fsfloatervramusage.h
fsfloaterwearablefavorites.h
fsgridhandler.h
fskeywords.h
fslightshare.h

View File

@ -598,4 +598,14 @@
is_running_function="Floater.IsOpen"
is_running_parameters="fs_group_titles"
/>
<command name="wearable_favorites"
available_in_toybox="true"
icon="Wearable_Favorites_Icon"
label_ref="Command_Wearable_Favorites_Label"
tooltip_ref="Command_Wearable_Favorites_Tooltip"
execute_function="Floater.Toggle"
execute_parameters="fs_wearable_favorites"
is_running_function="Floater.IsOpen"
is_running_parameters="fs_wearable_favorites"
/>
</commands>

View File

@ -24522,6 +24522,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>1</integer>
</map>
<key>FSWearableFavoritesSortOrder</key>
<map>
<key>Comment</key>
<string>The sort order for the wearable favorites item list</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>3</integer>
</map>
</map>
</llsd>

View File

@ -734,7 +734,16 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>ProtectWearableFavoritesFolders</key>
<map>
<key>Comment</key>
<string>Keep the Wearable Favorites folder in Inventory safe from manual changes.</string>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FSKeywordOn</key>
<map>
<key>Comment</key>

View File

@ -0,0 +1,376 @@
/**
* @file fsfloaterwearablefavorites.cpp
* @brief Class for the favorite wearables floater
*
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (c) 2018 Ansariel Hiller @ Second Life
*
* 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
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "fsfloaterwearablefavorites.h"
#include "fscommon.h"
#include "llappearancemgr.h"
#include "llbutton.h"
#include "llfiltereditor.h"
#include "llinventoryfunctions.h"
#include "llinventoryobserver.h"
#include "llmenugl.h"
#include "llmenubutton.h"
#include "lltoggleablemenu.h"
#include "llviewercontrol.h" // for gSavedSettings
#include "llviewermenu.h" // for gMenuHolder
#include "rlvactions.h"
#include "rlvlocks.h"
#define FS_WEARABLE_FAVORITES_FOLDER "#Wearable Favorites"
static LLDefaultChildRegistry::Register<FSWearableFavoritesItemsList> r("fs_wearable_favorites_items_list");
FSWearableFavoritesItemsList::FSWearableFavoritesItemsList(const Params& p)
: LLWearableItemsList(p)
{
}
BOOL FSWearableFavoritesItemsList::handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
// Scroll folder view if needed. Never accepts a drag or drop.
*accept = ACCEPT_NO;
autoScroll(x, y);
if (cargo_type == DAD_BODYPART || cargo_type == DAD_CLOTHING || cargo_type == DAD_OBJECT)
{
if (drop)
{
LLInventoryItem* item = (LLInventoryItem*)cargo_data;
if (!mDADSignal.empty())
{
mDADSignal(item->getUUID());
}
}
else
{
*accept = ACCEPT_YES_SINGLE;
}
}
return TRUE;
}
LLUUID FSFloaterWearableFavorites::sFolderID = LLUUID();
FSFloaterWearableFavorites::FSFloaterWearableFavorites(const LLSD& key)
: LLFloater(key),
mItemsList(NULL),
mInitialized(false),
mDADCallbackConnection()
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
}
FSFloaterWearableFavorites::~FSFloaterWearableFavorites()
{
if (gInventory.containsObserver(mCategoriesObserver))
{
gInventory.removeObserver(mCategoriesObserver);
}
delete mCategoriesObserver;
if (mDADCallbackConnection.connected())
{
mDADCallbackConnection.disconnect();
}
if (mOptionsMenuHandle.get())
{
mOptionsMenuHandle.get()->die();
}
}
//virtual
BOOL FSFloaterWearableFavorites::postBuild()
{
mItemsList = getChild<FSWearableFavoritesItemsList>("favorites_list");
mItemsList->setNoFilteredItemsMsg(getString("search_no_items"));
mItemsList->setDoubleClickCallback(boost::bind(&FSFloaterWearableFavorites::onDoubleClick, this));
mRemoveItemBtn = getChild<LLButton>("remove_btn");
mRemoveItemBtn->setCommitCallback(boost::bind(&FSFloaterWearableFavorites::handleRemove, this));
mFilterEditor = getChild<LLFilterEditor>("wearable_filter_input");
mFilterEditor->setCommitCallback(boost::bind(&FSFloaterWearableFavorites::onFilterEdit, this, _2));
// Create menus.
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
registrar.add("FavWearables.Action", boost::bind(&FSFloaterWearableFavorites::onOptionsMenuItemClicked, this, _2));
enable_registrar.add("FavWearables.CheckAction", boost::bind(&FSFloaterWearableFavorites::onOptionsMenuItemChecked, this, _2));
mOptionsButton = getChild<LLMenuButton>("options_btn");
LLToggleableMenu* options_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_fs_wearable_favorites.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if (options_menu)
{
mOptionsMenuHandle = options_menu->getHandle();
mOptionsButton->setMenu(options_menu, LLMenuButton::MP_BOTTOM_LEFT);
}
return TRUE;
}
//virtual
void FSFloaterWearableFavorites::onOpen(const LLSD& /*info*/)
{
if (!mInitialized)
{
if (!gInventory.isInventoryUsable())
{
return;
}
initCategory();
LLViewerInventoryCategory* category = gInventory.getCategory(sFolderID);
if (!category)
{
return;
}
const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
LLViewerInventoryCategory* category_cof = gInventory.getCategory(cof);
if (!category_cof)
{
return;
}
gInventory.addObserver(mCategoriesObserver);
mCategoriesObserver->addCategory(sFolderID, boost::bind(&FSFloaterWearableFavorites::updateList, this, sFolderID));
mCategoriesObserver->addCategory(cof, boost::bind(&FSFloaterWearableFavorites::updateList, this, sFolderID));
category->fetch();
mItemsList->setSortOrder((LLWearableItemsList::ESortOrder)gSavedSettings.getU32("FSWearableFavoritesSortOrder"));
updateList(sFolderID);
mItemsList->setDADCallback(boost::bind(&FSFloaterWearableFavorites::onItemDAD, this, _1));
mInitialized = true;
}
}
//virtual
void FSFloaterWearableFavorites::draw()
{
LLFloater::draw();
mRemoveItemBtn->setEnabled(mItemsList->numSelected() > 0);
}
//virtual
BOOL FSFloaterWearableFavorites::handleKeyHere(KEY key, MASK mask)
{
if (FSCommon::isFilterEditorKeyCombo(key, mask))
{
mFilterEditor->setFocus(TRUE);
return TRUE;
}
return LLFloater::handleKeyHere(key, mask);
}
void FSFloaterWearableFavorites::initCategory()
{
LLUUID fs_favs_id;
LLUUID fs_root_cat_id = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER);
if (!fs_root_cat_id.isNull())
{
LLInventoryModel::item_array_t* items;
LLInventoryModel::cat_array_t* cats;
gInventory.getDirectDescendentsOf(fs_root_cat_id, cats, items);
if (cats)
{
for (LLInventoryModel::cat_array_t::iterator it = cats->begin(); it != cats->end(); ++it)
{
if ((*it)->getName() == FS_WEARABLE_FAVORITES_FOLDER)
{
fs_favs_id = (*it)->getUUID();
break;
}
}
}
}
else
{
fs_root_cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER);
}
if (fs_favs_id.isNull())
{
fs_favs_id = gInventory.createNewCategory(fs_root_cat_id, LLFolderType::FT_NONE, FS_WEARABLE_FAVORITES_FOLDER);
}
sFolderID = fs_favs_id;
}
//static
LLUUID FSFloaterWearableFavorites::getFavoritesFolder()
{
if (sFolderID.notNull())
{
return sFolderID;
}
LLUUID fs_root_cat_id = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER);
if (!fs_root_cat_id.isNull())
{
LLInventoryModel::item_array_t* items;
LLInventoryModel::cat_array_t* cats;
gInventory.getDirectDescendentsOf(fs_root_cat_id, cats, items);
if (cats)
{
for (LLInventoryModel::cat_array_t::iterator it = cats->begin(); it != cats->end(); ++it)
{
if ((*it)->getName() == FS_WEARABLE_FAVORITES_FOLDER)
{
sFolderID = (*it)->getUUID();
break;
}
}
}
}
return sFolderID;
}
void FSFloaterWearableFavorites::updateList(const LLUUID& folder_id)
{
mItemsList->updateList(folder_id);
if (gInventory.isCategoryComplete(folder_id))
{
mItemsList->setNoItemsCommentText(getString("empty_list")); // Have to reset it here because LLWearableItemsList::updateList might override it
}
}
void FSFloaterWearableFavorites::onItemDAD(const LLUUID& item_id)
{
link_inventory_object(sFolderID, item_id, LLPointer<LLInventoryCallback>(NULL));
}
void FSFloaterWearableFavorites::handleRemove()
{
uuid_vec_t selected_item_ids;
mItemsList->getSelectedUUIDs(selected_item_ids);
for (uuid_vec_t::iterator it = selected_item_ids.begin(); it != selected_item_ids.end(); ++it)
{
remove_inventory_item(*it, LLPointer<LLInventoryCallback>(NULL));
}
}
void FSFloaterWearableFavorites::onFilterEdit(const std::string& search_string)
{
mItemsList->setFilterSubString(search_string);
mItemsList->setNoItemsCommentText(getString("empty_list"));
}
void FSFloaterWearableFavorites::onOptionsMenuItemClicked(const LLSD& userdata)
{
const std::string action = userdata.asString();
if (action == "sort_by_name")
{
mItemsList->setSortOrder(LLWearableItemsList::E_SORT_BY_NAME);
gSavedSettings.setU32("FSWearableFavoritesSortOrder", LLWearableItemsList::E_SORT_BY_NAME);
}
else if (action == "sort_by_most_recent")
{
mItemsList->setSortOrder(LLWearableItemsList::E_SORT_BY_MOST_RECENT);
gSavedSettings.setU32("FSWearableFavoritesSortOrder", LLWearableItemsList::E_SORT_BY_MOST_RECENT);
}
else if (action == "sort_by_type_name")
{
mItemsList->setSortOrder(LLWearableItemsList::E_SORT_BY_TYPE_NAME);
gSavedSettings.setU32("FSWearableFavoritesSortOrder", LLWearableItemsList::E_SORT_BY_TYPE_NAME);
}
}
bool FSFloaterWearableFavorites::onOptionsMenuItemChecked(const LLSD& userdata)
{
const std::string action = userdata.asString();
if (action == "sort_by_name")
{
return mItemsList->getSortOrder() == LLWearableItemsList::E_SORT_BY_NAME;
}
else if (action == "sort_by_most_recent")
{
return mItemsList->getSortOrder() == LLWearableItemsList::E_SORT_BY_MOST_RECENT;
}
else if (action == "sort_by_type_name")
{
return mItemsList->getSortOrder() == LLWearableItemsList::E_SORT_BY_TYPE_NAME;
}
return false;
}
void FSFloaterWearableFavorites::onDoubleClick()
{
LLUUID selected_item_id = mItemsList->getSelectedUUID();
if (selected_item_id.notNull())
{
uuid_vec_t ids;
ids.push_back(selected_item_id);
LLViewerInventoryItem* item = gInventory.getItem(selected_item_id);
if (get_is_item_worn(selected_item_id))
{
if ((item->getType() == LLAssetType::AT_CLOTHING && (!RlvActions::isRlvEnabled() || gRlvWearableLocks.canRemove(item))) ||
(item->getType() == LLAssetType::AT_OBJECT) && (!RlvActions::isRlvEnabled() || gRlvAttachmentLocks.canDetach(item)))
{
LLAppearanceMgr::instance().removeItemsFromAvatar(ids);
}
}
else
{
if (item->getType() == LLAssetType::AT_BODYPART && (!RlvActions::isRlvEnabled() || (gRlvWearableLocks.canWear(item) & RLV_WEAR_REPLACE) == RLV_WEAR_REPLACE))
{
wear_multiple(ids, true);
}
else if (item->getType() == LLAssetType::AT_CLOTHING && LLAppearanceMgr::instance().canAddWearables(ids) && (!RlvActions::isRlvEnabled() || (gRlvWearableLocks.canWear(item) & RLV_WEAR_ADD) == RLV_WEAR_ADD))
{
wear_multiple(ids, false);
}
else if (item->getType() == LLAssetType::AT_OBJECT && LLAppearanceMgr::instance().canAddWearables(ids) && (!RlvActions::isRlvEnabled() || (gRlvAttachmentLocks.canAttach(item) & RLV_WEAR_ADD) == RLV_WEAR_ADD))
{
wear_multiple(ids, false);
}
}
}
}

View File

@ -0,0 +1,110 @@
/**
* @file fsfloaterwearablefavorites.h
* @brief Class for the favorite wearables floater
*
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (c) 2018 Ansariel Hiller @ Second Life
*
* 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
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#ifndef FS_FLOATERWEARABLEFAVORITES_H
#define FS_FLOATERWEARABLEFAVORITES_H
#include "llfloater.h"
#include "llwearableitemslist.h"
class LLButton;
class LLFilterEditor;
class LLMenuButton;
class LLInventoryCategoriesObserver;
class FSWearableFavoritesItemsList : public LLWearableItemsList
{
public:
struct Params : public LLInitParam::Block<Params, LLWearableItemsList::Params>
{
Params()
{}
};
virtual ~FSWearableFavoritesItemsList() {}
/* virtual */ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
typedef boost::signals2::signal<void(const LLUUID& id)> item_dad_callback_t;
boost::signals2::connection setDADCallback(const item_dad_callback_t::slot_type& cb)
{
return mDADSignal.connect(cb);
}
protected:
friend class LLUICtrlFactory;
FSWearableFavoritesItemsList(const Params&);
item_dad_callback_t mDADSignal;
};
class FSFloaterWearableFavorites : public LLFloater
{
public:
FSFloaterWearableFavorites(const LLSD& key);
virtual ~FSFloaterWearableFavorites();
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& info);
/*virtual*/ void draw();
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ bool hasAccelerators() const { return true; }
static LLUUID getFavoritesFolder();
private:
void initCategory();
void updateList(const LLUUID& folder_id);
void onItemDAD(const LLUUID& item_id);
void handleRemove();
void onFilterEdit(const std::string& search_string);
void onDoubleClick();
void onOptionsMenuItemClicked(const LLSD& userdata);
bool onOptionsMenuItemChecked(const LLSD& userdata);
bool mInitialized;
boost::signals2::connection mDADCallbackConnection;
LLInventoryCategoriesObserver* mCategoriesObserver;
FSWearableFavoritesItemsList* mItemsList;
LLButton* mRemoveItemBtn;
LLFilterEditor* mFilterEditor;
LLMenuButton* mOptionsButton;
LLHandle<LLView> mOptionsMenuHandle;
static LLUUID sFolderID;
};
#endif // FS_FLOATERWEARABLEFAVORITES_H

View File

@ -99,6 +99,7 @@
#endif
// </FS:Zi>
#include "fsfloaterplacedetails.h"
#include "fsfloaterwearablefavorites.h"
#include "llviewerattachmenu.h"
#include "llresmgr.h"
@ -1374,6 +1375,13 @@ BOOL LLInvFVBridge::isProtectedFolder(bool ignore_setting /*= false*/) const
return TRUE;
}
if ((mUUID == FSFloaterWearableFavorites::getFavoritesFolder()
|| model->isObjectDescendentOf(mUUID, FSFloaterWearableFavorites::getFavoritesFolder()))
&& gSavedPerAccountSettings.getBOOL("ProtectWearableFavoritesFolders"))
{
return TRUE;
}
return FALSE;
}
// </FS:TT>
@ -5653,9 +5661,11 @@ bool LLFolderBridge::isProtected() const
{
static LLCachedControl<bool> protectAOFolders(gSavedPerAccountSettings, "ProtectAOFolders");
static LLCachedControl<bool> protectBridgeFolder(gSavedPerAccountSettings, "ProtectBridgeFolder");
static LLCachedControl<bool> WearableFavoritesprotectBridgeFolder(gSavedPerAccountSettings, "ProtectWearableFavoritesFolders");
return ((mUUID == AOEngine::instance().getAOFolder() && protectAOFolders) ||
(mUUID == FSLSLBridge::instance().getBridgeFolder() && protectBridgeFolder));
(mUUID == FSLSLBridge::instance().getBridgeFolder() && protectBridgeFolder) ||
(mUUID == FSFloaterWearableFavorites::getFavoritesFolder() && WearableFavoritesprotectBridgeFolder));
}
// </FS:Ansariel>

View File

@ -94,6 +94,7 @@
// Firestorm includes
#include "aoengine.h"
#include "fsfloaterwearablefavorites.h"
#include "fslslbridge.h"
BOOL LLInventoryState::sWearNewClothing = FALSE;
@ -640,6 +641,9 @@ BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
||
(model->isObjectDescendentOf(id, FSLSLBridge::instance().getBridgeFolder())
&& gSavedPerAccountSettings.getBOOL("ProtectBridgeFolder"))
||
(model->isObjectDescendentOf(id, FSFloaterWearableFavorites::getFavoritesFolder())
&& gSavedPerAccountSettings.getBOOL("ProtectWearableFavoritesFolders"))
)
{
return FALSE;
@ -707,6 +711,9 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
||
((id == FSLSLBridge::instance().getBridgeFolder() || model->isObjectDescendentOf(id, FSLSLBridge::instance().getBridgeFolder()))
&& gSavedPerAccountSettings.getBOOL("ProtectBridgeFolder"))
||
((id == FSFloaterWearableFavorites::getFavoritesFolder() || model->isObjectDescendentOf(id, FSFloaterWearableFavorites::getFavoritesFolder()))
&& gSavedPerAccountSettings.getBOOL("ProtectWearableFavoritesFolders"))
)
{
return FALSE;
@ -762,6 +769,9 @@ BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
||
((id == FSLSLBridge::instance().getBridgeFolder() || model->isObjectDescendentOf(id, FSLSLBridge::instance().getBridgeFolder()))
&& gSavedPerAccountSettings.getBOOL("ProtectBridgeFolder"))
||
((id == FSFloaterWearableFavorites::getFavoritesFolder() || model->isObjectDescendentOf(id, FSFloaterWearableFavorites::getFavoritesFolder()))
&& gSavedPerAccountSettings.getBOOL("ProtectWearableFavoritesFolders"))
)
{
return FALSE;

View File

@ -64,11 +64,11 @@
#include "rlvhandler.h"
#include "rlvlocks.h"
// [/RLVa:KB]
//-TT Patch: ReplaceWornItemsOnly
// <FS:TT> Patch: ReplaceWornItemsOnly
#include "llviewerobjectlist.h"
#include "llviewerobject.h"
#include "llgesturemgr.h"
//-TT
// </FS:TT>
//#define DIFF_INVENTORY_FILES
#ifdef DIFF_INVENTORY_FILES
@ -76,6 +76,7 @@
#endif
#include "aoengine.h"
#include "fsfloaterwearablefavorites.h"
#include "fslslbridge.h"
#ifdef OPENSIM
#include "llviewernetwork.h"
@ -1310,7 +1311,9 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item,
if ((isObjectDescendentOf(item->getUUID(), AOEngine::instance().getAOFolder())
&& gSavedPerAccountSettings.getBOOL("ProtectAOFolders")) ||
(isObjectDescendentOf(item->getUUID(), FSLSLBridge::instance().getBridgeFolder())
&& gSavedPerAccountSettings.getBOOL("ProtectBridgeFolder")))
&& gSavedPerAccountSettings.getBOOL("ProtectBridgeFolder")) ||
(isObjectDescendentOf(item->getUUID(), FSFloaterWearableFavorites::getFavoritesFolder())
&& gSavedPerAccountSettings.getBOOL("ProtectWearableFavoritesFolders")))
{
LL_INFOS("Inventory") << "Cannot move item because it is descendent of a protected folder" << LL_ENDL;
return;
@ -1352,7 +1355,9 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
if ((isObjectDescendentOf(cat->getUUID(), AOEngine::instance().getAOFolder())
&& gSavedPerAccountSettings.getBOOL("ProtectAOFolders")) ||
(isObjectDescendentOf(cat->getUUID(), FSLSLBridge::instance().getBridgeFolder())
&& gSavedPerAccountSettings.getBOOL("ProtectBridgeFolder")))
&& gSavedPerAccountSettings.getBOOL("ProtectBridgeFolder")) ||
(isObjectDescendentOf(cat->getUUID(), FSFloaterWearableFavorites::getFavoritesFolder())
&& gSavedPerAccountSettings.getBOOL("ProtectWearableFavoritesFolders")))
{
LL_INFOS("Inventory") << "Cannot move category because it is descendent of a protected folder" << LL_ENDL;
return;

View File

@ -194,6 +194,7 @@
#include "fsfloatervoicecontrols.h"
#include "fsfloatervolumecontrols.h"
#include "fsfloatervramusage.h"
#include "fsfloaterwearablefavorites.h"
#include "fsmoneytracker.h"
#include "fspanelclassified.h"
#include "lggbeamcolormapfloater.h"
@ -466,6 +467,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("fs_teleporthistory", "floater_fs_teleporthistory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterTeleportHistory>);
LLFloaterReg::add("fs_voice_controls", "floater_fs_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterVoiceControls>);
LLFloaterReg::add("fs_volume_controls", "floater_fs_volume_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterVolumeControls>);
LLFloaterReg::add("fs_wearable_favorites", "floater_fs_wearable_favorites.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterWearableFavorites>);
LLFloaterReg::add("imcontacts", "floater_fs_contacts.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterContacts>);
LLFloaterReg::add("lgg_beamcolormap", "floater_beamcolor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<lggBeamColorMapFloater>);
LLFloaterReg::add("lgg_beamshape", "floater_beamshape.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<lggBeamMapFloater>);

View File

@ -950,7 +950,14 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
// [/RLVa:KB]
} // for
bool standalone = mParent ? mParent->isStandalone() : false;
// <FS:Ansariel> Standalone check doesn't make sense here as the context
// menu is only shown if standalone is true. If not, this
// method isn't called at all and it is assumed you provide
// your own right-click handler (LLWearableItemsList::ContextMenu
// is only used in LLWearableItemsList::onRightClick handler
// method which in return is only set as event handler if
// standalone is true).
bool standalone = /*mParent ? mParent->isStandalone() :*/ false;
bool wear_add_visible = mask & (MASK_CLOTHING|MASK_ATTACHMENT) && n_worn == 0 && can_be_worn && (n_already_worn != 0 || mask & MASK_ATTACHMENT);
// *TODO: eliminate multiple traversals over the menu items

View File

@ -793,6 +793,7 @@ with the same filename but different name
<texture name="block_list" file_name="toolbar_icons/blocklist.png" preload="true" />
<texture name="resync_animations" file_name="toolbar_icons/resync_animations.png" preload="true" />
<texture name="Group_Titles_Icon" file_name="toolbar_icons/group_titles.png" preload="true" />
<texture name="Wearable_Favorites_Icon" file_name="toolbar_icons/wearable_favorites.png" preload="true" />
<texture name="skin ansastorm blood" file_name="skinspreview/ansa_blood.jpg" preload="true" />
<texture name="skin ansastorm bright blue" file_name="skinspreview/ansa_blue.jpg" preload="true" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="floater_fs_wearable_favorites" title="Kleidungsfavoriten">
<floater.string name="empty_list">
Kleidung oder Objekt hier hinziehen, um zur Liste hinzuzufügen.
</floater.string>
<floater.string name="search_no_items">
Keine treffenden Objekte gefunden.
</floater.string>
<panel name="buttons_panel">
<filter_editor label="Kleidungsfavoriten filtern" name="wearable_filter_input"/>
<menu_button name="options_btn" tool_tip="Kleidungsfavoriten-Optionen"/>
<button name="remove_btn" tool_tip="Kleidung aus Kleidungsfavoriten löschen"/>
</panel>
</floater>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<toggleable_menu name="menu_wearable_favorites">
<menu_item_check label="Sortierung nach Name..." name="sort_by_name"/>
<menu_item_check label="Sortierung nach Aktualität..." name="sort_by_most_recent"/>
<menu_item_check label="Sortierung nach Typname..." name="sort_by_type_name"/>
</toggleable_menu>

View File

@ -8,6 +8,7 @@
<menu_item_call label="L$ kaufen" name="Buy and Sell L$"/>
<menu_item_check label="Inventar" name="Inventory"/>
<menu_item_check label="Inventar" name="ShowSidetrayInventory"/>
<menu_item_check label="Kleidungsfavoriten" name="WearableFavorites"/>
<menu_item_call label="Auswahlen" name="Picks"/>
<menu_item_call label="Erlebnisse" name="Experiences"/>
<menu_item_call label="Profil" name="Profile"/>

View File

@ -5827,6 +5827,9 @@ Setzen Sie den Editorpfad in Anführungszeichen
<string name="Command_Group_Titles_Label">
Gruppentitel
</string>
<string name="Command_Wearable_Favorites_Label">
Kleidungsfavoriten
</string>
<string name="Command_Appearance_Tooltip">
Avatar ändern
</string>
@ -6007,6 +6010,9 @@ Setzen Sie den Editorpfad in Anführungszeichen
<string name="Command_Group_Titles_Tooltip">
Aktuellen Gruppentitel ändern
</string>
<string name="Command_Wearable_Favorites_Tooltip">
Liste der Kleidungsfavoriten öffnen
</string>
<string name="Toolbar_Bottom_Tooltip">
gegenwärtig in der unteren Symbolleiste
</string>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
positioning="cascading"
can_close="true"
can_resize="true"
height="350"
help_topic="fs_wearable_favorites"
min_height="250"
min_width="210"
layout="topleft"
name="floater_fs_wearable_favorites"
save_rect="true"
save_visibility="true"
single_instance="true"
reuse_instance="true"
title="Favorite Wearables"
width="310">
<floater.string name="empty_list">
Drag wearable items here to add to list.
</floater.string>
<floater.string name="search_no_items">
No matching items found.
</floater.string>
<panel
follows="left|top|right"
height="27"
layout="topleft"
left="2"
name="buttons_panel"
right="-1"
top="2">
<filter_editor
follows="left|top|right"
height="23"
layout="topleft"
left="3"
label="Filter Wearables"
max_length_chars="300"
name="wearable_filter_input"
top="1"
right="-70" />
<menu_button
follows="right"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Conv_toolbar_sort"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
left_pad="2"
name="options_btn"
tool_tip="Wearable favorites options"
top_delta="0"
width="31" />
<button
follows="right"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="TrashItem_Off"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
left_pad="2"
layout="topleft"
name="remove_btn"
tool_tip="Remove wearable from favorites list"
top_delta="0"
width="31"/>
</panel>
<panel
layout="topleft"
follows="all"
name="panel_fs_wearable_favorites"
top="32"
left="2"
bottom="-2"
right="-1">
<fs_wearable_favorites_items_list
layout="topleft"
follows="all"
name="favorites_list"
multi_select="true"
standalone="true"
top="0"
left="0"
bottom="-1"
right="-1"
worn_indication_enabled="true" />
</panel>
</floater>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<toggleable_menu name="menu_wearable_favorites">
<menu_item_check
label="Sort by name..."
name="sort_by_name">
<on_click
function="FavWearables.Action"
parameter="sort_by_name"/>
<on_check
function="FavWearables.CheckAction"
parameter="sort_by_name"/>
</menu_item_check>
<menu_item_check
label="Sort by most recent..."
name="sort_by_most_recent">
<on_click
function="FavWearables.Action"
parameter="sort_by_most_recent"/>
<on_check
function="FavWearables.CheckAction"
parameter="sort_by_most_recent"/>
</menu_item_check>
<menu_item_check
label="Sort by type name..."
name="sort_by_type_name">
<on_click
function="FavWearables.Action"
parameter="sort_by_type_name"/>
<on_check
function="FavWearables.CheckAction"
parameter="sort_by_type_name"/>
</menu_item_check>
</toggleable_menu>

View File

@ -64,6 +64,17 @@
parameter="inventory" />
</menu_item_check>
<menu_item_check
label="Favorite Wearables"
name="WearableFavorites">
<menu_item_check.on_click
function="Floater.Toggle"
parameter="fs_wearable_favorites" />
<menu_item_check.on_check
function="Floater.Visible"
parameter="fs_wearable_favorites" />
</menu_item_check>
<menu_item_call
label="Picks"
name="Picks">

View File

@ -2630,6 +2630,7 @@ Try enclosing path to the editor with double quotes.
<string name="Command_ResyncAnimations_Label">Resync animations</string>
<string name="Command_RegionTracker_Label">Region Tracker</string>
<string name="Command_Group_Titles_Label">Group Titles</string>
<string name="Command_Wearable_Favorites_Label">Favorite Wearables</string>
<string name="Command_AboutLand_Tooltip">Information about the land you're visiting</string>
<string name="Command_Appearance_Tooltip">Change your avatar</string>
@ -2693,6 +2694,7 @@ Try enclosing path to the editor with double quotes.
<string name="Command_ResyncAnimations_Tooltip">Synchronizes avatar animations</string>
<string name="Command_RegionTracker_Tooltip">Track various regions status</string>
<string name="Command_Group_Titles_Tooltip">Change active group tag</string>
<string name="Command_Wearable_Favorites_Tooltip">Open the list of favorite wearables</string>
<string name="Toolbar_Bottom_Tooltip">currently in your bottom toolbar</string>
<string name="Toolbar_Left_Tooltip" >currently in your left toolbar</string>