FIRE-20809: Improve HUD management
parent
2e3d7676f5
commit
50d1556d3b
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 |
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue