# Conflicts:
#	indra/llui/llfolderviewitem.cpp
#	indra/llui/llfolderviewitem.h
#	indra/newview/llappviewer.cpp
#	indra/newview/llinventorybridge.cpp
#	indra/newview/llinventorypanel.cpp
#	indra/newview/lloutfitgallery.cpp
#	indra/newview/llpanelmaininventory.cpp
#	indra/newview/llpanelmaininventory.h
#	indra/newview/llpanelprofile.cpp
#	indra/newview/llsidepanelinventory.cpp
#	indra/newview/llsidepanelinventory.h
#	indra/newview/llviewerfloaterreg.cpp
#	indra/newview/skins/default/textures/textures.xml
#	indra/newview/skins/default/xui/en/floater_my_inventory.xml
#	indra/newview/skins/default/xui/en/floater_simple_snapshot.xml
#	indra/newview/skins/default/xui/en/menu_inventory.xml
#	indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
#	indra/newview/skins/default/xui/en/menu_viewer.xml
#	indra/newview/skins/default/xui/en/panel_main_inventory.xml
#	indra/newview/skins/default/xui/en/sidepanel_inventory.xml
master
Ansariel 2023-02-24 14:28:21 +01:00
commit 61042ad1c7
64 changed files with 2989 additions and 1310 deletions

View File

@ -251,6 +251,8 @@ public:
void dumpSelectionInformation();
virtual S32 notify(const LLSD& info) ;
void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; }
bool useLabelSuffix() { return mUseLabelSuffix; }
virtual void updateMenu();

View File

@ -117,6 +117,7 @@ LLFolderViewItem::Params::Params()
icon_width("icon_width", 0),
text_pad("text_pad", 0),
text_pad_right("text_pad_right", 0),
single_folder_mode("single_folder_mode", false),
arrow_size("arrow_size", 0),
max_folder_item_overlap("max_folder_item_overlap", 0),
// <FS:Ansariel> Inventory specials
@ -158,6 +159,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mTextPad(p.text_pad),
mTextPadRight(p.text_pad_right),
mArrowSize(p.arrow_size),
mSingleFolderMode(p.single_folder_mode),
mMaxFolderItemOverlap(p.max_folder_item_overlap),
// <FS:Ansariel> Inventory specials
mForInventory(p.for_inventory),
@ -970,7 +972,10 @@ void LLFolderViewItem::draw()
getViewModelItem()->update();
drawOpenFolderArrow(default_params, sFgColor);
if(!mSingleFolderMode)
{
drawOpenFolderArrow(default_params, sFgColor);
}
drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
@ -1945,7 +1950,14 @@ void LLFolderViewFolder::toggleOpen()
// Force a folder open or closed
void LLFolderViewFolder::setOpen(BOOL openitem)
{
setOpenArrangeRecursively(openitem);
if(mSingleFolderMode)
{
getViewModelItem()->navigateToFolder();
}
else
{
setOpenArrangeRecursively(openitem);
}
}
void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse)
@ -2148,7 +2160,8 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
}
if( !handled )
{
if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad)
if((mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad)
&& !mSingleFolderMode)
{
toggleOpen();
handled = TRUE;
@ -2166,6 +2179,11 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
{
BOOL handled = FALSE;
if(mSingleFolderMode)
{
getViewModelItem()->navigateToFolder();
return TRUE;
}
if( isOpen() )
{
handled = childrenHandleDoubleClick( x, y, mask ) != NULL;

View File

@ -72,6 +72,7 @@ public:
text_pad_right,
arrow_size,
max_folder_item_overlap;
Optional<bool> single_folder_mode;
// <FS:Ansariel> Inventory specials
Optional<bool> for_inventory;
@ -125,6 +126,7 @@ protected:
mIsMouseOverTitle,
mAllowWear,
mAllowDrop,
mSingleFolderMode,
mSelectPending,
mIsItemCut;

View File

@ -160,6 +160,8 @@ public:
virtual void openItem( void ) = 0;
virtual void closeItem( void ) = 0;
virtual void selectItem(void) = 0;
virtual void navigateToFolder() = 0;
virtual BOOL isItemWearable() const { return FALSE; }

View File

@ -597,13 +597,13 @@ void LLMenuItemGL::onVisibilityChange(BOOL new_visibility)
//
// This class represents a separator.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LLMenuItemSeparatorGL::Params::Params()
{
}
LLMenuItemSeparatorGL::LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p) :
LLMenuItemGL( p )
{
if (p.on_visible.isProvided())
{
mVisibleSignal.connect(initEnableCallback(p.on_visible));
}
}
//virtual
@ -620,6 +620,15 @@ void LLMenuItemSeparatorGL::draw( void )
gl_line_2d( PAD, y, getRect().getWidth() - PAD, y );
}
void LLMenuItemSeparatorGL::buildDrawLabel( void )
{
if (mVisibleSignal.num_slots() > 0)
{
bool visible = mVisibleSignal(this, LLSD());
setVisible(visible);
}
}
BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask)
{
LLMenuGL* parent_menu = getMenu();

View File

@ -235,7 +235,9 @@ class LLMenuItemSeparatorGL : public LLMenuItemGL
public:
struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
{
Params();
Optional<EnableCallbackParam > on_visible;
Params() : on_visible("on_visible")
{}
};
LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p = LLMenuItemSeparatorGL::Params());
@ -244,7 +246,12 @@ public:
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
virtual void buildDrawLabel();
/*virtual*/ U32 getNominalHeight( void ) const;
private:
enable_signal_t mVisibleSignal;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -348,6 +348,7 @@ set(viewer_SOURCE_FILES
llfloaterbuyland.cpp
llfloatercamera.cpp
llfloatercamerapresets.cpp
llfloaterchangeitemthumbnail.cpp
llfloaterchatvoicevolume.cpp
llfloaterclassified.cpp
llfloatercolorpicker.cpp
@ -404,7 +405,7 @@ set(viewer_SOURCE_FILES
llfloateroutfitphotopreview.cpp
llfloaterobjectweights.cpp
llfloateropenobject.cpp
llfloatersimpleoutfitsnapshot.cpp
llfloatersimplesnapshot.cpp
llfloaterpathfindingcharacters.cpp
llfloaterpathfindingconsole.cpp
llfloaterpathfindinglinksets.cpp
@ -1130,6 +1131,7 @@ set(viewer_HEADER_FILES
llfloaterbuycurrencyhtml.h
llfloaterbuyland.h
llfloatercamerapresets.h
llfloaterchangeitemthumbnail.h
llfloatercamera.h
llfloaterchatvoicevolume.h
llfloaterclassified.h
@ -1190,7 +1192,7 @@ set(viewer_HEADER_FILES
llfloateroutfitphotopreview.h
llfloaterobjectweights.h
llfloateropenobject.h
llfloatersimpleoutfitsnapshot.h
llfloatersimplesnapshot.h
llfloaterpathfindingcharacters.h
llfloaterpathfindingconsole.h
llfloaterpathfindinglinksets.h

View File

@ -229,7 +229,7 @@
#include "llcommandlineparser.h"
#include "llfloatermemleak.h"
#include "llfloaterreg.h"
#include "llfloatersimpleoutfitsnapshot.h"
#include "llfloatersimplesnapshot.h"
#include "llfloatersnapshot.h"
#include "llsidepanelinventory.h"
#include "llatmosphere.h"
@ -1798,7 +1798,7 @@ bool LLAppViewer::doFrame()
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot")
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
LLFloaterSimpleOutfitSnapshot::update();
LLFloaterSimpleSnapshot::update();
gGLActive = FALSE;
}
}

View File

@ -114,6 +114,7 @@ public:
virtual void previewItem( void );
virtual void selectItem(void) { }
virtual void showProperties(void);
virtual void navigateToFolder() {}
// Methods used in sorting (see LLConversationSort::operator())
EConversationType const getType() const { return mConvType; }

View File

@ -0,0 +1,558 @@
/**
* @file llfloaterchangeitemthumbnail.cpp
* @brief LLFloaterChangeItemThumbnail class implementation
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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 "llfloaterchangeitemthumbnail.h"
#include "llbutton.h"
#include "llclipboard.h"
#include "lliconctrl.h"
#include "llinventoryfunctions.h"
#include "llinventoryicon.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
#include "llfloaterreg.h"
#include "llfloatersimplesnapshot.h"
#include "lllineeditor.h"
#include "llnotificationsutil.h"
#include "lltextbox.h"
#include "lltexturectrl.h"
#include "llthumbnailctrl.h"
#include "llviewerfoldertype.h"
#include "llviewermenufile.h"
#include "llviewerobjectlist.h"
#include "llwindow.h"
#include "lltrans.h"
class LLThumbnailImagePicker : public LLFilePickerThread
{
public:
LLThumbnailImagePicker(const LLUUID &item_id);
LLThumbnailImagePicker(const LLUUID &item_id, const LLUUID &task_id);
~LLThumbnailImagePicker();
void notify(const std::vector<std::string>& filenames) override;
private:
LLUUID mInventoryId;
LLUUID mTaskId;
};
LLThumbnailImagePicker::LLThumbnailImagePicker(const LLUUID &item_id)
: LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE)
, mInventoryId(item_id)
{
}
LLThumbnailImagePicker::LLThumbnailImagePicker(const LLUUID &item_id, const LLUUID &task_id)
: LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE)
, mInventoryId(item_id)
, mTaskId(task_id)
{
}
LLThumbnailImagePicker::~LLThumbnailImagePicker()
{
}
void LLThumbnailImagePicker::notify(const std::vector<std::string>& filenames)
{
if (filenames.empty())
{
return;
}
std::string file_path = filenames[0];
if (file_path.empty())
{
return;
}
LLFloaterSimpleSnapshot::uploadThumbnail(file_path, mInventoryId, mTaskId);
}
LLFloaterChangeItemThumbnail::LLFloaterChangeItemThumbnail(const LLSD& key)
: LLFloater(key)
, mObserverInitialized(false)
, mTooltipState(TOOLTIP_NONE)
{
}
LLFloaterChangeItemThumbnail::~LLFloaterChangeItemThumbnail()
{
gInventory.removeObserver(this);
removeVOInventoryListener();
}
BOOL LLFloaterChangeItemThumbnail::postBuild()
{
mItemNameText = getChild<LLUICtrl>("item_name");
mItemTypeIcon = getChild<LLIconCtrl>("item_type_icon");
mThumbnailCtrl = getChild<LLThumbnailCtrl>("item_thumbnail");
mToolTipTextBox = getChild<LLTextBox>("tooltip_text");
LLSD tooltip_text;
mToolTipTextBox->setValue(tooltip_text);
LLButton *upload_local = getChild<LLButton>("upload_local");
upload_local->setClickedCallback(onUploadLocal, (void*)this);
upload_local->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_UPLOAD_LOCAL));
upload_local->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_UPLOAD_LOCAL));
LLButton *upload_snapshot = getChild<LLButton>("upload_snapshot");
upload_snapshot->setClickedCallback(onUploadSnapshot, (void*)this);
upload_snapshot->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_UPLOAD_SNAPSHOT));
upload_snapshot->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_UPLOAD_SNAPSHOT));
LLButton *use_texture = getChild<LLButton>("use_texture");
use_texture->setClickedCallback(onUseTexture, (void*)this);
use_texture->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_USE_TEXTURE));
use_texture->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_USE_TEXTURE));
mCopyToClipboardBtn = getChild<LLButton>("copy_to_clipboard");
mCopyToClipboardBtn->setClickedCallback(onCopyToClipboard, (void*)this);
mCopyToClipboardBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_COPY_TO_CLIPBOARD));
mCopyToClipboardBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_COPY_TO_CLIPBOARD));
mPasteFromClipboardBtn = getChild<LLButton>("paste_from_clipboard");
mPasteFromClipboardBtn->setClickedCallback(onPasteFromClipboard, (void*)this);
mPasteFromClipboardBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_COPY_FROM_CLIPBOARD));
mPasteFromClipboardBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_COPY_FROM_CLIPBOARD));
mRemoveImageBtn = getChild<LLButton>("remove_image");
mRemoveImageBtn->setClickedCallback(onRemove, (void*)this);
mRemoveImageBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_REMOVE));
mRemoveImageBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_REMOVE));
return LLFloater::postBuild();
}
void LLFloaterChangeItemThumbnail::onOpen(const LLSD& key)
{
if (!key.has("item_id") && !key.isUUID())
{
closeFloater();
}
if (key.isUUID())
{
mItemId = key.asUUID();
}
else
{
mItemId = key["item_id"].asUUID();
mTaskId = key["task_id"].asUUID();
}
refreshFromInventory();
}
void LLFloaterChangeItemThumbnail::changed(U32 mask)
{
//LLInventoryObserver
if (mTaskId.notNull() || mItemId.isNull())
{
// Task inventory or not set up yet
return;
}
const std::set<LLUUID>& mChangedItemIDs = gInventory.getChangedIDs();
std::set<LLUUID>::const_iterator it;
for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++)
{
// set dirty for 'item profile panel' only if changed item is the item for which 'item profile panel' is shown (STORM-288)
if (*it == mItemId)
{
// if there's a change we're interested in.
if ((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
{
refreshFromInventory();
}
}
}
}
void LLFloaterChangeItemThumbnail::inventoryChanged(LLViewerObject* object,
LLInventoryObject::object_list_t* inventory,
S32 serial_num,
void* user_data)
{
//LLVOInventoryListener
refreshFromInventory();
}
LLInventoryObject* LLFloaterChangeItemThumbnail::getInventoryObject()
{
LLInventoryObject* obj = NULL;
if (mTaskId.isNull())
{
// it is in agent inventory
if (!mObserverInitialized)
{
gInventory.addObserver(this);
mObserverInitialized = true;
}
obj = gInventory.getObject(mItemId);
}
else
{
LLViewerObject* object = gObjectList.findObject(mTaskId);
if (object)
{
if (!mObserverInitialized)
{
registerVOInventoryListener(object, NULL);
mObserverInitialized = false;
}
obj = object->getInventoryObject(mItemId);
}
}
return obj;
}
void LLFloaterChangeItemThumbnail::refreshFromInventory()
{
LLInventoryObject* obj = getInventoryObject();
if (!obj)
{
closeFloater();
}
if (obj)
{
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
bool in_trash = (obj->getUUID() == trash_id) || gInventory.isObjectDescendentOf(obj->getUUID(), trash_id);
if (in_trash)
{
// Close properties when moving to trash
// Aren't supposed to view properties from trash
closeFloater();
}
else
{
refreshFromObject(obj);
}
}
else
{
closeFloater();
}
}
class LLIsOutfitTextureType : public LLInventoryCollectFunctor
{
public:
LLIsOutfitTextureType() {}
virtual ~LLIsOutfitTextureType() {}
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item);
};
bool LLIsOutfitTextureType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return item && (item->getType() == LLAssetType::AT_TEXTURE);
}
void LLFloaterChangeItemThumbnail::refreshFromObject(LLInventoryObject* obj)
{
LLUIImagePtr icon_img;
LLUUID thumbnail_id = obj->getThumbnailUUID();
LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(obj);
if (item)
{
// This floater probably shouldn't be be possible to open
// for imcomplete items
llassert(item->isFinished());
icon_img = LLInventoryIcon::getIcon(item->getType(), item->getInventoryType(), item->getFlags(), FALSE);
mRemoveImageBtn->setEnabled(thumbnail_id.notNull() && ((item->getActualType() != LLAssetType::AT_TEXTURE) || (item->getAssetUUID() != thumbnail_id)));
}
else
{
LLViewerInventoryCategory* cat = dynamic_cast<LLViewerInventoryCategory*>(obj);
if (cat)
{
icon_img = LLUI::getUIImage(LLViewerFolderType::lookupIconName(cat->getPreferredType(), true));
if (thumbnail_id.isNull() && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))
{
// Legacy support, check if there is an image inside
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
// Not LLIsOfAssetType, because we allow links
LLIsOutfitTextureType f;
gInventory.getDirectDescendentsOf(mItemId, cats, items, f);
if (1 == items.size())
{
LLViewerInventoryItem* item = items.front();
if (item && item->getIsLinkType())
{
item = item->getLinkedItem();
}
if (item)
{
LL_INFOS() << "Setting image from outfit as a thumbnail" << LL_ENDL;
thumbnail_id = item->getAssetUUID();
// per SL-19188, set this image as a thumbnail
cat->setThumbnailUUID(thumbnail_id);
// todo: needs to trigger send/update once server support is done
}
}
}
mRemoveImageBtn->setEnabled(thumbnail_id.notNull());
}
}
mItemTypeIcon->setImage(icon_img);
mItemNameText->setValue(obj->getName());
mThumbnailCtrl->setValue(thumbnail_id);
mCopyToClipboardBtn->setEnabled(thumbnail_id.notNull());
// todo: some elements might not support setting thumbnails
// since they already have them
}
void LLFloaterChangeItemThumbnail::onUploadLocal(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
(new LLThumbnailImagePicker(self->mItemId, self->mTaskId))->getFile();
LLFloater* floaterp = self->mPickerHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
floaterp = self->mSnapshotHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onUploadSnapshot(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLFloater* floaterp = self->mSnapshotHandle.get();
// Show the dialog
if (floaterp)
{
floaterp->openFloater();
}
else
{
LLSD key;
key["item_id"] = self->mItemId;
key["task_id"] = self->mTaskId;
LLFloaterSimpleSnapshot* snapshot_floater = (LLFloaterSimpleSnapshot*)LLFloaterReg::showInstance("simple_snapshot", key, true);
if (snapshot_floater)
{
self->addDependentFloater(snapshot_floater);
self->mSnapshotHandle = snapshot_floater->getHandle();
snapshot_floater->setOwner(self);
}
}
floaterp = self->mPickerHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onUseTexture(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLInventoryObject* obj = self->getInventoryObject();
if (obj)
{
self->showTexturePicker(obj->getThumbnailUUID());
}
LLFloater* floaterp = self->mSnapshotHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onCopyToClipboard(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLInventoryObject* obj = self->getInventoryObject();
if (obj)
{
LLClipboard::instance().addToClipboard(obj->getThumbnailUUID());
}
}
void LLFloaterChangeItemThumbnail::onPasteFromClipboard(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
std::vector<LLUUID> objects;
LLClipboard::instance().pasteFromClipboard(objects);
if (objects.size() > 0)
{
LLInventoryObject* obj = self->getInventoryObject();
if (obj)
{
obj->setThumbnailUUID(objects[0]);
// todo: need to trigger send/update once server support is done
}
}
}
void LLFloaterChangeItemThumbnail::onRemove(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLSD payload;
payload["item_id"] = self->mItemId;
payload["object_id"] = self->mTaskId;
LLNotificationsUtil::add("DeleteThumbnail", LLSD(), payload, boost::bind(&LLFloaterChangeItemThumbnail::onRemovalConfirmation, _1, _2, self->getHandle()));
}
// static
void LLFloaterChangeItemThumbnail::onRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFloater> handle)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0 && !handle.isDead() && !handle.get()->isDead())
{
LLFloaterChangeItemThumbnail* self = (LLFloaterChangeItemThumbnail*)handle.get();
LLInventoryObject* obj = self->getInventoryObject();
if (obj)
{
obj->setThumbnailUUID(LLUUID::null);
// todo: need to trigger send/update once server support is done
}
}
}
void LLFloaterChangeItemThumbnail::showTexturePicker(const LLUUID &thumbnail_id)
{
// show hourglass cursor when loading inventory window
getWindow()->setCursor(UI_CURSOR_WAIT);
LLFloater* floaterp = mPickerHandle.get();
// Show the dialog
if (floaterp)
{
floaterp->openFloater();
}
else
{
floaterp = new LLFloaterTexturePicker(
this,
thumbnail_id,
thumbnail_id,
thumbnail_id,
FALSE,
TRUE,
LLTrans::getString("TexturePickerOutfitHeader"), // "SELECT PHOTO", // <FS:Ansariel> Localizable floater header
PERM_NONE,
PERM_NONE,
PERM_NONE,
FALSE,
NULL);
mPickerHandle = floaterp->getHandle();
LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
if (texture_floaterp)
{
//texture_floaterp->setTextureSelectedCallback();
//texture_floaterp->setOnUpdateImageStatsCallback();
texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLUUID id)
{
if (op == LLTextureCtrl::TEXTURE_SELECT)
{
onTexturePickerCommit(id);
}
}
);
texture_floaterp->setLocalTextureEnabled(FALSE);
texture_floaterp->setBakeTextureEnabled(FALSE);
texture_floaterp->setCanApplyImmediately(false);
texture_floaterp->setCanApply(false, true);
addDependentFloater(texture_floaterp);
}
floaterp->openFloater();
}
floaterp->setFocus(TRUE);
}
void LLFloaterChangeItemThumbnail::onTexturePickerCommit(LLUUID id)
{
LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mPickerHandle.get();
LLInventoryObject* obj = getInventoryObject();
if (obj && floaterp)
{
obj->setThumbnailUUID(floaterp->getAssetID());
// todo: need to trigger send/update once server support is done
}
}
void LLFloaterChangeItemThumbnail::onButtonMouseEnter(LLUICtrl* button, const LLSD& param, EToolTipState state)
{
mTooltipState = state;
std::string tooltip_text;
std::string tooltip_name = "tooltip_" + button->getName();
if (hasString(tooltip_name))
{
tooltip_text = getString(tooltip_name);
}
mToolTipTextBox->setValue(tooltip_text);
}
void LLFloaterChangeItemThumbnail::onButtonMouseLeave(LLUICtrl* button, const LLSD& param, EToolTipState state)
{
if (mTooltipState == state)
{
mTooltipState = TOOLTIP_NONE;
LLSD tooltip_text;
mToolTipTextBox->setValue(tooltip_text);
}
}

View File

@ -0,0 +1,103 @@
/**
* @file llfloaterchangeitemthumbnail.h
* @brief LLFloaterChangeItemThumbnail class definition
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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$
*/
#ifndef LL_LLFLOATERCHANGEITEMTHUMBNAIL_H
#define LL_LLFLOATERCHANGEITEMTHUMBNAIL_H
#include "llfloater.h"
#include "llinventoryobserver.h"
#include "llvoinventorylistener.h"
class LLButton;
class LLIconCtrl;
class LLTextBox;
class LLThumbnailCtrl;
class LLUICtrl;
class LLViewerInventoryItem;
class LLFloaterChangeItemThumbnail : public LLFloater, public LLInventoryObserver, public LLVOInventoryListener
{
public:
LLFloaterChangeItemThumbnail(const LLSD& key);
~LLFloaterChangeItemThumbnail();
BOOL postBuild() override;
void onOpen(const LLSD& key) override;
void changed(U32 mask) override;
void inventoryChanged(LLViewerObject* object,
LLInventoryObject::object_list_t* inventory,
S32 serial_num,
void* user_data) override;
private:
LLInventoryObject* getInventoryObject();
void refreshFromInventory();
void refreshFromObject(LLInventoryObject* obj);
static void onUploadLocal(void*);
static void onUploadSnapshot(void*);
static void onUseTexture(void*);
static void onCopyToClipboard(void*);
static void onPasteFromClipboard(void*);
static void onRemove(void*);
static void onRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFloater> handle);
void showTexturePicker(const LLUUID &thumbnail_id);
void onTexturePickerCommit(LLUUID id);
enum EToolTipState
{
TOOLTIP_NONE,
TOOLTIP_UPLOAD_LOCAL,
TOOLTIP_UPLOAD_SNAPSHOT,
TOOLTIP_USE_TEXTURE,
TOOLTIP_COPY_TO_CLIPBOARD,
TOOLTIP_COPY_FROM_CLIPBOARD,
TOOLTIP_REMOVE,
};
void onButtonMouseEnter(LLUICtrl* button, const LLSD& param, EToolTipState state);
void onButtonMouseLeave(LLUICtrl* button, const LLSD& param, EToolTipState state);
bool mObserverInitialized;
EToolTipState mTooltipState;
LLUUID mItemId;
LLUUID mTaskId;
LLIconCtrl *mItemTypeIcon;
LLUICtrl *mItemNameText;
LLThumbnailCtrl *mThumbnailCtrl;
LLTextBox *mToolTipTextBox;
LLButton *mCopyToClipboardBtn;
LLButton *mPasteFromClipboardBtn;
LLButton *mRemoveImageBtn;
LLHandle<LLFloater> mPickerHandle;
LLHandle<LLFloater> mSnapshotHandle;
};
#endif // LL_LLFLOATERCHANGEITEMTHUMBNAIL_H

View File

@ -1,319 +0,0 @@
/**
* @file llfloatersimpleoutfitsnapshot.cpp
* @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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 "llfloatersimpleoutfitsnapshot.h"
#include "llfloaterreg.h"
#include "llimagefiltersmanager.h"
#include "llstatusbar.h" // can_afford_transaction()
#include "llnotificationsutil.h"
#include "llagentbenefits.h"
#include "llviewercontrol.h"
LLSimpleOutfitSnapshotFloaterView* gSimpleOutfitSnapshotFloaterView = NULL;
const S32 OUTFIT_SNAPSHOT_WIDTH = 256;
const S32 OUTFIT_SNAPSHOT_HEIGHT = 256;
static LLDefaultChildRegistry::Register<LLSimpleOutfitSnapshotFloaterView> r("simple_snapshot_outfit_floater_view");
///----------------------------------------------------------------------------
/// Class LLFloaterSimpleOutfitSnapshot::Impl
///----------------------------------------------------------------------------
LLSnapshotModel::ESnapshotFormat LLFloaterSimpleOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
{
return LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
}
LLSnapshotModel::ESnapshotLayerType LLFloaterSimpleOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
{
return LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
}
void LLFloaterSimpleOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
{
LLSnapshotLivePreview* previewp = getPreviewView();
updateResolution(floater);
if (previewp)
{
previewp->setSnapshotType(LLSnapshotModel::ESnapshotType::SNAPSHOT_TEXTURE);
previewp->setSnapshotFormat(LLSnapshotModel::ESnapshotFormat::SNAPSHOT_FORMAT_PNG);
previewp->setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType::SNAPSHOT_TYPE_COLOR);
}
}
std::string LLFloaterSimpleOutfitSnapshot::Impl::getSnapshotPanelPrefix()
{
return "panel_outfit_snapshot_";
}
void LLFloaterSimpleOutfitSnapshot::Impl::updateResolution(void* data)
{
LLFloaterSimpleOutfitSnapshot *view = (LLFloaterSimpleOutfitSnapshot *)data;
if (!view)
{
llassert(view);
return;
}
S32 width = OUTFIT_SNAPSHOT_WIDTH;
S32 height = OUTFIT_SNAPSHOT_HEIGHT;
LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
S32 original_width = 0, original_height = 0;
previewp->getSize(original_width, original_height);
if (gSavedSettings.getBOOL("RenderHUDInSnapshot"))
{ //clamp snapshot resolution to window size when showing UI HUD in snapshot
width = llmin(width, gViewerWindow->getWindowWidthRaw());
height = llmin(height, gViewerWindow->getWindowHeightRaw());
}
llassert(width > 0 && height > 0);
previewp->setSize(width, height);
if (original_width != width || original_height != height)
{
// hide old preview as the aspect ratio could be wrong
checkAutoSnapshot(previewp, FALSE);
previewp->updateSnapshot(TRUE);
}
}
}
void LLFloaterSimpleOutfitSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg)
{
switch (status)
{
case STATUS_READY:
mFloater->setCtrlsEnabled(true);
break;
case STATUS_WORKING:
mFloater->setCtrlsEnabled(false);
break;
case STATUS_FINISHED:
mFloater->setCtrlsEnabled(true);
break;
}
mStatus = status;
}
///----------------------------------------------------------------re------------
/// Class LLFloaterSimpleOutfitSnapshot
///----------------------------------------------------------------------------
LLFloaterSimpleOutfitSnapshot::LLFloaterSimpleOutfitSnapshot(const LLSD& key)
: LLFloaterSnapshotBase(key),
mOutfitGallery(NULL)
{
impl = new Impl(this);
}
LLFloaterSimpleOutfitSnapshot::~LLFloaterSimpleOutfitSnapshot()
{
}
BOOL LLFloaterSimpleOutfitSnapshot::postBuild()
{
getChild<LLUICtrl>("save_btn")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()));
childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
childSetAction("save_btn", boost::bind(&LLFloaterSimpleOutfitSnapshot::onSend, this));
childSetAction("cancel_btn", boost::bind(&LLFloaterSimpleOutfitSnapshot::onCancel, this));
mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
// create preview window
LLRect full_screen_rect = getRootView()->getRect();
LLSnapshotLivePreview::Params p;
p.rect(full_screen_rect);
LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
LLView* parent_view = gSnapshotFloaterView->getParent();
parent_view->addChild(previewp);
//move snapshot floater to special purpose snapshotfloaterview
gFloaterView->removeChild(this);
gSnapshotFloaterView->addChild(this);
impl->mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
impl->updateControls(this);
impl->setAdvanced(true);
impl->setSkipReshaping(true);
previewp->mKeepAspectRatio = FALSE;
previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
previewp->setAllowRenderUI(false);
previewp->setThumbnailSubsampled(TRUE);
return TRUE;
}
const S32 PREVIEW_OFFSET_Y = 70;
void LLFloaterSimpleOutfitSnapshot::draw()
{
LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))
{
// don't render snapshot window in snapshot, even if "show ui" is turned on
return;
}
LLFloater::draw();
if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible())
{
if(previewp->getThumbnailImage())
{
bool working = impl->getStatus() == ImplBase::STATUS_WORKING;
const S32 thumbnail_w = previewp->getThumbnailWidth();
const S32 thumbnail_h = previewp->getThumbnailHeight();
LLRect local_rect = getLocalRect();
S32 offset_x = (local_rect.getWidth() - thumbnail_w) / 2;
S32 offset_y = PREVIEW_OFFSET_Y;
gGL.matrixMode(LLRender::MM_MODELVIEW);
// Apply floater transparency to the texture unless the floater is focused.
F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
LLColor4 color = working ? LLColor4::grey4 : LLColor4::white;
gl_draw_scaled_image(offset_x, offset_y,
thumbnail_w, thumbnail_h,
previewp->getThumbnailImage(), color % alpha);
}
}
impl->updateLayout(this);
}
void LLFloaterSimpleOutfitSnapshot::onOpen(const LLSD& key)
{
LLSnapshotLivePreview* preview = getPreviewView();
if (preview)
{
preview->updateSnapshot(TRUE);
}
focusFirstItem(FALSE);
gSnapshotFloaterView->setEnabled(TRUE);
gSnapshotFloaterView->setVisible(TRUE);
gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
impl->updateControls(this);
impl->setStatus(ImplBase::STATUS_READY);
}
void LLFloaterSimpleOutfitSnapshot::onCancel()
{
closeFloater();
}
void LLFloaterSimpleOutfitSnapshot::onSend()
{
S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
if (can_afford_transaction(expected_upload_cost))
{
saveTexture();
postSave();
}
else
{
LLSD args;
args["COST"] = llformat("%d", expected_upload_cost);
LLNotificationsUtil::add("ErrorPhotoCannotAfford", args);
inventorySaveFailed();
}
}
void LLFloaterSimpleOutfitSnapshot::postSave()
{
impl->setStatus(ImplBase::STATUS_WORKING);
}
// static
void LLFloaterSimpleOutfitSnapshot::update()
{
LLFloaterSimpleOutfitSnapshot* inst = findInstance();
if (inst != NULL)
{
inst->impl->updateLivePreview();
}
}
// static
LLFloaterSimpleOutfitSnapshot* LLFloaterSimpleOutfitSnapshot::findInstance()
{
return LLFloaterReg::findTypedInstance<LLFloaterSimpleOutfitSnapshot>("simple_outfit_snapshot");
}
// static
LLFloaterSimpleOutfitSnapshot* LLFloaterSimpleOutfitSnapshot::getInstance()
{
return LLFloaterReg::getTypedInstance<LLFloaterSimpleOutfitSnapshot>("simple_outfit_snapshot");
}
void LLFloaterSimpleOutfitSnapshot::saveTexture()
{
LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
return;
}
if (mOutfitGallery)
{
mOutfitGallery->onBeforeOutfitSnapshotSave();
}
previewp->saveTexture(TRUE, getOutfitID().asString());
if (mOutfitGallery)
{
mOutfitGallery->onAfterOutfitSnapshotSave();
}
closeFloater();
}
///----------------------------------------------------------------------------
/// Class LLSimpleOutfitSnapshotFloaterView
///----------------------------------------------------------------------------
LLSimpleOutfitSnapshotFloaterView::LLSimpleOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p)
{
}
LLSimpleOutfitSnapshotFloaterView::~LLSimpleOutfitSnapshotFloaterView()
{
}

View File

@ -0,0 +1,467 @@
/**
* @file llfloatersimplesnapshot.cpp
* @brief Snapshot preview window for saving as a thumbnail
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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 "llfloatersimplesnapshot.h"
#include "llfloaterreg.h"
#include "llimagefiltersmanager.h"
#include "llinventorymodel.h"
#include "llstatusbar.h" // can_afford_transaction()
#include "llnotificationsutil.h"
#include "llagent.h"
#include "llagentbenefits.h"
#include "llviewercontrol.h"
#include "llviewertexturelist.h"
LLSimpleSnapshotFloaterView* gSimpleSnapshotFloaterView = NULL;
const S32 THUMBNAIL_SNAPSHOT_DIM = 256;
// Thumbnail posting coro
static const std::string THUMBNAIL_ITEM_UPLOAD_CAP = "InventoryItemThumbnailUpload";
static const std::string THUMBNAIL_CATEGORY_UPLOAD_CAP = "InventoryCategoryThumbnailUpload";
void post_thumbnail_image_coro(std::string cap_url, std::string path_to_image, LLSD first_data)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("post_profile_image_coro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpHeaders::ptr_t httpHeaders;
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
httpOpts->setFollowRedirects(true);
LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (!status)
{
// todo: notification?
LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL;
return;
}
if (!result.has("uploader"))
{
// todo: notification?
LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL;
return;
}
std::string uploader_cap = result["uploader"].asString();
if (uploader_cap.empty())
{
LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL;
return;
}
// Upload the image
LLCore::HttpRequest::ptr_t uploaderhttpRequest(new LLCore::HttpRequest);
LLCore::HttpHeaders::ptr_t uploaderhttpHeaders(new LLCore::HttpHeaders);
LLCore::HttpOptions::ptr_t uploaderhttpOpts(new LLCore::HttpOptions);
S64 length;
{
llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate);
if (!instream.is_open())
{
LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL;
return;
}
length = instream.tellg();
}
uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional
uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required!
uploaderhttpOpts->setFollowRedirects(true);
result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders);
httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
LL_DEBUGS("Thumbnail") << result << LL_ENDL;
if (!status)
{
LL_WARNS("Thumbnail") << "Failed to upload image " << status.toString() << LL_ENDL;
return;
}
if (result["state"].asString() != "complete")
{
if (result.has("message"))
{
LL_WARNS("Thumbnail") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL;
}
else
{
LL_WARNS("Thumbnail") << "Failed to upload image " << result << LL_ENDL;
}
return;
}
// todo: issue an inventory udpate?
//return result["new_asset"].asUUID();
}
///----------------------------------------------------------------------------
/// Class LLFloaterSimpleSnapshot::Impl
///----------------------------------------------------------------------------
LLSnapshotModel::ESnapshotFormat LLFloaterSimpleSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
{
return LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
}
LLSnapshotModel::ESnapshotLayerType LLFloaterSimpleSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
{
return LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
}
void LLFloaterSimpleSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
{
LLSnapshotLivePreview* previewp = getPreviewView();
updateResolution(floater);
if (previewp)
{
previewp->setSnapshotType(LLSnapshotModel::ESnapshotType::SNAPSHOT_TEXTURE);
previewp->setSnapshotFormat(LLSnapshotModel::ESnapshotFormat::SNAPSHOT_FORMAT_PNG);
previewp->setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType::SNAPSHOT_TYPE_COLOR);
}
}
std::string LLFloaterSimpleSnapshot::Impl::getSnapshotPanelPrefix()
{
return "panel_outfit_snapshot_";
}
void LLFloaterSimpleSnapshot::Impl::updateResolution(void* data)
{
LLFloaterSimpleSnapshot *view = (LLFloaterSimpleSnapshot *)data;
if (!view)
{
llassert(view);
return;
}
S32 width = THUMBNAIL_SNAPSHOT_DIM;
S32 height = THUMBNAIL_SNAPSHOT_DIM;
LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
S32 original_width = 0, original_height = 0;
previewp->getSize(original_width, original_height);
if (gSavedSettings.getBOOL("RenderHUDInSnapshot"))
{ //clamp snapshot resolution to window size when showing UI HUD in snapshot
width = llmin(width, gViewerWindow->getWindowWidthRaw());
height = llmin(height, gViewerWindow->getWindowHeightRaw());
}
llassert(width > 0 && height > 0);
previewp->setSize(width, height);
if (original_width != width || original_height != height)
{
// hide old preview as the aspect ratio could be wrong
checkAutoSnapshot(previewp, FALSE);
previewp->updateSnapshot(TRUE);
}
}
}
void LLFloaterSimpleSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg)
{
switch (status)
{
case STATUS_READY:
mFloater->setCtrlsEnabled(true);
break;
case STATUS_WORKING:
mFloater->setCtrlsEnabled(false);
break;
case STATUS_FINISHED:
mFloater->setCtrlsEnabled(true);
break;
}
mStatus = status;
}
///----------------------------------------------------------------re------------
/// Class LLFloaterSimpleSnapshot
///----------------------------------------------------------------------------
LLFloaterSimpleSnapshot::LLFloaterSimpleSnapshot(const LLSD& key)
: LLFloaterSnapshotBase(key)
, mOwner(NULL)
, mContextConeOpacity(0.f)
{
impl = new Impl(this);
}
LLFloaterSimpleSnapshot::~LLFloaterSimpleSnapshot()
{
}
BOOL LLFloaterSimpleSnapshot::postBuild()
{
childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
childSetAction("save_btn", boost::bind(&LLFloaterSimpleSnapshot::onSend, this));
childSetAction("cancel_btn", boost::bind(&LLFloaterSimpleSnapshot::onCancel, this));
mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
// create preview window
LLRect full_screen_rect = getRootView()->getRect();
LLSnapshotLivePreview::Params p;
p.rect(full_screen_rect);
LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
// Do not move LLFloaterSimpleSnapshot floater into gSnapshotFloaterView
// since it can be a dependednt floater and does not draw UI
impl->mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
impl->updateControls(this);
impl->setAdvanced(true);
impl->setSkipReshaping(true);
previewp->mKeepAspectRatio = FALSE;
previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
previewp->setAllowRenderUI(false);
previewp->setThumbnailSubsampled(TRUE);
return TRUE;
}
const S32 PREVIEW_OFFSET_Y = 70;
void LLFloaterSimpleSnapshot::draw()
{
if (mOwner)
{
static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
drawConeToOwner(mContextConeOpacity, max_opacity, mOwner);
}
LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))
{
// don't render snapshot window in snapshot, even if "show ui" is turned on
return;
}
LLFloater::draw();
if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible())
{
if(previewp->getThumbnailImage())
{
bool working = impl->getStatus() == ImplBase::STATUS_WORKING;
const S32 thumbnail_w = previewp->getThumbnailWidth();
const S32 thumbnail_h = previewp->getThumbnailHeight();
LLRect local_rect = getLocalRect();
S32 offset_x = (local_rect.getWidth() - thumbnail_w) / 2;
S32 offset_y = PREVIEW_OFFSET_Y;
gGL.matrixMode(LLRender::MM_MODELVIEW);
// Apply floater transparency to the texture unless the floater is focused.
F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
LLColor4 color = working ? LLColor4::grey4 : LLColor4::white;
gl_draw_scaled_image(offset_x, offset_y,
thumbnail_w, thumbnail_h,
previewp->getThumbnailImage(), color % alpha);
}
}
impl->updateLayout(this);
}
void LLFloaterSimpleSnapshot::onOpen(const LLSD& key)
{
LLSnapshotLivePreview* preview = getPreviewView();
if (preview)
{
preview->updateSnapshot(TRUE);
}
focusFirstItem(FALSE);
gSnapshotFloaterView->setEnabled(TRUE);
gSnapshotFloaterView->setVisible(TRUE);
gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
impl->updateControls(this);
impl->setStatus(ImplBase::STATUS_READY);
mInventoryId = key["item_id"].asUUID();
mTaskId = key["task_id"].asUUID();
}
void LLFloaterSimpleSnapshot::onCancel()
{
closeFloater();
}
void LLFloaterSimpleSnapshot::onSend()
{
LLSnapshotLivePreview* previewp = getPreviewView();
std::string temp_file = gDirUtilp->getTempFilename();
if (previewp->createUploadFile(temp_file, THUMBNAIL_SNAPSHOT_DIM))
{
uploadImageUploadFile(temp_file, mInventoryId, mTaskId);
}
else
{
LLSD notif_args;
notif_args["REASON"] = LLImage::getLastError().c_str();
LLNotificationsUtil::add("CannotUploadTexture", notif_args);
}
}
void LLFloaterSimpleSnapshot::postSave()
{
impl->setStatus(ImplBase::STATUS_WORKING);
}
// static
void LLFloaterSimpleSnapshot::uploadThumbnail(const std::string &file_path, const LLUUID &inventory_id, const LLUUID &task_id)
{
// generate a temp texture file for coroutine
std::string temp_file = gDirUtilp->getTempFilename();
U32 codec = LLImageBase::getCodecFromExtension(gDirUtilp->getExtension(file_path));
if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, THUMBNAIL_SNAPSHOT_DIM))
{
LLSD notif_args;
notif_args["REASON"] = LLImage::getLastError().c_str();
LLNotificationsUtil::add("CannotUploadTexture", notif_args);
LL_WARNS("Thumbnail") << "Failed to upload thumbnail for " << inventory_id << " " << task_id << ", reason: " << notif_args["REASON"].asString() << LL_ENDL;
return;
}
uploadImageUploadFile(temp_file, inventory_id, task_id);
}
// static
void LLFloaterSimpleSnapshot::uploadImageUploadFile(const std::string &temp_file, const LLUUID &inventory_id, const LLUUID &task_id)
{
std::string cap_name;
LLSD data;
if (task_id.notNull())
{
cap_name = THUMBNAIL_ITEM_UPLOAD_CAP;
data["item_id"] = inventory_id;
data["task_id"] = task_id;
}
else if (gInventory.getCategory(inventory_id))
{
cap_name = THUMBNAIL_CATEGORY_UPLOAD_CAP;
data["category_id"] = inventory_id;
}
else
{
cap_name = THUMBNAIL_ITEM_UPLOAD_CAP;
data["item_id"] = inventory_id;
}
std::string cap_url = gAgent.getRegionCapability(cap_name);
if (cap_url.empty())
{
LLSD args;
args["CAPABILITY"] = cap_url;
LLNotificationsUtil::add("RegionCapabilityRequestError", args);
LL_WARNS("Thumbnail") << "Failed to upload profile image for item " << inventory_id << " " << task_id << ", no cap found" << LL_ENDL;
return;
}
LLCoros::instance().launch("postAgentUserImageCoro",
boost::bind(post_thumbnail_image_coro, cap_url, temp_file, data));
}
void LLFloaterSimpleSnapshot::update()
{
// initializes snapshots when needed
LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("simple_snapshot");
for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
iter != inst_list.end(); ++iter)
{
LLFloaterSimpleSnapshot* floater = dynamic_cast<LLFloaterSimpleSnapshot*>(*iter);
if (floater)
{
floater->impl->updateLivePreview();
}
}
}
// static
LLFloaterSimpleSnapshot* LLFloaterSimpleSnapshot::findInstance(const LLSD &key)
{
return LLFloaterReg::findTypedInstance<LLFloaterSimpleSnapshot>("simple_snapshot", key);
}
// static
LLFloaterSimpleSnapshot* LLFloaterSimpleSnapshot::getInstance(const LLSD &key)
{
return LLFloaterReg::getTypedInstance<LLFloaterSimpleSnapshot>("simple_snapshot", key);
}
void LLFloaterSimpleSnapshot::saveTexture()
{
LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
return;
}
previewp->saveTexture(TRUE, getInventoryId().asString());
closeFloater();
}
///----------------------------------------------------------------------------
/// Class LLSimpleOutfitSnapshotFloaterView
///----------------------------------------------------------------------------
LLSimpleSnapshotFloaterView::LLSimpleSnapshotFloaterView(const Params& p) : LLFloaterView(p)
{
}
LLSimpleSnapshotFloaterView::~LLSimpleSnapshotFloaterView()
{
}

View File

@ -1,6 +1,6 @@
/**
* @file llfloatersimpleoutfitsnapshot.h
* @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
* @file llfloatersimplesnapshot.h
* @brief Snapshot preview window for saving as a thumbnail
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
@ -24,26 +24,25 @@
* $/LicenseInfo$
*/
#ifndef LL_LLFLOATERSIMPLEOUTFITSNAPSHOT_H
#define LL_LLFLOATERSIMPLEOUTFITSNAPSHOT_H
#ifndef LL_LLFLOATERSIMPLESNAPSHOT_H
#define LL_LLFLOATERSIMPLESNAPSHOT_H
#include "llfloater.h"
#include "llfloatersnapshot.h"
#include "lloutfitgallery.h"
#include "llsnapshotlivepreview.h"
///----------------------------------------------------------------------------
/// Class LLFloaterSimpleOutfitSnapshot
/// Class LLFloaterSimpleSnapshot
///----------------------------------------------------------------------------
class LLFloaterSimpleOutfitSnapshot : public LLFloaterSnapshotBase
class LLFloaterSimpleSnapshot : public LLFloaterSnapshotBase
{
LOG_CLASS(LLFloaterSimpleOutfitSnapshot);
LOG_CLASS(LLFloaterSimpleSnapshot);
public:
LLFloaterSimpleOutfitSnapshot(const LLSD& key);
~LLFloaterSimpleOutfitSnapshot();
LLFloaterSimpleSnapshot(const LLSD& key);
~LLFloaterSimpleSnapshot();
BOOL postBuild();
void onOpen(const LLSD& key);
@ -51,17 +50,19 @@ public:
static void update();
static LLFloaterSimpleOutfitSnapshot* getInstance();
static LLFloaterSimpleOutfitSnapshot* findInstance();
static LLFloaterSimpleSnapshot* getInstance(const LLSD &key);
static LLFloaterSimpleSnapshot* findInstance(const LLSD &key);
void saveTexture();
const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
void setOutfitID(LLUUID id) { mOutfitID = id; }
LLUUID getOutfitID() { return mOutfitID; }
void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; }
void setInventoryId(const LLUUID &inventory_id) { mInventoryId = inventory_id; }
LLUUID getInventoryId() { return mInventoryId; }
void setTaskId(const LLUUID &task_id) { mTaskId = task_id; }
void setOwner(LLView *owner_view) { mOwner = owner_view; }
void postSave();
static void uploadThumbnail(const std::string &file_path, const LLUUID &inventory_id, const LLUUID &task_id);
class Impl;
friend class Impl;
@ -70,17 +71,23 @@ private:
void onSend();
void onCancel();
LLUUID mOutfitID;
LLOutfitGallery* mOutfitGallery;
// uploads upload-ready file
static void uploadImageUploadFile(const std::string &temp_file, const LLUUID &inventory_id, const LLUUID &task_id);
LLUUID mInventoryId;
LLUUID mTaskId;
LLView* mOwner;
F32 mContextConeOpacity;
};
///----------------------------------------------------------------------------
/// Class LLFloaterSimpleOutfitSnapshot::Impl
/// Class LLFloaterSimpleSnapshot::Impl
///----------------------------------------------------------------------------
class LLFloaterSimpleOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase
class LLFloaterSimpleSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase
{
LOG_CLASS(LLFloaterSimpleOutfitSnapshot::Impl);
LOG_CLASS(LLFloaterSimpleSnapshot::Impl);
public:
Impl(LLFloaterSnapshotBase* floater)
: LLFloaterSnapshotBase::ImplBase(floater)
@ -108,7 +115,7 @@ private:
/// Class LLSimpleOutfitSnapshotFloaterView
///----------------------------------------------------------------------------
class LLSimpleOutfitSnapshotFloaterView : public LLFloaterView
class LLSimpleSnapshotFloaterView : public LLFloaterView
{
public:
struct Params
@ -117,13 +124,13 @@ public:
};
protected:
LLSimpleOutfitSnapshotFloaterView(const Params& p);
LLSimpleSnapshotFloaterView(const Params& p);
friend class LLUICtrlFactory;
public:
virtual ~LLSimpleOutfitSnapshotFloaterView();
virtual ~LLSimpleSnapshotFloaterView();
};
extern LLSimpleOutfitSnapshotFloaterView* gSimpleOutfitSnapshotFloaterView;
extern LLSimpleSnapshotFloaterView* gSimpleOutfitSnapshotFloaterView;
#endif // LL_LLFLOATERSIMPLEOUTFITSNAPSHOT_H
#endif // LL_LLFLOATERSIMPLESNAPSHOT_H

View File

@ -75,11 +75,11 @@ void LLInspectTexture::onOpen(const LLSD& sdData)
// Start fade animation
LLInspect::onOpen(sdData);
bool fIsAsset = sdData.has("asset_id");
bool fIsAsset = sdData.has("thumbnail_id");
bool fIsInventory = sdData.has("item_id");
// Skip if we're being asked to display the same thing
const LLUUID idAsset = (fIsAsset) ? sdData["asset_id"].asUUID() : LLUUID::null;
const LLUUID idAsset = (fIsAsset) ? sdData["thumbnail_id"].asUUID() : LLUUID::null;
const LLUUID idItem = (fIsInventory) ? sdData["item_id"].asUUID() : LLUUID::null;
if ( (getVisible()) && ( ((fIsAsset) && (idAsset == mAssetId)) || ((fIsInventory) && (idItem == mItemId)) ) )
{
@ -134,13 +134,27 @@ BOOL LLInspectTexture::postBuild()
// Helper functions
//
class LLIsTextureType : public LLInventoryCollectFunctor
{
public:
LLIsTextureType() {}
virtual ~LLIsTextureType() {}
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item);
};
bool LLIsTextureType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return item && (item->getType() == LLAssetType::AT_TEXTURE);
}
LLToolTip* LLInspectTextureUtil::createInventoryToolTip(LLToolTip::Params p)
{
const LLSD& sdTooltip = p.create_params;
if (sdTooltip.has("thumbnail_id") && sdTooltip["thumbnail_id"].asUUID().notNull())
{
// go straight for tooltip regardless of type
// go straight for thumbnail regardless of type
return LLUICtrlFactory::create<LLTextureToolTip>(p);
}
@ -152,18 +166,32 @@ LLToolTip* LLInspectTextureUtil::createInventoryToolTip(LLToolTip::Params p)
if (sdTooltip.has("item_id"))
{
const LLUUID idCategory = sdTooltip["item_id"].asUUID();
LLViewerInventoryCategory* cat = gInventory.getCategory(idCategory);
if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
{
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
// Not LLIsOfAssetType, because we allow links
LLIsTextureType f;
gInventory.getDirectDescendentsOf(idCategory, cats, items, f);
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLIsOfAssetType f(LLAssetType::AT_TEXTURE);
gInventory.getDirectDescendentsOf(idCategory, cats, items, f);
// Exactly one texture found => show the texture tooltip
if (1 == items.size())
{
p.create_params.getValue()["asset_id"] = items.front()->getAssetUUID();
return LLUICtrlFactory::create<LLTextureToolTip>(p);
}
// Exactly one texture found => show the texture tooltip
if (1 == items.size())
{
LLViewerInventoryItem* item = items.front();
if (item && item->getIsLinkType())
{
item = item->getLinkedItem();
}
if (item)
{
// Note: LLFloaterChangeItemThumbnail will attempt to write this
// into folder's thumbnail id when opened
p.create_params.getValue()["thumbnail_id"] = item->getAssetUUID();
return LLUICtrlFactory::create<LLTextureToolTip>(p);
}
}
}
}
// No or more than one texture found => show default tooltip

View File

@ -161,6 +161,12 @@ bool isMarketplaceSendAction(const std::string& action)
return ("send_to_marketplace" == action);
}
bool isPanelActive(const std::string& panel_name)
{
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
return (active_panel && (active_panel->getName() == panel_name));
}
// Used by LLFolderBridge as callback for directory fetching recursion
class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
{
@ -455,6 +461,25 @@ void LLInvFVBridge::showProperties()
}
}
void LLInvFVBridge::navigateToFolder()
{
LLInventorySingleFolderPanel* panel = dynamic_cast<LLInventorySingleFolderPanel*>(mInventoryPanel.get());
if (!panel)
{
return;
}
LLInventoryModel* model = getInventoryModel();
if (!model)
{
return;
}
if (mUUID.isNull())
{
return;
}
panel->changeFolderRoot(mUUID);
}
void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)
{
// Deactivate gestures when moving them into Trash
@ -919,6 +944,13 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
disabled_items.push_back(std::string("Rename"));
}
}
LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID);
items.push_back(std::string("thumbnail"));
if (inv_item && !inv_item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
{
disabled_items.push_back(std::string("thumbnail"));
}
if (show_asset_id)
{
@ -926,7 +958,6 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
bool is_asset_knowable = false;
LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID);
if (inv_item)
{
is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(inv_item->getType());
@ -999,11 +1030,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
addDeleteContextMenuOptions(items, disabled_items);
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
// <FS:Zi> Don't offer "Show in Main View" for folders opened in separate inventory views
// as there are no tabs to switch to
// if (active_panel && (active_panel->getName() != "All Items"))
if (active_panel && (active_panel->getName() != "All Items") && (active_panel->getName() != "inv_panel"))
//if (!isPanelActive("All Items") && !isPanelActive("single_folder_inv"))
if (!isPanelActive("All Items") && !isPanelActive("single_folder_inv") && !isPanelActive("inv_panel"))
// </FS:Zi>
{
items.push_back(std::string("Show in Main Panel"));
@ -1113,7 +1143,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,
items.push_back(std::string("Delete"));
if (!isItemRemovable())
if (!isItemRemovable() || isPanelActive("Favorite Items"))
{
disabled_items.push_back(std::string("Delete"));
}
@ -1862,6 +1892,12 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
restoreItem();
return;
}
else if ("thumbnail" == action)
{
LLSD data(mUUID);
LLFloaterReg::showInstance("change_item_thumbnail", data);
return;
}
else if ("copy_uuid" == action)
{
// Single item only
@ -3566,6 +3602,12 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
return;
}
else if ("thumbnail" == action)
{
LLSD data(mUUID);
LLFloaterReg::showInstance("change_item_thumbnail", data);
return;
}
else if ("paste" == action)
{
pasteFromClipboard();
@ -4537,12 +4579,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
}
disabled_items.push_back(std::string("New Folder"));
disabled_items.push_back(std::string("New Script"));
disabled_items.push_back(std::string("New Note"));
disabled_items.push_back(std::string("New Settings"));
disabled_items.push_back(std::string("New Gesture"));
disabled_items.push_back(std::string("New Clothes"));
disabled_items.push_back(std::string("New Body Parts"));
disabled_items.push_back(std::string("upload_def"));
}
if (favorites == mUUID)
@ -4565,11 +4601,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)
{
disabled_items.push_back(std::string("New Folder"));
disabled_items.push_back(std::string("New Script"));
disabled_items.push_back(std::string("New Note"));
disabled_items.push_back(std::string("New Gesture"));
disabled_items.push_back(std::string("New Clothes"));
disabled_items.push_back(std::string("New Body Parts"));
disabled_items.push_back(std::string("upload_def"));
}
if (marketplace_listings_id == mUUID)
@ -4579,14 +4610,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("Cut"));
disabled_items.push_back(std::string("Delete"));
}
if (isPanelActive("Favorite Items"))
{
disabled_items.push_back(std::string("Delete"));
}
if(trash_id == mUUID)
{
bool is_recent_panel = false;
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
if (active_panel && (active_panel->getName() == "Recent Items"))
{
is_recent_panel = true;
}
bool is_recent_panel = isPanelActive("Recent Items");
// This is the trash.
items.push_back(std::string("Empty Trash"));
@ -4636,19 +4667,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
if (!isMarketplaceListingsFolder() && !model->isObjectDescendentOf(mUUID, outfits_id))
// </FS:Ansariel>
{
items.push_back(std::string("New Script"));
items.push_back(std::string("New Note"));
items.push_back(std::string("New Gesture"));
items.push_back(std::string("New Clothes"));
items.push_back(std::string("New Body Parts"));
items.push_back(std::string("New Settings"));
items.push_back(std::string("upload_def"));
if (!LLEnvironment::instance().isInventoryEnabled())
{
disabled_items.push_back("New Settings");
}
}
}
getClipboardEntries(false, items, disabled_items, flags);
@ -4872,6 +4891,17 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
disabled_items.push_back(std::string("New folder from selected"));
}
if ((flags & ITEM_IN_MULTI_SELECTION) == 0)
{
items.push_back(std::string("open_in_new_window"));
items.push_back(std::string("Open Folder Separator"));
if(isPanelActive("single_folder_inv"))
{
items.push_back(std::string("open_in_current_window"));
}
}
#ifndef LL_RELEASE_FOR_DOWNLOAD
if (LLFolderType::lookupIsProtectedType(type) && is_agent_inventory)
{

View File

@ -108,6 +108,7 @@ public:
virtual std::string getLabelSuffix() const { return LLStringUtil::null; }
virtual void openItem() {}
virtual void closeItem() {}
virtual void navigateToFolder();
virtual void showProperties();
virtual BOOL isItemRenameable() const { return TRUE; }
virtual BOOL isMultiPreviewAllowed() { return TRUE; }

View File

@ -90,7 +90,8 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)
mCurrentGeneration(0),
mFirstRequiredGeneration(0),
mFirstSuccessGeneration(0),
mSearchType(SEARCHTYPE_NAME)
mSearchType(SEARCHTYPE_NAME),
mSingleFolderMode(false)
{
// copy mFilterOps into mDefaultFilterOps
markDefault();
@ -1841,7 +1842,7 @@ bool LLInventoryFilter::areDateLimitsSet()
bool LLInventoryFilter::showAllResults() const
{
return hasFilterString();
return hasFilterString() && !mSingleFolderMode;
}

View File

@ -252,6 +252,8 @@ public:
std::string::size_type getFilterSubStringLen(U32 index) const;
// </FS:Zi> Multi-substring inventory search
void setSingleFolderMode(bool is_single_folder) { mSingleFolderMode = is_single_folder; }
void setFilterPermissions(PermissionMask perms);
PermissionMask getFilterPermissions() const;
@ -384,6 +386,8 @@ private:
std::vector<std::string> mFilterTokens;
std::string mExactToken;
bool mSingleFolderMode;
};
#endif

View File

@ -195,6 +195,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this));
mCommitCallbackRegistrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryPanel::fileUploadLocation, this, _2));
mCommitCallbackRegistrar.add("Inventory.OpenNewFolderWindow", boost::bind(&LLInventoryPanel::openSingleViewInventory, this, _2));
mCommitCallbackRegistrar.add("Inventory.CustomAction", boost::bind(&LLInventoryPanel::onCustomAction, this, _2)); // <FS:Ansariel> Prevent warning "No callback found for: 'Inventory.CustomAction' in control: Find Links"
}
@ -1797,6 +1798,11 @@ void LLInventoryPanel::fileUploadLocation(const LLSD& userdata)
}
}
void LLInventoryPanel::openSingleViewInventory(const LLSD& userdata)
{
LLPanelMainInventory::newFolderWindow(LLFolderBridge::sSelf.get()->getUUID());
}
void LLInventoryPanel::purgeSelectedItems()
{
if (!mFolderRoot.get()) return;
@ -2284,6 +2290,138 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
}
static LLDefaultChildRegistry::Register<LLInventorySingleFolderPanel> t_single_folder_inventory_panel("single_folder_inventory_panel");
LLInventorySingleFolderPanel::LLInventorySingleFolderPanel(const Params& params)
: LLInventoryPanel(params)
{
getFilter().setSingleFolderMode(true);
mCommitCallbackRegistrar.add("Inventory.OpenSelectedFolder", boost::bind(&LLInventorySingleFolderPanel::openInCurrentWindow, this, _2));
}
LLInventorySingleFolderPanel::~LLInventorySingleFolderPanel()
{
}
void LLInventorySingleFolderPanel::setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)
{
if (mFolderRoot.get())
{
mFolderRoot.get()->setSelectCallback(cb);
mSelectionCallback = cb;
}
}
void LLInventorySingleFolderPanel::initFromParams(const Params& p)
{
Params fav_params(p);
fav_params.start_folder.id = gInventory.getRootFolderID();
LLInventoryPanel::initFromParams(p);
changeFolderRoot(gInventory.getRootFolderID());
}
void LLInventorySingleFolderPanel::openInCurrentWindow(const LLSD& userdata)
{
changeFolderRoot(LLFolderBridge::sSelf.get()->getUUID());
}
void LLInventorySingleFolderPanel::changeFolderRoot(const LLUUID& new_id)
{
if(mFolderID.notNull())
{
mBackwardFolders.push_back(mFolderID);
}
mFolderID = new_id;
updateSingleFolderRoot();
}
void LLInventorySingleFolderPanel::onForwardFolder()
{
if(!mForwardFolders.empty() && (mFolderID != mForwardFolders.back()))
{
mBackwardFolders.push_back(mFolderID);
mFolderID = mForwardFolders.back();
mForwardFolders.pop_back();
updateSingleFolderRoot();
}
}
void LLInventorySingleFolderPanel::onBackwardFolder()
{
if(!mBackwardFolders.empty() && (mFolderID != mBackwardFolders.back()))
{
mForwardFolders.push_back(mFolderID);
mFolderID = mBackwardFolders.back();
mBackwardFolders.pop_back();
updateSingleFolderRoot();
}
}
void LLInventorySingleFolderPanel::clearNavigationHistory()
{
mForwardFolders.clear();
mBackwardFolders.clear();
}
boost::signals2::connection LLInventorySingleFolderPanel::setRootChangedCallback(root_changed_callback_t cb)
{
return mRootChangedSignal.connect(cb);
}
void LLInventorySingleFolderPanel::updateSingleFolderRoot()
{
if (mFolderID != getRootFolderID())
{
mRootChangedSignal();
LLUUID root_id = mFolderID;
if (mFolderRoot.get())
{
removeItemID(getRootFolderID());
mFolderRoot.get()->destroyView();
}
mCommitCallbackRegistrar.pushScope();
{
LLFolderView* folder_view = createFolderRoot(root_id);
folder_view->setChildrenInited(false);
mFolderRoot = folder_view->getHandle();
addItemID(root_id, mFolderRoot.get());
LLRect scroller_view_rect = getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
LLScrollContainer::Params scroller_params(mParams.scroll());
scroller_params.rect(scroller_view_rect);
if (mScroller)
{
removeChild(mScroller);
delete mScroller;
mScroller = NULL;
}
mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);
addChild(mScroller);
mScroller->addChild(mFolderRoot.get());
mFolderRoot.get()->setScrollContainer(mScroller);
mFolderRoot.get()->setFollowsAll();
mFolderRoot.get()->addChild(mFolderRoot.get()->mStatusTextBox);
if (!mSelectionCallback.empty())
{
mFolderRoot.get()->setSelectCallback(mSelectionCallback);
}
}
mCommitCallbackRegistrar.popScope();
mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar);
buildNewViews(mFolderID);
mFolderRoot.get()->setShowEmptyMessage(false);
}
}
/************************************************************************/
/* Asset Pre-Filtered Inventory Panel related class */
/************************************************************************/

View File

@ -233,6 +233,7 @@ public:
void doCreate(const LLSD& userdata);
bool beginIMSession();
void fileUploadLocation(const LLSD& userdata);
void openSingleViewInventory(const LLSD& userdata);
void purgeSelectedItems();
bool attachObject(const LLSD& userdata);
static void idle(void* user_data);
@ -279,6 +280,8 @@ public:
void callbackPurgeSelectedItems(const LLSD& notification, const LLSD& response);
void changeFolderRoot(const LLUUID& new_id) {};
protected:
void openStartFolderOrMyInventory(); // open the first level of inventory
void onItemsCompletion(); // called when selected items are complete
@ -399,6 +402,44 @@ private:
std::deque<LLUUID> mBuildViewsQueue;
};
class LLInventorySingleFolderPanel : public LLInventoryPanel
{
public:
struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
{};
void initFromParams(const Params& p);
bool isSelectionRemovable() { return false; }
//void setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
void openInCurrentWindow(const LLSD& userdata);
void changeFolderRoot(const LLUUID& new_id);
void onForwardFolder();
void onBackwardFolder();
void clearNavigationHistory();
LLUUID getSingleFolderRoot() { return mFolderID; }
void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
typedef boost::function<void()> root_changed_callback_t;
boost::signals2::connection setRootChangedCallback(root_changed_callback_t cb);
protected:
LLInventorySingleFolderPanel(const Params& params);
~LLInventorySingleFolderPanel();
void updateSingleFolderRoot();
boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)> mSelectionCallback;
friend class LLUICtrlFactory;
LLUUID mFolderID;
std::list<LLUUID> mBackwardFolders;
std::list<LLUUID> mForwardFolders;
boost::signals2::signal<void()> mRootChangedSignal;
};
/************************************************************************/
/* Asset Pre-Filtered Inventory Panel related class */
/* Exchanges filter's flexibility for speed of generation and */

View File

@ -36,12 +36,11 @@
#include "llaccordionctrltab.h"
#include "llappearancemgr.h"
#include "llagentbenefits.h"
#include "llerror.h"
#include "llfilepicker.h"
#include "llfloaterperms.h"
#include "llfloaterreg.h"
#include "llfloatersimpleoutfitsnapshot.h"
#include "llfloatersimplesnapshot.h"
#include "llimagedimensionsinfo.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
@ -125,7 +124,6 @@ void LLOutfitGallery::onOpen(const LLSD& info)
LLOutfitListBase::onOpen(info);
if (!mGalleryCreated)
{
loadPhotos();
uuid_vec_t cats;
getCurrentCategories(cats);
int n = cats.size();
@ -837,50 +835,20 @@ LLContextMenu* LLOutfitGalleryContextMenu::createMenu()
registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
registrar.add("Outfit.Delete", boost::bind(&LLOutfitGalleryContextMenu::onRemoveOutfit, this, selected_id));
registrar.add("Outfit.Create", boost::bind(&LLOutfitGalleryContextMenu::onCreate, this, _2));
registrar.add("Outfit.UploadPhoto", boost::bind(&LLOutfitGalleryContextMenu::onUploadPhoto, this, selected_id));
registrar.add("Outfit.SelectPhoto", boost::bind(&LLOutfitGalleryContextMenu::onSelectPhoto, this, selected_id));
registrar.add("Outfit.TakeSnapshot", boost::bind(&LLOutfitGalleryContextMenu::onTakeSnapshot, this, selected_id));
registrar.add("Outfit.RemovePhoto", boost::bind(&LLOutfitGalleryContextMenu::onRemovePhoto, this, selected_id));
registrar.add("Outfit.Thumbnail", boost::bind(&LLOutfitGalleryContextMenu::onThumbnail, this, selected_id));
enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitGalleryContextMenu::onEnable, this, _2));
enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitGalleryContextMenu::onVisible, this, _2));
return createFromFile("menu_gallery_outfit_tab.xml");
}
void LLOutfitGalleryContextMenu::onUploadPhoto(const LLUUID& outfit_cat_id)
void LLOutfitGalleryContextMenu::onThumbnail(const LLUUID& outfit_cat_id)
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
if (gallery && outfit_cat_id.notNull())
{
gallery->uploadPhoto(outfit_cat_id);
}
}
void LLOutfitGalleryContextMenu::onSelectPhoto(const LLUUID& outfit_cat_id)
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
if (gallery && outfit_cat_id.notNull())
{
gallery->onSelectPhoto(outfit_cat_id);
}
}
void LLOutfitGalleryContextMenu::onRemovePhoto(const LLUUID& outfit_cat_id)
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
if (gallery && outfit_cat_id.notNull())
{
gallery->checkRemovePhoto(outfit_cat_id);
gallery->refreshOutfit(outfit_cat_id);
}
}
void LLOutfitGalleryContextMenu::onTakeSnapshot(const LLUUID& outfit_cat_id)
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
if (gallery && outfit_cat_id.notNull())
{
gallery->onTakeSnapshot(outfit_cat_id);
LLSD data(outfit_cat_id);
LLFloaterReg::showInstance("change_item_thumbnail", data);
}
}
@ -919,16 +887,6 @@ bool LLOutfitGalleryContextMenu::onEnable(LLSD::String param)
bool LLOutfitGalleryContextMenu::onVisible(LLSD::String param)
{
mMenuHandle.get()->getChild<LLUICtrl>("upload_photo")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()));
if ("remove_photo" == param)
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
LLUUID selected_id = mUUIDs.front();
if (gallery && selected_id.notNull())
{
return !gallery->hasDefaultImage(selected_id);
}
}
return LLOutfitContextMenu::onVisible(param);
}
@ -943,56 +901,12 @@ void LLOutfitGalleryGearMenu::onUpdateItemsVisibility()
bool have_selection = getSelectedOutfitID().notNull();
mMenu->setItemVisible("expand", FALSE);
mMenu->setItemVisible("collapse", FALSE);
mMenu->setItemVisible("upload_photo", have_selection);
mMenu->setItemVisible("select_photo", have_selection);
mMenu->setItemVisible("take_snapshot", have_selection);
mMenu->setItemVisible("remove_photo", !hasDefaultImage());
mMenu->setItemVisible("thumbnail", have_selection);
mMenu->setItemVisible("sepatator3", TRUE);
mMenu->setItemVisible("sort_folders_by_name", TRUE);
LLOutfitListGearMenuBase::onUpdateItemsVisibility();
}
void LLOutfitGalleryGearMenu::onUploadFoto()
{
LLUUID selected_outfit_id = getSelectedOutfitID();
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
if (gallery && selected_outfit_id.notNull())
{
gallery->uploadPhoto(selected_outfit_id);
}
}
void LLOutfitGalleryGearMenu::onSelectPhoto()
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
LLUUID selected_outfit_id = getSelectedOutfitID();
if (gallery && !selected_outfit_id.isNull())
{
gallery->onSelectPhoto(selected_outfit_id);
}
}
void LLOutfitGalleryGearMenu::onRemovePhoto()
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
LLUUID selected_outfit_id = getSelectedOutfitID();
if (gallery && !selected_outfit_id.isNull())
{
gallery->checkRemovePhoto(selected_outfit_id);
gallery->refreshOutfit(selected_outfit_id);
}
}
void LLOutfitGalleryGearMenu::onTakeSnapshot()
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
LLUUID selected_outfit_id = getSelectedOutfitID();
if (gallery && !selected_outfit_id.isNull())
{
gallery->onTakeSnapshot(selected_outfit_id);
}
}
void LLOutfitGalleryGearMenu::onChangeSortOrder()
{
bool sort_by_name = !gSavedSettings.getBOOL("OutfitGallerySortByName");
@ -1019,104 +933,82 @@ void LLOutfitGallery::onTextureSelectionChanged(LLInventoryItem* itemp)
{
}
void LLOutfitGallery::loadPhotos()
{
//Iterate over inventory
mSnapshotFolderID = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_TEXTURE);
LLViewerInventoryCategory* textures_category = gInventory.getCategory(mSnapshotFolderID);
if (!textures_category)
return;
if (mTexturesObserver == NULL)
{
mTexturesObserver = new LLInventoryCategoriesObserver();
gInventory.addObserver(mTexturesObserver);
}
// Start observing changes in "Textures" category.
mTexturesObserver->addCategory(mSnapshotFolderID,
boost::bind(&LLOutfitGallery::refreshTextures, this, mSnapshotFolderID));
textures_category->fetch();
}
void LLOutfitGallery::updateSnapshotFolderObserver()
{
if(mSnapshotFolderID != gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_TEXTURE))
{
if (gInventory.containsObserver(mTexturesObserver))
{
gInventory.removeObserver(mTexturesObserver);
}
delete mTexturesObserver;
mTexturesObserver = NULL;
loadPhotos();
}
}
void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
{
LLViewerInventoryCategory* category = gInventory.getCategory(category_id);
if (category)
{
bool photo_loaded = false;
LLInventoryModel::cat_array_t sub_cat_array;
LLInventoryModel::item_array_t outfit_item_array;
// Collect all sub-categories of a given category.
gInventory.collectDescendents(
category->getUUID(),
sub_cat_array,
outfit_item_array,
LLInventoryModel::EXCLUDE_TRASH);
BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array)
LLUUID asset_id = category->getThumbnailUUID();
if (asset_id.isNull())
{
LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem();
LLUUID asset_id, inv_id;
std::string item_name;
if (linked_item != NULL)
LLInventoryModel::cat_array_t sub_cat_array;
LLInventoryModel::item_array_t outfit_item_array;
// Collect all sub-categories of a given category.
gInventory.collectDescendents(
category->getUUID(),
sub_cat_array,
outfit_item_array,
LLInventoryModel::EXCLUDE_TRASH);
BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array)
{
if (linked_item->getActualType() == LLAssetType::AT_TEXTURE)
LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem();
LLUUID asset_id, inv_id;
std::string item_name;
if (linked_item != NULL)
{
asset_id = linked_item->getAssetUUID();
inv_id = linked_item->getUUID();
item_name = linked_item->getName();
}
}
else if (outfit_item->getActualType() == LLAssetType::AT_TEXTURE)
{
asset_id = outfit_item->getAssetUUID();
inv_id = outfit_item->getUUID();
item_name = outfit_item->getName();
}
if (asset_id.notNull())
{
photo_loaded |= mOutfitMap[category_id]->setImageAssetId(asset_id);
// Rename links
if (!mOutfitRenamePending.isNull() && mOutfitRenamePending.asString() == item_name)
{
LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(mOutfitRenamePending);
LLStringUtil::format_map_t photo_string_args;
photo_string_args["OUTFIT_NAME"] = outfit_cat->getName();
std::string new_name = getString("outfit_photo_string", photo_string_args);
LLSD updates;
updates["name"] = new_name;
update_inventory_item(inv_id, updates, NULL);
mOutfitRenamePending.setNull();
LLFloater* appearance_floater = LLFloaterReg::getInstance("appearance");
if (appearance_floater)
if (linked_item->getActualType() == LLAssetType::AT_TEXTURE)
{
appearance_floater->setFocus(TRUE);
asset_id = linked_item->getAssetUUID();
inv_id = linked_item->getUUID();
item_name = linked_item->getName();
}
}
if (item_name == LLAppearanceMgr::sExpectedTextureName)
else if (outfit_item->getActualType() == LLAssetType::AT_TEXTURE)
{
// Images with "appropriate" name take priority
break;
asset_id = outfit_item->getAssetUUID();
inv_id = outfit_item->getUUID();
item_name = outfit_item->getName();
}
if (category->getThumbnailUUID().notNull())
{
asset_id = category->getThumbnailUUID();
}
if (asset_id.notNull())
{
photo_loaded |= mOutfitMap[category_id]->setImageAssetId(asset_id);
// Rename links
if (!mOutfitRenamePending.isNull() && mOutfitRenamePending.asString() == item_name)
{
LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(mOutfitRenamePending);
LLStringUtil::format_map_t photo_string_args;
photo_string_args["OUTFIT_NAME"] = outfit_cat->getName();
std::string new_name = getString("outfit_photo_string", photo_string_args);
LLSD updates;
updates["name"] = new_name;
update_inventory_item(inv_id, updates, NULL);
mOutfitRenamePending.setNull();
LLFloater* appearance_floater = LLFloaterReg::getInstance("appearance");
if (appearance_floater)
{
appearance_floater->setFocus(TRUE);
}
}
if (item_name == LLAppearanceMgr::sExpectedTextureName)
{
// Images with "appropriate" name take priority
break;
}
}
if (!photo_loaded)
{
mOutfitMap[category_id]->setDefaultImage();
}
}
if (!photo_loaded)
{
mOutfitMap[category_id]->setDefaultImage();
}
}
else
{
mOutfitMap[category_id]->setImageAssetId(asset_id);
}
}
@ -1126,131 +1018,6 @@ void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
}
}
// Refresh linked textures from "textures" uploads folder
void LLOutfitGallery::refreshTextures(const LLUUID& category_id)
{
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
// Collect all sub-categories of a given category.
LLIsType is_texture(LLAssetType::AT_TEXTURE);
gInventory.collectDescendentsIf(
category_id,
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH,
is_texture);
//Find texture which contain pending outfit ID string in name
LLViewerInventoryItem* photo_upload_item = NULL;
BOOST_FOREACH(LLViewerInventoryItem* item, item_array)
{
std::string name = item->getName();
if (!mOutfitLinkPending.isNull() && name == mOutfitLinkPending.asString())
{
photo_upload_item = item;
break;
}
}
if (photo_upload_item != NULL)
{
LLUUID photo_item_id = photo_upload_item->getUUID();
LLInventoryObject* upload_object = gInventory.getObject(photo_item_id);
if (!upload_object)
{
LL_WARNS() << "LLOutfitGallery::refreshTextures added_object is null!" << LL_ENDL;
}
else
{
linkPhotoToOutfit(photo_item_id, mOutfitLinkPending);
mOutfitRenamePending = mOutfitLinkPending;
mOutfitLinkPending.setNull();
}
}
}
void LLOutfitGallery::uploadPhoto(LLUUID outfit_id)
{
outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id);
if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull())
{
return;
}
(new LLFilePickerReplyThread(boost::bind(&LLOutfitGallery::uploadOutfitImage, this, _1, outfit_id), LLFilePicker::FFLOAD_IMAGE, false))->getFile();
}
void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filenames, LLUUID outfit_id)
{
std::string filename = filenames[0];
LLLocalBitmap* unit = new LLLocalBitmap(filename);
if (unit->getValid())
{
std::string exten = gDirUtilp->getExtension(filename);
U32 codec = LLImageBase::getCodecFromExtension(exten);
LLImageDimensionsInfo image_info;
std::string image_load_error;
if (!image_info.load(filename, codec))
{
image_load_error = image_info.getLastError();
}
S32 max_width = MAX_OUTFIT_PHOTO_WIDTH;
S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT;
if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height))
{
LLStringUtil::format_map_t args;
args["WIDTH"] = llformat("%d", max_width);
args["HEIGHT"] = llformat("%d", max_height);
image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args);
}
if (!image_load_error.empty())
{
LLSD subst;
subst["REASON"] = image_load_error;
LLNotificationsUtil::add("OutfitPhotoLoadError", subst);
return;
}
S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
void *nruserdata = NULL;
nruserdata = (void *)&outfit_id;
LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id);
if (!outfit_cat) return;
updateSnapshotFolderObserver();
checkRemovePhoto(outfit_id);
std::string upload_pending_name = outfit_id.asString();
std::string upload_pending_desc = "";
upload_new_resource(filename, // file
upload_pending_name,
upload_pending_desc,
0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
LLFloaterPerms::getNextOwnerPerms("Uploads"),
LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"),
upload_pending_name, LLAssetStorage::LLStoreAssetCallback(), expected_upload_cost, nruserdata, false);
mOutfitLinkPending = outfit_id;
}
delete unit;
}
void LLOutfitGallery::linkPhotoToOutfit(LLUUID photo_id, LLUUID outfit_id)
{
LLPointer<LLInventoryCallback> cb = new LLUpdateGalleryOnPhotoLinked();
link_inventory_object(outfit_id, photo_id, cb);
}
bool LLOutfitGallery::checkRemovePhoto(LLUUID outfit_id)
{
LLAppearanceMgr::instance().removeOutfitPhoto(outfit_id);
return true;
}
void LLUpdateGalleryOnPhotoLinked::fire(const LLUUID& inv_item_id)
{
}
@ -1270,151 +1037,3 @@ LLUUID LLOutfitGallery::getDefaultPhoto()
return LLUUID();
}
void LLOutfitGallery::onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id)
{
LLUUID selected_outfit_id = getSelectedOutfitUUID();
if (selected_outfit_id.isNull())
{
return;
}
LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
if (floaterp && op == LLTextureCtrl::TEXTURE_SELECT)
{
LLUUID image_item_id;
if (id.notNull())
{
image_item_id = id;
}
else
{
image_item_id = floaterp->findItemID(floaterp->getAssetID(), FALSE, TRUE);
if (image_item_id.isNull())
{
LL_WARNS() << "id or image_item_id is NULL!" << LL_ENDL;
return;
}
}
std::string image_load_error;
S32 max_width = MAX_OUTFIT_PHOTO_WIDTH;
S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT;
if (mTextureSelected.isNull() ||
mTextureSelected->getFullWidth() == 0 ||
mTextureSelected->getFullHeight() == 0)
{
image_load_error = LLTrans::getString("outfit_photo_verify_dimensions_error");
LL_WARNS() << "Cannot verify selected texture dimensions" << LL_ENDL;
return;
}
S32 width = mTextureSelected->getFullWidth();
S32 height = mTextureSelected->getFullHeight();
if ((width > max_width) || (height > max_height))
{
LLStringUtil::format_map_t args;
args["WIDTH"] = llformat("%d", max_width);
args["HEIGHT"] = llformat("%d", max_height);
image_load_error = LLTrans::getString("outfit_photo_select_dimensions_error", args);
}
if (!image_load_error.empty())
{
LLSD subst;
subst["REASON"] = image_load_error;
LLNotificationsUtil::add("OutfitPhotoLoadError", subst);
return;
}
checkRemovePhoto(selected_outfit_id);
linkPhotoToOutfit(image_item_id, selected_outfit_id);
}
}
void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id)
{
if (selected_outfit_id.notNull())
{
// show hourglass cursor when loading inventory window
// because inventory construction is slooow
getWindow()->setCursor(UI_CURSOR_WAIT);
LLFloater* floaterp = mFloaterHandle.get();
// Show the dialog
if (floaterp)
{
floaterp->openFloater();
}
else
{
floaterp = new LLFloaterTexturePicker(
this,
getPhotoAssetId(selected_outfit_id),
getPhotoAssetId(selected_outfit_id),
getPhotoAssetId(selected_outfit_id),
FALSE,
TRUE,
LLTrans::getString("TexturePickerOutfitHeader"), // "SELECT PHOTO", // <FS:Ansariel> Localizable floater header
PERM_NONE,
PERM_NONE,
PERM_NONE,
FALSE,
NULL);
mFloaterHandle = floaterp->getHandle();
mTextureSelected = NULL;
LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
if (texture_floaterp)
{
texture_floaterp->setTextureSelectedCallback(boost::bind(&LLOutfitGallery::onTextureSelectionChanged, this, _1));
texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2));
texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1));
texture_floaterp->setLocalTextureEnabled(FALSE);
texture_floaterp->setBakeTextureEnabled(FALSE);
texture_floaterp->setCanApply(false, true);
}
floaterp->openFloater();
}
floaterp->setFocus(TRUE);
}
}
void LLOutfitGallery::onTakeSnapshot(LLUUID selected_outfit_id)
{
LLFloaterReg::toggleInstanceOrBringToFront("simple_outfit_snapshot");
LLFloaterSimpleOutfitSnapshot* snapshot_floater = LLFloaterSimpleOutfitSnapshot::getInstance();
if (snapshot_floater)
{
snapshot_floater->setOutfitID(selected_outfit_id);
snapshot_floater->getInstance()->setGallery(this);
}
}
void LLOutfitGallery::onBeforeOutfitSnapshotSave()
{
LLUUID selected_outfit_id = getSelectedOutfitUUID();
if (!selected_outfit_id.isNull())
{
checkRemovePhoto(selected_outfit_id);
updateSnapshotFolderObserver();
}
}
void LLOutfitGallery::onAfterOutfitSnapshotSave()
{
LLUUID selected_outfit_id = getSelectedOutfitUUID();
if (!selected_outfit_id.isNull())
{
mOutfitLinkPending = selected_outfit_id;
}
}
void LLOutfitGallery::onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture)
{
mTextureSelected = texture;
}

View File

@ -33,7 +33,6 @@
#include "lllayoutstack.h"
#include "lloutfitslist.h"
#include "llpanelappearancetab.h"
#include "lltexturectrl.h"
#include "llviewertexture.h"
#include <vector>
@ -106,14 +105,8 @@ public:
void updateMessageVisibility();
bool hasDefaultImage(const LLUUID& outfit_cat_id);
void refreshTextures(const LLUUID& category_id);
void refreshOutfit(const LLUUID& category_id);
void onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id);
void onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture);
void onBeforeOutfitSnapshotSave();
void onAfterOutfitSnapshotSave();
protected:
/*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id);
/*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid);
@ -127,14 +120,10 @@ protected:
void applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring);
private:
void loadPhotos();
void uploadPhoto(LLUUID outfit_id);
void uploadOutfitImage(const std::vector<std::string>& filenames, LLUUID outfit_id);
void updateSnapshotFolderObserver();
LLUUID getPhotoAssetId(const LLUUID& outfit_id);
LLUUID getDefaultPhoto();
void linkPhotoToOutfit(LLUUID outfit_id, LLUUID photo_id);
bool checkRemovePhoto(LLUUID outfit_id);
void addToGallery(LLOutfitGalleryItem* item);
void removeFromGalleryLast(LLOutfitGalleryItem* item);
void removeFromGalleryMiddle(LLOutfitGalleryItem* item);
@ -190,8 +179,6 @@ private:
LLListContextMenu* mOutfitGalleryMenu;
LLHandle<LLFloater> mFloaterHandle;
typedef std::map<LLUUID, LLOutfitGalleryItem*> outfit_map_t;
typedef outfit_map_t::value_type outfit_map_value_t;
outfit_map_t mOutfitMap;
@ -215,10 +202,7 @@ protected:
/* virtual */ LLContextMenu* createMenu();
bool onEnable(LLSD::String param);
bool onVisible(LLSD::String param);
void onUploadPhoto(const LLUUID& outfit_cat_id);
void onSelectPhoto(const LLUUID& outfit_cat_id);
void onRemovePhoto(const LLUUID& outfit_cat_id);
void onTakeSnapshot(const LLUUID& outfit_cat_id);
void onThumbnail(const LLUUID& outfit_cat_id);
void onCreate(const LLSD& data);
void onRemoveOutfit(const LLUUID& outfit_cat_id);
void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id);
@ -236,10 +220,6 @@ public:
protected:
/*virtual*/ void onUpdateItemsVisibility();
private:
/*virtual*/ void onUploadFoto();
/*virtual*/ void onSelectPhoto();
/*virtual*/ void onTakeSnapshot();
/*virtual*/ void onRemovePhoto();
/*virtual*/ void onChangeSortOrder();
bool hasDefaultImage();

View File

@ -35,7 +35,7 @@
#include "llaccordionctrltab.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "llagentbenefits.h"
#include "llfloaterreg.h"
#include "llfloatersidepanelcontainer.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
@ -1255,10 +1255,7 @@ LLOutfitListGearMenuBase::LLOutfitListGearMenuBase(LLOutfitListBase* olist)
registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenuBase::onAdd, this));
registrar.add("Gear.UploadPhoto", boost::bind(&LLOutfitListGearMenuBase::onUploadFoto, this));
registrar.add("Gear.SelectPhoto", boost::bind(&LLOutfitListGearMenuBase::onSelectPhoto, this));
registrar.add("Gear.TakeSnapshot", boost::bind(&LLOutfitListGearMenuBase::onTakeSnapshot, this));
registrar.add("Gear.RemovePhoto", boost::bind(&LLOutfitListGearMenuBase::onRemovePhoto, this));
registrar.add("Gear.Thumbnail", boost::bind(&LLOutfitListGearMenuBase::onThumbnail, this));
registrar.add("Gear.SortByName", boost::bind(&LLOutfitListGearMenuBase::onChangeSortOrder, this));
enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenuBase::onEnable, this, _2));
@ -1375,7 +1372,6 @@ bool LLOutfitListGearMenuBase::onEnable(LLSD::String param)
bool LLOutfitListGearMenuBase::onVisible(LLSD::String param)
{
getMenu()->getChild<LLUICtrl>("upload_photo")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()));
const LLUUID& selected_outfit_id = getSelectedOutfitID();
if (selected_outfit_id.isNull()) // no selection or invalid outfit selected
{
@ -1394,24 +1390,11 @@ bool LLOutfitListGearMenuBase::onVisible(LLSD::String param)
return true;
}
void LLOutfitListGearMenuBase::onUploadFoto()
void LLOutfitListGearMenuBase::onThumbnail()
{
}
void LLOutfitListGearMenuBase::onSelectPhoto()
{
}
void LLOutfitListGearMenuBase::onTakeSnapshot()
{
}
void LLOutfitListGearMenuBase::onRemovePhoto()
{
const LLUUID& selected_outfit_id = getSelectedOutfitID();
LLSD data(selected_outfit_id);
LLFloaterReg::showInstance("change_item_thumbnail", data);
}
void LLOutfitListGearMenuBase::onChangeSortOrder()
@ -1431,10 +1414,7 @@ void LLOutfitListGearMenu::onUpdateItemsVisibility()
if (!mMenu) return;
mMenu->setItemVisible("expand", TRUE);
mMenu->setItemVisible("collapse", TRUE);
mMenu->setItemVisible("upload_photo", FALSE);
mMenu->setItemVisible("select_photo", FALSE);
mMenu->setItemVisible("take_snapshot", FALSE);
mMenu->setItemVisible("remove_photo", FALSE);
mMenu->setItemVisible("thumbnail", FALSE); // Never visible?
mMenu->setItemVisible("sepatator3", FALSE);
mMenu->setItemVisible("sort_folders_by_name", FALSE);
LLOutfitListGearMenuBase::onUpdateItemsVisibility();

View File

@ -170,10 +170,7 @@ public:
protected:
virtual void onUpdateItemsVisibility();
virtual void onUploadFoto();
virtual void onSelectPhoto();
virtual void onTakeSnapshot();
virtual void onRemovePhoto();
virtual void onThumbnail();
virtual void onChangeSortOrder();
const LLUUID& getSelectedOutfitID();

View File

@ -38,7 +38,6 @@
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventorypanel.h"
#include "llfiltereditor.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterreg.h"
@ -129,6 +128,8 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
mMenuAddHandle(),
mNeedUploadCost(true),
mMenuViewDefault(NULL),
mSingleFolderMode(false),
mFolderRootChangedConnection(),
mViewMenuButton(nullptr), // <FS:Ansariel> Keep better inventory layout
mSearchTypeCombo(NULL) // <FS:Ansariel> Properly initialize this
{
@ -176,6 +177,13 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
mEnableCallbackRegistrar.add("Inventory.CoalescedObjects.Check", boost::bind(&LLPanelMainInventory::isCoalescedObjectsChecked, this, _2));
// </FS:Zi>
// <FS:Ansariel> Register all callback handlers early
mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Visible", boost::bind(&LLPanelMainInventory::isActionVisible, this, _2));
// </FS:Ansariel>
mSavedFolderState = new LLSaveFolderState();
mSavedFolderState->setApply(FALSE);
@ -354,6 +362,10 @@ BOOL LLPanelMainInventory::postBuild()
//mViewMenuButton = getChild<LLMenuButton>("view_btn");
mViewMenuButton = findChild<LLMenuButton>("view_btn");
mSingleFolderPanelInventory = getChild<LLInventorySingleFolderPanel>("single_folder_inv");
mFolderRootChangedConnection = mSingleFolderPanelInventory->setRootChangedCallback(boost::bind(&LLPanelMainInventory::updateTitle, this));
mSingleFolderPanelInventory->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mSingleFolderPanelInventory, _1, _2));
initListCommandsHandlers();
const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost());
const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost());
@ -436,6 +448,11 @@ LLPanelMainInventory::~LLPanelMainInventory( void )
menu->die();
mMenuAddHandle.markDead();
}
if (mFolderRootChangedConnection.connected())
{
mFolderRootChangedConnection.disconnect();
}
}
LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel()
@ -511,10 +528,17 @@ void LLPanelMainInventory::closeAllFolders()
getPanel()->getRootFolder()->closeAllFolders();
}
S32 get_instance_num()
{
static S32 instance_num = 0;
instance_num = (instance_num + 1) % S32_MAX;
return instance_num;
}
void LLPanelMainInventory::newWindow()
{
static S32 instance_num = 0;
instance_num = (instance_num + 1) % S32_MAX;
S32 instance_num = get_instance_num();
if (!gAgentCamera.cameraMouselook())
{
@ -522,13 +546,48 @@ void LLPanelMainInventory::newWindow()
}
}
void LLPanelMainInventory::newFolderWindow(const LLUUID& folder_id)
{
S32 instance_num = get_instance_num();
LLFloaterSidePanelContainer* inventory_container = LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num));
if(inventory_container)
{
LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(inventory_container->findChild<LLPanel>("main_panel", true));
if (sidepanel_inventory)
{
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
if (main_inventory)
{
main_inventory->onViewModeClick();
if(folder_id.notNull())
{
main_inventory->setSingleFolderViewRoot(folder_id);
}
}
}
}
}
void LLPanelMainInventory::doCreate(const LLSD& userdata)
{
// <FS:Ansariel> FIRE-20108: Can't create new folder in secondary inventory if view is filtered
//reset_inventory_filter();
onFilterEdit("");
// </FS:Ansariel>
menu_create_inventory_item(getPanel(), NULL, userdata);
if(mSingleFolderMode)
{
LLFolderViewItem* current_folder = getActivePanel()->getRootFolder();
if (current_folder)
{
LLFolderBridge* bridge = (LLFolderBridge*)current_folder->getViewModelItem();
menu_create_inventory_item(getPanel(), bridge, userdata);
}
}
else
{
menu_create_inventory_item(getPanel(), NULL, userdata);
}
}
void LLPanelMainInventory::resetFilters()
@ -713,7 +772,7 @@ void LLPanelMainInventory::onClearSearch()
}
// re-open folders that were initially open in case filter was active
if (mActivePanel && (mFilterSubString.size() || initially_active))
if (mActivePanel && (mFilterSubString.size() || initially_active) && !mSingleFolderMode)
{
mSavedFolderState->setApply(TRUE);
mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
@ -724,7 +783,7 @@ void LLPanelMainInventory::onClearSearch()
mFilterSubString = "";
// <FS:Ansariel> FIRE-22509: Only apply inbox filter on primary inventory window
//LLSidepanelInventory * sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
//LLSidepanelInventory * sidepanel_inventory = getParentSidepanelInventory();
//if (sidepanel_inventory)
//{
// LLPanelMarketplaceInbox* inbox_panel = sidepanel_inventory->getChild<LLPanelMarketplaceInbox>("marketplace_inbox");
@ -798,7 +857,7 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string )
// </FS:Ansariel> Separate search for inventory tabs from Satomi Ahn (FIRE-913 & FIRE-6862)
// <FS:Ansariel> FIRE-22509: Only apply inbox filter on primary inventory window
//LLSidepanelInventory * sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
//LLSidepanelInventory * sidepanel_inventory = getParentSidepanelInventory();
//if (sidepanel_inventory)
//{
// LLPanelMarketplaceInbox* inbox_panel = sidepanel_inventory->getChild<LLPanelMarketplaceInbox>("marketplace_inbox");
@ -1629,6 +1688,10 @@ void LLPanelMainInventory::initListCommandsHandlers()
{
childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this)); // <FS:Ansariel> Keep better inventory layout
childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
childSetAction("view_mode_btn", boost::bind(&LLPanelMainInventory::onViewModeClick, this));
childSetAction("up_btn", boost::bind(&LLPanelMainInventory::onUpFolderClicked, this));
childSetAction("back_btn", boost::bind(&LLPanelMainInventory::onBackFolderClicked, this));
childSetAction("forward_btn", boost::bind(&LLPanelMainInventory::onForwardFolderClicked, this));
// <FS:Ansariel> Keep better inventory layout
mTrashButton = getChild<LLDragAndDropButton>("trash_btn");
@ -1639,9 +1702,12 @@ void LLPanelMainInventory::initListCommandsHandlers()
));
// </FS:Ansariel>
mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
// <FS:Ansariel> Moved to constructor to register early
//mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
//mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
//mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
//mEnableCallbackRegistrar.add("Inventory.GearDefault.Visible", boost::bind(&LLPanelMainInventory::isActionVisible, this, _2));
// </FS:Ansariel>
mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_TOP_LEFT, true);
mMenuViewDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_view_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
@ -1681,6 +1747,64 @@ void LLPanelMainInventory::onAddButtonClick()
}
}
void LLPanelMainInventory::onViewModeClick()
{
mSingleFolderMode = !mSingleFolderMode;
getChild<LLPanel>("default_inventory_panel")->setVisible(!mSingleFolderMode);
getChild<LLPanel>("single_folder_inventory")->setVisible(mSingleFolderMode);
getChild<LLLayoutPanel>("nav_buttons")->setVisible(mSingleFolderMode);
getChild<LLButton>("view_mode_btn")->setImageOverlay(mSingleFolderMode ? getString("default_mode_btn") : getString("single_folder_mode_btn"));
// <FS:Ansariel> Disable Expand/Collapse buttons in single folder mode
getChild<LLLayoutPanel>("collapse_expand_buttons")->setVisible(!mSingleFolderMode);
mActivePanel = mSingleFolderMode ? getChild<LLInventoryPanel>("single_folder_inv") : (LLInventoryPanel*)getChild<LLTabContainer>("inventory filter tabs")->getCurrentPanel();
updateTitle();
LLSidepanelInventory* sidepanel_inventory = getParentSidepanelInventory();
if (sidepanel_inventory)
{
if(mSingleFolderMode)
{
sidepanel_inventory->hideInbox();
}
else
{
sidepanel_inventory->toggleInbox();
}
}
}
void LLPanelMainInventory::onUpFolderClicked()
{
const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot());
if (cat)
{
if (cat->getParentUUID().notNull())
{
mSingleFolderPanelInventory->changeFolderRoot(cat->getParentUUID());
}
}
}
void LLPanelMainInventory::onBackFolderClicked()
{
mSingleFolderPanelInventory->onBackwardFolder();
}
void LLPanelMainInventory::onForwardFolderClicked()
{
mSingleFolderPanelInventory->onForwardFolder();
}
void LLPanelMainInventory::setSingleFolderViewRoot(const LLUUID& folder_id)
{
mSingleFolderPanelInventory->changeFolderRoot(folder_id);
mSingleFolderPanelInventory->clearNavigationHistory();
}
void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
{
if (menu)
@ -1731,6 +1855,27 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
return;
const std::string command_name = userdata.asString();
if (command_name == "new_single_folder_window")
{
newFolderWindow(LLUUID());
}
if ((command_name == "open_in_current_window") || (command_name == "open_in_new_window"))
{
LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
if (!current_item)
{
return;
}
const LLUUID& folder_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();
if((command_name == "open_in_current_window"))
{
mSingleFolderPanelInventory->changeFolderRoot(folder_id);
}
if((command_name == "open_in_new_window"))
{
newFolderWindow(folder_id);
}
}
if (command_name == "new_window")
{
newWindow();
@ -2003,6 +2148,33 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
return TRUE;
}
bool LLPanelMainInventory::isActionVisible(const LLSD& userdata)
{
const std::string param_str = userdata.asString();
if (param_str == "single_folder_view")
{
return mSingleFolderMode;
}
if (param_str == "multi_folder_view")
{
return !mSingleFolderMode;
}
if (param_str == "open_folder" || param_str == "open_new_folder")
{
if (!mSingleFolderMode && (param_str == "open_folder")) return false;
LLFolderView* root = getActivePanel()->getRootFolder();
std::set<LLFolderViewItem*> selection_set = root->getSelectionList();
if (selection_set.size() != 1) return false;
LLFolderViewItem* current_item = *selection_set.begin();
if (!current_item) return false;
const LLUUID& folder_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();
return (gInventory.getCategory(folder_id) != NULL);
}
return true;
}
BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
{
U32 sort_order_mask = getActivePanel()->getSortOrder();
@ -2047,6 +2219,19 @@ BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) != 0;
}
if (command_name == "list_view")
{
return true;
}
if (command_name == "gallery_view")
{
return false;
}
if (command_name == "combination_view")
{
return false;
}
if (command_name == "add_objects_on_double_click")
{
return gSavedSettings.getBOOL("FSDoubleClickAddInventoryObjects");
@ -2267,5 +2452,34 @@ bool LLPanelMainInventory::hasSettingsInventory()
return LLEnvironment::instance().isInventoryEnabled();
}
void LLPanelMainInventory::updateTitle()
{
LLFloater* inventory_floater = gFloaterView->getParentFloater(this);
if(inventory_floater)
{
if(mSingleFolderMode)
{
const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot());
if (cat)
{
inventory_floater->setTitle(cat->getName());
}
}
else
{
inventory_floater->setTitle(getString("inventory_title"));
}
}
}
LLSidepanelInventory* LLPanelMainInventory::getParentSidepanelInventory()
{
LLFloaterSidePanelContainer* inventory_container = dynamic_cast<LLFloaterSidePanelContainer*>(gFloaterView->getParentFloater(this));
if(inventory_container)
{
return dynamic_cast<LLSidepanelInventory*>(inventory_container->findChild<LLPanel>("main_panel", true));
}
return NULL;
}
// List Commands //
////////////////////////////////////////////////////////////////////////////////

View File

@ -31,6 +31,7 @@
#include "llpanel.h"
#include "llinventoryfilter.h"
#include "llinventoryobserver.h"
#include "llinventorypanel.h"
#include "lldndbutton.h"
#include "llfolderview.h"
@ -44,6 +45,7 @@ class LLTabContainer;
class LLFloaterInventoryFinder;
class LLMenuButton;
class LLMenuGL;
class LLSidepanelInventory;
class LLToggleableMenu;
class LLFloater;
class LLComboBox; // <FS:Zi> Filter dropdown
@ -99,10 +101,17 @@ public:
void setFocusFilterEditor();
static void newWindow();
static void newFolderWindow(const LLUUID& folder_id);
void toggleFindOptions();
void resetFilters();
void onViewModeClick();
void onUpFolderClicked();
void onBackFolderClicked();
void onForwardFolderClicked();
void setSingleFolderViewRoot(const LLUUID& folder_id);
bool isSingleFolderMode() { return mSingleFolderMode; }
// <FS:Zi> Filter dropdown
void onFilterTypeSelected(const std::string& filter_type_name);
@ -156,6 +165,8 @@ protected:
void onSelectSearchType();
void updateSearchTypeCombo();
LLSidepanelInventory* getParentSidepanelInventory();
private:
LLFloaterInventoryFinder* getFinder();
@ -175,12 +186,16 @@ private:
std::string mCategoryCountString;
LLComboBox* mSearchTypeCombo;
bool mSingleFolderMode;
LLInventorySingleFolderPanel* mSingleFolderPanelInventory;
// <FS:Zi> Filter dropdown
LLComboBox* mFilterComboBox;
std::map<std::string,U64> mFilterMap; // contains name-to-number mapping for dropdown filter types
U64 mFilterMask; // contains the cumulated bit filter for all dropdown filter types
// </FS:Zi> Filter dropdown
boost::signals2::connection mFolderRootChangedConnection;
//////////////////////////////////////////////////////////////////////////////////
// List Commands //
@ -194,6 +209,7 @@ protected:
BOOL isActionEnabled(const LLSD& command_name);
BOOL isActionChecked(const LLSD& userdata);
void onCustomAction(const LLSD& command_name);
bool isActionVisible(const LLSD& userdata);
// <FS:Zi> FIRE-31369: Add inventory filter for coalesced objects
void onCoalescedObjectsToggled(const LLSD& userdata);
@ -218,6 +234,7 @@ protected:
// <FS:Ansariel> Keep better inventory layout
bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
static bool hasSettingsInventory();
void updateTitle();
/**
* Set upload cost in "Upload" sub menu.
*/

View File

@ -132,6 +132,7 @@ public:
virtual BOOL canOpenItem() const { return FALSE; }
virtual void closeItem() {}
virtual void selectItem() {}
virtual void navigateToFolder() {}
virtual BOOL isItemRenameable() const;
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL isItemMovable() const;

View File

@ -379,7 +379,7 @@ LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::stri
httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
LL_WARNS("AvatarProperties") << result << LL_ENDL;
LL_DEBUGS("AvatarProperties") << result << LL_ENDL;
if (!status)
{
@ -1904,15 +1904,20 @@ void LLProfileImagePicker::notify(const std::vector<std::string>& filenames)
const S32 MAX_DIM = 256;
if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM))
{
//todo: image not supported notification
LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", failed to open image" << LL_ENDL;
LLSD notif_args;
notif_args["REASON"] = LLImage::getLastError().c_str();
LLNotificationsUtil::add("CannotUploadTexture", notif_args);
LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", " << notif_args["REASON"].asString() << LL_ENDL;
return;
}
std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP);
if (cap_url.empty())
{
LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", no cap found" << LL_ENDL;
LLSD args;
args["CAPABILITY"] = PROFILE_IMAGE_UPLOAD_CAP;
LLNotificationsUtil::add("RegionCapabilityRequestError", args);
LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", no cap found" << LL_ENDL;
return;
}

View File

@ -127,6 +127,7 @@ LLSidepanelInventory::LLSidepanelInventory()
, mInboxEnabled(false)
, mCategoriesObserver(NULL)
, mInboxAddedObserver(NULL)
, mInboxLayoutPanel(NULL)
{
//buildFromFile( "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
}
@ -134,14 +135,12 @@ LLSidepanelInventory::LLSidepanelInventory()
LLSidepanelInventory::~LLSidepanelInventory()
{
// <FS:Ansariel> FIRE-17603: Received Items button sometimes vanishing
//LLLayoutPanel* inbox_layout_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
LLLayoutPanel* inbox_layout_panel = findChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
if (inbox_layout_panel)
if (mInboxLayoutPanel)
{
// </FS:Ansariel>
// Save the InventoryMainPanelHeight in settings per account
gSavedPerAccountSettings.setS32("InventoryInboxHeight", inbox_layout_panel->getTargetDim());
gSavedPerAccountSettings.setS32("InventoryInboxHeight", mInboxLayoutPanel->getTargetDim());
// <FS:Ansariel> FIRE-17603: Received Items button sometimes vanishing
}
// </FS:Ansariel>
@ -209,11 +208,11 @@ BOOL LLSidepanelInventory::postBuild()
bool is_inbox_collapsed = !inbox_button->getToggleState();
// Restore the collapsed inbox panel state
LLLayoutPanel* inbox_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
inv_stack->collapsePanel(inbox_panel, is_inbox_collapsed);
mInboxLayoutPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
inv_stack->collapsePanel(mInboxLayoutPanel, is_inbox_collapsed);
if (!is_inbox_collapsed)
{
inbox_panel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight"));
mInboxLayoutPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight"));
}
// Set the inbox visible based on debug settings (final setting comes from http request below)
@ -329,16 +328,29 @@ void LLSidepanelInventory::enableInbox(bool enabled)
{
mInboxEnabled = enabled;
LLLayoutPanel * inbox_layout_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
if(!enabled || !mPanelMainInventory->isSingleFolderMode())
{
toggleInbox();
}
}
void LLSidepanelInventory::hideInbox()
{
if (mInboxLayoutPanel) // <FS:Ansariel> Inbox panel randomly shown on secondary inventory window
mInboxLayoutPanel->setVisible(false);
}
void LLSidepanelInventory::toggleInbox()
{
// <FS:Ansariel> Optional hiding of Received Items folder aka Inbox
//inbox_layout_panel->setVisible(enabled);
inbox_layout_panel->setVisible(enabled && (!gSavedSettings.getBOOL("FSShowInboxFolder") || gSavedSettings.getBOOL("FSAlwaysShowInboxButton"))
//mInboxLayoutPanel->setVisible(mInboxEnabled);
if (mInboxLayoutPanel)
mInboxLayoutPanel->setVisible(mInboxEnabled && (!gSavedSettings.getBOOL("FSShowInboxFolder") || gSavedSettings.getBOOL("FSAlwaysShowInboxButton"))
// <FS:CR> Show Received Items panel only in Second Life
#ifdef OPENSIM
&& LLGridManager::getInstance()->isInSecondLife()
#endif // OPENSIM
);
// </FS:CR>
}
// <FS:Ansariel> Optional hiding of Received Items folder aka Inbox
@ -375,25 +387,24 @@ void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id)
void LLSidepanelInventory::onToggleInboxBtn()
{
LLButton* inboxButton = getChild<LLButton>(INBOX_BUTTON_NAME);
LLLayoutPanel* inboxPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
const bool inbox_expanded = inboxButton->getToggleState();
// Expand/collapse the indicated panel
inv_stack->collapsePanel(inboxPanel, !inbox_expanded);
inv_stack->collapsePanel(mInboxLayoutPanel, !inbox_expanded);
if (inbox_expanded)
{
inboxPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight"));
if (inboxPanel->isInVisibleChain())
mInboxLayoutPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight"));
if (mInboxLayoutPanel->isInVisibleChain())
{
gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());
}
}
else
{
gSavedPerAccountSettings.setS32("InventoryInboxHeight", inboxPanel->getTargetDim());
gSavedPerAccountSettings.setS32("InventoryInboxHeight", mInboxLayoutPanel->getTargetDim());
}
}

View File

@ -74,6 +74,8 @@ public:
void onToggleInboxBtn();
void enableInbox(bool enabled);
void toggleInbox();
void hideInbox();
// <FS:Ansariel> Optional hiding of Received Items folder aka Inbox
void refreshInboxVisibility();
@ -104,6 +106,8 @@ private:
LLHandle<LLInventoryPanel> mInventoryPanelInbox;
LLPanelMainInventory* mPanelMainInventory;
LLLayoutPanel* mInboxLayoutPanel;
protected:
public:
void onBackButtonClicked();

View File

@ -36,6 +36,7 @@
#include "llcallbacklist.h"
#include "llcombobox.h"
#include "llfloater.h"
#include "llfloaterreg.h"
#include "llgroupactions.h"
#include "llgroupmgr.h"
#include "lliconctrl.h"
@ -163,6 +164,8 @@ BOOL LLSidepanelItemInfo::postBuild()
getChild<LLLineEditor>("LabelItemName")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this));
getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this));
// Thumnail edition
getChild<LLUICtrl>("change_thumbnail_btn")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onEditThumbnail, this));
// acquired date
// owner permissions
// Permissions debug text
@ -800,7 +803,7 @@ void LLSidepanelItemInfo::changed(U32 mask)
const LLUUID& item_id = getItemID();
if (getObjectID().notNull() || item_id.isNull())
{
// Tasl inventory or not set up yet
// Task inventory or not set up yet
return;
}
@ -1087,7 +1090,14 @@ void LLSidepanelItemInfo::updatePermissions()
}
}
// static
void LLSidepanelItemInfo::onEditThumbnail()
{
LLSD data;
data["task_id"] = mObjectID;
data["item_id"] = mItemID;
LLFloaterReg::showInstance("change_item_thumbnail", data);
}
void LLSidepanelItemInfo::onCommitSaleInfo(LLUICtrl* ctrl)
{
if (ctrl)

View File

@ -119,6 +119,7 @@ protected:
void onCommitDescription();
void onCommitPermissions(LLUICtrl* ctrl);
void updatePermissions();
void onEditThumbnail();
void onCommitSaleInfo(LLUICtrl* ctrl);
void updateSaleInfo();
void onCommitChanges(LLPointer<LLViewerInventoryItem> item);

View File

@ -52,6 +52,7 @@
#include "llviewercontrol.h"
#include "llviewermenufile.h" // upload_new_resource()
#include "llviewerstats.h"
#include "llviewertexturelist.h"
#include "llwindow.h"
#include "llworld.h"
#include <boost/filesystem.hpp>
@ -986,6 +987,31 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
return mPreviewImageEncoded;
}
bool LLSnapshotLivePreview::createUploadFile(const std::string &out_filename, const S32 max_image_dimentions)
{
// make a copy, since convertToUploadFile modifies raw image
LLPointer<LLImageRaw> raw_image = new LLImageRaw(
mPreviewImage->getData(),
mPreviewImage->getWidth(),
mPreviewImage->getHeight(),
mPreviewImage->getComponents());
LLPointer<LLImageJ2C> compressedImage = LLViewerTextureList::convertToUploadFile(raw_image, max_image_dimentions);
if (compressedImage.isNull())
{
compressedImage->setLastError("Couldn't convert the image to jpeg2000.");
LL_INFOS() << "Couldn't convert to j2c, file : " << out_filename << LL_ENDL;
return false;
}
if (!compressedImage->save(out_filename))
{
compressedImage->setLastError("Couldn't create the jpeg2000 image for upload.");
LL_INFOS() << "Couldn't create output file : " << out_filename << LL_ENDL;
return false;
}
return true;
}
// We actually estimate the data size so that we do not require actual compression when showing the preview
// Note : whenever formatted image is computed, mDataSize will be updated to reflect the true size
void LLSnapshotLivePreview::estimateDataSize()

View File

@ -109,6 +109,7 @@ public:
LLPointer<LLImageFormatted> getFormattedImage();
LLPointer<LLImageRaw> getEncodedImage();
bool createUploadFile(const std::string &out_file, const S32 max_image_dimentions);
/// Sets size of preview thumbnail image and the surrounding rect.
void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; }

View File

@ -56,6 +56,7 @@
#include "llfloaterbvhpreview.h"
#include "llfloatercamera.h"
#include "llfloatercamerapresets.h"
#include "llfloaterchangeitemthumbnail.h"
#include "llfloaterchatvoicevolume.h"
#include "llfloaterclassified.h"
#include "llfloaterconversationlog.h"
@ -103,7 +104,7 @@
#include "llfloaterobjectweights.h"
#include "llfloateropenobject.h"
#include "llfloateroutfitphotopreview.h"
#include "llfloatersimpleoutfitsnapshot.h"
#include "llfloatersimplesnapshot.h"
#include "llfloaterpathfindingcharacters.h"
#include "llfloaterpathfindingconsole.h"
#include "llfloaterpathfindinglinksets.h"
@ -396,6 +397,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("fs_camera_small", "floater_fs_camera_small.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCameraPresets>);
LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>);
LLFloaterReg::add("change_item_thumbnail", "floater_change_item_thumbnail.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChangeItemThumbnail>);
// <FS:Ansariel> [FS communication UI]
//LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater);
LLFloaterReg::add("fs_nearby_chat", "floater_fs_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterNearbyChat>);
@ -564,7 +566,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);
LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);
LLFloaterReg::add("simple_outfit_snapshot", "floater_simple_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSimpleOutfitSnapshot>);
LLFloaterReg::add("simple_snapshot", "floater_simple_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSimpleSnapshot>);
// <FS:CR> Search floater is deferred to login now so we can tell what grid we're in.
//LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>);

View File

@ -12549,6 +12549,7 @@ void initialize_menus()
view_listener_t::addMenu(new FSResetMeshLOD(), "Avatar.ResetMeshLOD");
commit.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow));
commit.add("Inventory.NewFolderWindow", boost::bind(&LLPanelMainInventory::newFolderWindow, LLUUID()));
enable.add("EnablePayObject", boost::bind(&enable_pay_object));
enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar));

View File

@ -38,7 +38,7 @@
#include "llfloatermap.h"
#include "llfloatermodelpreview.h"
#include "llfloatersnapshot.h"
#include "llfloatersimpleoutfitsnapshot.h"
#include "llfloatersimplesnapshot.h"
#include "llimage.h"
#include "llimagebmp.h"
#include "llimagepng.h"
@ -744,9 +744,7 @@ class LLFileEnableCloseAllWindows : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
LLFloaterSimpleOutfitSnapshot* floater_outfit_snapshot = LLFloaterSimpleOutfitSnapshot::findInstance();
bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain())
|| (floater_outfit_snapshot && floater_outfit_snapshot->isInVisibleChain());
bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain());
bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened;
return !open_children && !LLNotificationsUI::LLToast::isAlertToastShown();
}
@ -761,9 +759,6 @@ class LLFileCloseAllWindows : public view_listener_t
LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
if (floater_snapshot)
floater_snapshot->closeFloater(app_quitting);
LLFloaterSimpleOutfitSnapshot* floater_outfit_snapshot = LLFloaterSimpleOutfitSnapshot::findInstance();
if (floater_outfit_snapshot)
floater_outfit_snapshot->closeFloater(app_quitting);
if (gMenuHolder) gMenuHolder->hideMenus();
return true;
}

View File

@ -3258,6 +3258,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("InterestList");
capabilityNames.append("InventoryCategoryThumbnailUpload");
capabilityNames.append("InventoryItemThumbnailUpload");
capabilityNames.append("GetDisplayNames");
capabilityNames.append("GetExperiences");
capabilityNames.append("AgentExperiences");

View File

@ -24,6 +24,9 @@
name="ItemcountUnknown">
Fetched [ITEM_COUNT] Elements [FILTER]
</panel.string>
<panel.string name="inventory_title">Inventory</panel.string>
<panel.string name="default_mode_btn">Multi_Folder_Mode</panel.string>
<panel.string name="single_folder_mode_btn">Single_Folder_Mode</panel.string>
<menu_bar
follows="left|top"
@ -76,6 +79,53 @@
function="Floater.Toggle"
parameter="fs_protectedfolders" />
</menu_item_check>
<menu_item_separator>
<menu_item_separator.on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_separator>
<menu_item_check
label="List view"
layout="topleft"
name="list_view">
<menu_item_check.on_click
function="Inventory.GearDefault.Custom.Action"
parameter="list_view" />
<menu_item_check.on_check
function="Inventory.GearDefault.Check"
parameter="list_view" />
<menu_item_check.on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_check
label="Gallery view"
layout="topleft"
name="gallery_view">
<menu_item_check.on_click
function="Inventory.GearDefault.Custom.Action"
parameter="gallery_view" />
<menu_item_check.on_check
function="Inventory.GearDefault.Check"
parameter="gallery_view" />
<menu_item_check.on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_check
label="Combination view"
layout="topleft"
name="combination_view">
<menu_item_check.on_click
function="Inventory.GearDefault.Custom.Action"
parameter="combination_view" />
<menu_item_check.on_check
function="Inventory.GearDefault.Check"
parameter="combination_view" />
<menu_item_check.on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_separator />
<menu_item_check
label="Add objects on double click"
@ -115,13 +165,23 @@
label="Close All Folders">
<menu_item_call.on_click
function="Inventory.CloseAllFolders" />
<menu_item_call.on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_call>
<menu_item_separator />
<menu_item_separator>
<menu_item_separator.on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_separator>
<menu_item_call
name="inventory_empty_trash"
label="Empty Trash">
<menu_item_call.on_click
function="Inventory.EmptyTrash" />
<menu_item_call.on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_call>
</menu>
@ -363,6 +423,9 @@
<on_check
function="Inventory.SortBy.Check"
parameter="systemfolderstotop" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_check>
</menu>
@ -498,167 +561,304 @@
</menu>
</menu_bar>
<filter_editor
text_pad_left="4"
<layout_stack
follows="left|top|right"
height="23"
label="Filter Inventory"
layout="topleft"
height="25"
animate="false"
top_pad="0"
left="4"
max_length_chars="300"
highlight_text_field="true"
name="inventory search editor"
tool_tip="Type in one or more words to search for, separated by '+' "
top_pad="4"
right="-6" />
<button
name="collapse_btn"
image_overlay="MinusItem_Off"
width="18"
height="18"
left="4"
top_pad="4"
follows="top|left"
layout="topleft"/>
<button
name="expand_btn"
image_overlay="AddItem_Off"
width="18"
height="18"
left_pad="2"
follows="top|left"
layout="topleft" />
<text
name="filter_label"
value="Filter:"
width="40"
height="18"
left_pad="4"
top_delta="2"
follows="top|left"
layout="topleft" />
<combo_box
name="filter_combo_box"
right="-79"
height="18"
left_pad="4"
top_delta="-2"
follows="top|left|right"
layout="topleft">
<combo_box.item value="filter_type_all" label="All Types" />
<combo_box.item value="filter_separator" label="------------" enabled="false" />
<combo_box.item value="filter_type_animations" label="Animations" />
<combo_box.item value="filter_type_calling_cards" label="Calling Cards" />
<combo_box.item value="filter_type_clothing" label="Clothing / Body Parts" />
<combo_box.item value="filter_type_gestures" label="Gestures" />
<combo_box.item value="filter_type_landmarks" label="Landmarks" />
<combo_box.item value="filter_type_notecards" label="Notecards" />
<combo_box.item value="filter_type_objects" label="Objects" />
<combo_box.item value="filter_type_scripts" label="Scripts" />
<combo_box.item value="filter_type_sounds" label="Sounds" />
<combo_box.item value="filter_type_textures" label="Textures" />
<combo_box.item value="filter_type_snapshots" label="Snapshots" />
<combo_box.item value="filter_type_meshes" label="Meshes" />
<combo_box.item value="filter_type_settings" label="Settings" />
<combo_box.item value="filter_separator" label="------------" enabled="false" />
<combo_box.item value="filter_type_custom" label="Custom..." />
</combo_box>
<button
commit_callback.function="Inventory.ShowFilters"
name="filteroptions_btn"
image_overlay="Script_Config"
width="18"
height="18"
right="-59"
top_delta="0"
follows="top|right"
layout="topleft"/>
<menu_button
follows="top|right"
tool_tip="Show search visibility options"
height="18"
image_overlay="Inv_Toolbar_SearchVisibility"
layout="topleft"
right="-26"
top_delta="0"
name="options_visibility_btn"
width="31" />
<button
commit_callback.function="Inventory.ResetFilters"
name="resetfilters_btn"
image_overlay="StopReload_Off"
width="18"
height="18"
right="-6"
top_delta="0"
follows="top|right"
layout="topleft"/>
<tab_container
bg_alpha_color="DkGray"
bg_opaque_color="DkGray"
background_visible="false"
background_opaque="false"
follows="all"
halign="center"
height="322"
layout="topleft"
left="2"
name="inventory filter tabs"
open_tabs_on_drag_and_drop="true"
tab_group="1"
tab_position="top"
top_pad="4"
width="326">
<inventory_panel
right="-5"
name="nav_stack"
orientation="horizontal">
<layout_panel
border="false"
bevel_style="none"
bevel_style="in"
user_resize="false"
auto_resize="false"
height="25"
width="62"
name="nav_buttons"
visible="false">
<button
follows="top|left"
height="23"
image_selected="Single_Folder_Back"
image_pressed="Single_Folder_Back"
image_unselected="Single_Folder_Back"
scale_image="false"
layout="topleft"
left="0"
top="2"
name="back_btn"
tool_tip="Back"
width="20" />
<button
follows="top|left"
height="23"
image_selected="Single_Folder_Forward"
image_pressed="Single_Folder_Forward"
image_unselected="Single_Folder_Forward"
scale_image="false"
layout="topleft"
left_pad="1"
name="forward_btn"
tool_tip="Forward"
width="20" />
<button
follows="top|left"
height="23"
image_selected="Single_Folder_Up"
image_pressed="Single_Folder_Up"
image_unselected="Single_Folder_Up"
scale_image="false"
layout="topleft"
left_pad="1"
name="up_btn"
tool_tip="Go up one level"
width="20" />
</layout_panel>
<layout_panel
border="false"
bevel_style="in"
user_resize="false"
height="25"
width="324"
name="filter_panel"
visible="true">
<filter_editor
text_pad_left="4"
follows="left|top|right"
height="23"
label="Filter Inventory"
layout="topleft"
left="0"
max_length_chars="300"
highlight_text_field="true"
name="inventory search editor"
tool_tip="Type in one or more words to search for, separated by '+' "
top_pad="0"
right="-1" />
</layout_panel>
</layout_stack>
<layout_stack
follows="left|top|right"
height="18"
animate="false"
top_pad="0"
left="4"
right="-5"
name="ctrl_stack"
orientation="horizontal">
<layout_panel
border="false"
bevel_style="in"
user_resize="false"
auto_resize="false"
height="18"
width="38"
name="collapse_expand_buttons">
<button
name="collapse_btn"
image_overlay="MinusItem_Off"
width="18"
height="18"
left="0"
top="0"
follows="top|left"
layout="topleft"/>
<button
name="expand_btn"
image_overlay="AddItem_Off"
width="18"
height="18"
left_pad="2"
follows="top|left"
layout="topleft" />
</layout_panel>
<layout_panel
border="false"
bevel_style="in"
user_resize="false"
height="18"
width="200"
name="filter_ctrls">
<text
name="filter_label"
value="Filter:"
width="40"
height="18"
left="2"
top="2"
follows="top|left"
layout="topleft" />
<combo_box
name="filter_combo_box"
right="-75"
height="18"
left_pad="4"
top_delta="-2"
follows="top|left|right"
layout="topleft">
<combo_box.item value="filter_type_all" label="All Types" />
<combo_box.item value="filter_separator" label="------------" enabled="false" />
<combo_box.item value="filter_type_animations" label="Animations" />
<combo_box.item value="filter_type_calling_cards" label="Calling Cards" />
<combo_box.item value="filter_type_clothing" label="Clothing / Body Parts" />
<combo_box.item value="filter_type_gestures" label="Gestures" />
<combo_box.item value="filter_type_landmarks" label="Landmarks" />
<combo_box.item value="filter_type_notecards" label="Notecards" />
<combo_box.item value="filter_type_objects" label="Objects" />
<combo_box.item value="filter_type_scripts" label="Scripts" />
<combo_box.item value="filter_type_sounds" label="Sounds" />
<combo_box.item value="filter_type_textures" label="Textures" />
<combo_box.item value="filter_type_snapshots" label="Snapshots" />
<combo_box.item value="filter_type_meshes" label="Meshes" />
<combo_box.item value="filter_type_settings" label="Settings" />
<combo_box.item value="filter_separator" label="------------" enabled="false" />
<combo_box.item value="filter_type_custom" label="Custom..." />
</combo_box>
<button
commit_callback.function="Inventory.ShowFilters"
name="filteroptions_btn"
image_overlay="Script_Config"
width="18"
height="18"
right="-54"
top_delta="0"
follows="top|right"
layout="topleft"/>
<menu_button
follows="top|right"
tool_tip="Show search visibility options"
height="18"
image_overlay="Inv_Toolbar_SearchVisibility"
layout="topleft"
right="-21"
top_delta="0"
name="options_visibility_btn"
width="31" />
<button
commit_callback.function="Inventory.ResetFilters"
name="resetfilters_btn"
image_overlay="StopReload_Off"
width="18"
height="18"
right="-1"
top_delta="0"
follows="top|right"
layout="topleft"/>
</layout_panel>
</layout_stack>
<panel
follows="all"
halign="center"
height="319"
layout="topleft"
left="2"
name="default_inventory_panel"
top_pad="4"
width="326">
<tab_container
bg_alpha_color="DkGray"
bg_opaque_color="DkGray"
background_visible="false"
background_opaque="false"
follows="all"
halign="center"
height="319"
layout="topleft"
left="0"
name="inventory filter tabs"
open_tabs_on_drag_and_drop="true"
tab_group="1"
tab_position="top"
top="0"
width="326">
<inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Inventory"
help_topic="my_inventory_tab"
layout="topleft"
left="0"
name="All Items"
sort_order_setting="InventorySortOrder"
show_item_link_overlays="true"
top="16"
width="288"
scroll.reserve_scroll_corner="false"/>
<recent_inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Recent"
sort_order_setting="RecentItemsSortOrder"
help_topic="recent_inventory_tab"
layout="topleft"
left_delta="0"
name="Recent Items"
show_item_link_overlays="true"
width="288"
scroll.reserve_scroll_corner="false"/>
<worn_inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Worn"
help_topic="worn_inventory_tab"
layout="topleft"
left_delta="0"
name="Worn Items"
show_item_link_overlays="true"
width="288"
scroll.reserve_scroll_corner="false"/>
</tab_container>
</panel>
<panel
follows="all"
halign="center"
height="319"
layout="topleft"
left="2"
name="single_folder_inventory"
top_delta="0"
visible="false"
width="326">
<single_folder_inventory_panel
name="single_folder_inv"
show_empty_message="false"
follows="all"
height="338"
label="Inventory"
help_topic="my_inventory_tab"
layout="topleft"
left="0"
name="All Items"
sort_order_setting="InventorySortOrder"
show_item_link_overlays="true"
top="16"
width="288" />
<recent_inventory_panel
top="0"
top_pad="5"
height="319"
width="324"
layout="topleft"
background_visible="true"
border="false"
bevel_style="none"
follows="all"
height="338"
label="Recent"
sort_order_setting="RecentItemsSortOrder"
help_topic="recent_inventory_tab"
layout="topleft"
left_delta="0"
name="Recent Items"
show_item_link_overlays="true"
width="290" />
<worn_inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Worn"
help_topic="worn_inventory_tab"
layout="topleft"
left_delta="0"
name="Worn Items"
show_item_link_overlays="true"
width="290" />
</tab_container>
scroll.reserve_scroll_corner="false">
<item folder_indentation="0"/>
<folder
single_folder_mode="true"
folder_indentation="0"/>
</single_folder_inventory_panel>
</panel>
<panel
follows="left|right|bottom"
height="25"
@ -721,10 +921,10 @@
<button
follows="top|left"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_hover_unselected="Toolbar_Left_Over"
image_overlay="inventory_18"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
image_selected="Toolbar_Left_Selected"
image_unselected="Toolbar_Left_Off"
layout="topleft"
left="0"
name="new_inv_btn"
@ -736,6 +936,27 @@
parameter="secondary_inventory" />
</button>
</panel>
<panel
follows="top|left"
height="25"
layout="topleft"
left_pad="0"
name="view_mode_panel"
width="32">
<button
follows="top|left"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Single_Folder_Mode"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
left="0"
name="view_mode_btn"
tool_tip="Switch between views"
top="0"
width="31"/>
</panel>
<panel
follows="top|left|right"
height="25"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -275,10 +275,16 @@ with the same filename but different name
<texture name="Icon_Close_Foreground" file_name="windows/Icon_Close_Foreground.png" preload="true" />
<texture name="Icon_Close_Press" file_name="windows/Icon_Close_Press.png" preload="true" />
<texture name="Icon_Close_Toast" file_name="windows/Icon_Close_Toast.png" preload="true" />
<texture name="Icon_Copy" file_name="icons/copy_clipboard.png" preload="true" />
<texture name="Icon_Delete" file_name="icons/delete_icon.png" preload="true" />
<texture name="Icon_Dock_Foreground" file_name="windows/Icon_Dock_Foreground.png" preload="true" />
<texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" />
<texture name="Icon_File_Upload" file_name="icons/file_upload.png" preload="true" />
<texture name="Icon_For_Sale" file_name="icons/Icon_For_Sale.png" preload="false" />
<texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" />
@ -291,10 +297,16 @@ with the same filename but different name
<texture name="Icon_Minimize_Foreground" file_name="windows/Icon_Minimize_Foreground.png" preload="true" />
<texture name="Icon_Minimize_Press" file_name="windows/Icon_Minimize_Press.png" preload="true" />
<texture name="Icon_Paste" file_name="icons/paste_clipboard.png" preload="true" />
<texture name="Icon_Restore_Foreground" file_name="windows/Icon_Restore_Foreground.png" preload="false" />
<texture name="Icon_Restore_Press" file_name="windows/Icon_Restore_Press.png" preload="false" />
<texture name="Icon_Snapshot" file_name="icons/snapshot_icon.png" preload="true" />
<texture name="Icon_Use_Texture" file_name="icons/texture_icon.png" preload="true" />
<texture name="Icon_Snooze_Foreground" file_name="windows/Icon_Snooze_Foreground.png" preload="false" />
<texture name="Icon_Snooze_Press" file_name="windows/Icon_Snooze_Press.png" preload="false" />
@ -1048,6 +1060,12 @@ with the same filename but different name
<texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/>
<texture name="Icon_Attachment_Small" file_name="icons/Icon_Attachment_Small.png" preload="true"/>
<texture name="Icon_Attachment_Large" file_name="icons/Icon_Attachment_Large.png" preload="true"/>
<texture name="Single_Folder_Mode" file_name="icons/single_folder_mode.png" preload="true"/>
<texture name="Multi_Folder_Mode" file_name="icons/multi_folder_mode.png" preload="true"/>
<texture name="Single_Folder_Back" file_name="icons/single_folder_back.png" preload="true"/>
<texture name="Single_Folder_Forward" file_name="icons/single_folder_forward.png" preload="true"/>
<texture name="Single_Folder_Up" file_name="icons/single_folder_up.png" preload="true"/>
<!-- StarLight Textures -->

View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
can_resize="false"
height="366"
layout="topleft"
name="change_item_thumbnail"
help_topic="change_item_thumbnail"
title="Change Item Image"
width="319">
<floater.string
name="tooltip_upload_local">
Upload from computer
</floater.string>
<floater.string
name="tooltip_upload_snapshot">
Use snapshot tool
</floater.string>
<floater.string
name="tooltip_use_texture">
Choose texture
</floater.string>
<floater.string
name="tooltip_copy_to_clipboard">
Copy to clipboard
</floater.string>
<floater.string
name="tooltip_paste_from_clipboard">
Paste from clipboard
</floater.string>
<floater.string
name="tooltip_remove_image">
Remove image
</floater.string>
<icon
follows="top|left"
height="16"
image_name="Inv_Object"
layout="topleft"
left="10"
mouse_opaque="true"
name="item_type_icon"
top="4"
width="16" />
<text
follows="left|top|right"
font="SansSerif"
height="19"
layout="topleft"
top_delta="1"
left_pad="3"
max_length_bytes="127"
name="item_name"
width="286"/>
<thumbnail
name="item_thumbnail"
follows="top|left"
layout="topleft"
left="32"
top_pad="9"
height="256"
width="256"
/>
<button
follows="right|bottom"
layout="topleft"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Icon_File_Upload"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="upload_local"
left="38"
top_pad="9"
height="32"
width="32" />
<button
follows="right|bottom"
layout="topleft"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Icon_Snapshot"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="upload_snapshot"
left_pad="10"
top_delta="0"
height="32"
width="32" />
<button
follows="right|bottom"
layout="topleft"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Icon_Use_Texture"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="use_texture"
left_pad="10"
top_delta="0"
height="32"
width="32" />
<button
follows="right|bottom"
layout="topleft"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Icon_Copy"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="copy_to_clipboard"
left_pad="10"
top_delta="0"
height="32"
width="32" />
<button
follows="right|bottom"
layout="topleft"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Icon_Paste"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="paste_from_clipboard"
left_pad="10"
top_delta="0"
height="32"
width="32" />
<button
follows="right|bottom"
layout="topleft"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Icon_Delete"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="remove_image"
left_pad="10"
top_delta="0"
height="32"
width="32" />
<text
type="string"
halign="center"
length="1"
follows="left|top"
height="17"
layout="topleft"
left="5"
right="-5"
name="tooltip_text"
top_pad="12"
width="78">
tooltip
</text>
</floater>

View File

@ -2,17 +2,17 @@
<floater
positioning="cascading"
legacy_header_height="18"
can_minimize="true"
can_minimize="false"
can_resize="false"
can_close="true"
height="305"
layout="topleft"
name="simple_outfit_snapshot"
single_instance="true"
name="simple_snapshot"
single_instance="false"
help_topic="snapshot"
save_rect="true"
save_visibility="false"
title="Outfit Snapshot"
title="Item Snapshot"
width="351">
<ui_ctrl
layout="topleft"
@ -36,7 +36,7 @@
height="22"
layout="topleft"
left_pad="10"
label="Save (L$[UPLOAD_COST])"
label="Save"
name="save_btn"
width="90" />
<button

View File

@ -42,35 +42,11 @@
parameter="take_off" />
</menu_item_call>
<menu_item_call
label="Upload Photo (L$[UPLOAD_COST])"
layout="topleft"
name="upload_photo">
label="Image..."
layout="topleft"
name="thumbnail">
<on_click
function="Outfit.UploadPhoto" />
</menu_item_call>
<menu_item_call
label="Select Photo"
layout="topleft"
name="select_photo">
<on_click
function="Outfit.SelectPhoto" />
</menu_item_call>
<menu_item_call
label="Take a Snapshot"
layout="topleft"
name="take_snapshot">
<on_click
function="Outfit.TakeSnapshot" />
</menu_item_call>
<menu_item_call
label="Remove Photo"
layout="topleft"
name="remove_photo">
<on_click
function="Outfit.RemovePhoto" />
<on_visible
function="Outfit.OnVisible"
parameter="remove_photo" />
function="Outfit.Thumbnail" />
</menu_item_call>
<menu_item_separator name="sepatator1" />
<menu

View File

@ -612,6 +612,14 @@
function="Inventory.DoToSelected"
parameter="rename" />
</menu_item_call>
<menu_item_call
label="Image..."
layout="topleft"
name="thumbnail">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="thumbnail" />
</menu_item_call>
<menu_item_call
label="Protect"
layout="topleft"
@ -628,6 +636,14 @@
function="Inventory.DoToSelected"
parameter="unprotect_folder" />
</menu_item_call>
<menu_item_call
label="Reload Folder"
layout="topleft"
name="ReloadFolder">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="reload_folder" />
</menu_item_call>
<menu_item_call
label="Copy Asset UUID"
layout="topleft"
@ -636,6 +652,14 @@
function="Inventory.DoToSelected"
parameter="copy_uuid" />
</menu_item_call>
<menu_item_call
label="Restore to Last Position"
layout="topleft"
name="Restore to Last Position">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="restoreToWorld" />
</menu_item_call>
<menu_item_call
label="Show in Main View"
layout="topleft"
@ -652,25 +676,26 @@
function="Inventory.DoToSelected"
parameter="show_in_new_window" />
</menu_item_call>
<menu_item_call
label="Reload Folder"
layout="topleft"
name="ReloadFolder">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="reload_folder" />
</menu_item_call>
<menu_item_call
label="Restore to Last Position"
layout="topleft"
name="Restore to Last Position">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="restoreToWorld" />
</menu_item_call>
<menu_item_separator
layout="topleft"
name="Copy Separator" />
<menu_item_call
label="Open"
layout="topleft"
name="open_in_current_window">
<menu_item_call.on_click
function="Inventory.OpenSelectedFolder"/>
</menu_item_call>
<menu_item_call
label="Open in new window"
layout="topleft"
name="open_in_new_window">
<menu_item_call.on_click
function="Inventory.OpenNewFolderWindow"/>
</menu_item_call>
<menu_item_separator
layout="topleft"
name="Open Folder Separator" />
<menu_item_call
label="Copy"
layout="topleft"

View File

@ -6,15 +6,36 @@
mouse_opaque="false"
name="menu_gear_default"
visible="false">
<menu_item_call
label="Open"
layout="topleft"
name="open_in_current_window">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="open_in_current_window" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="open_folder" />
</menu_item_call>
<menu_item_call
label="Open in new window"
layout="topleft"
name="open_in_new_window">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="open_in_new_window" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="open_new_folder" />
</menu_item_call>
<menu_item_call
label="New Folder Window"
layout="topleft"
shortcut="control|shift|J"
enabled="false"
name="new_single_folder">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="new_window" />
parameter="new_single_folder_window" />
</menu_item_call>
<menu_item_call
label="New Inventory Window"
@ -35,6 +56,53 @@
function="Floater.Toggle"
parameter="fs_protectedfolders" />
</menu_item_check>
<menu_item_separator>
<menu_item_separator.on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_separator>
<menu_item_check
label="List view"
layout="topleft"
name="list_view">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="list_view" />
<on_check
function="Inventory.GearDefault.Check"
parameter="list_view" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_check
label="Gallery view"
layout="topleft"
name="gallery_view">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="gallery_view" />
<on_check
function="Inventory.GearDefault.Check"
parameter="gallery_view" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_check
label="Combination view"
layout="topleft"
name="combination_view">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="combination_view" />
<on_check
function="Inventory.GearDefault.Check"
parameter="combination_view" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_separator
layout="topleft" />
<menu_item_check
@ -80,6 +148,9 @@
<on_check
function="Inventory.GearDefault.Check"
parameter="sort_system_folders_to_top" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_check>
<menu_item_separator
layout="topleft" />
@ -192,9 +263,15 @@
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="close_folders" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_separator>
<menu_item_separator.on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_separator>
<menu_item_call
label="Empty Lost and Found"
layout="topleft"
@ -205,6 +282,9 @@
<on_enable
function="Inventory.GearDefault.Enable"
parameter="empty_lostnfound" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_call>
<menu_item_separator
layout="topleft" />
@ -342,7 +422,11 @@
function="Inventory.CoalescedObjects.Check"
parameter="coalesced_objects_only" />
</menu_item_check>
<menu_item_separator />
<menu_item_separator>
<menu_item_separator.on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_separator>
<!-- </FS:Zi> -->
<menu_item_call
@ -355,5 +439,8 @@
<on_enable
function="Inventory.GearDefault.Enable"
parameter="empty_trash" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_call>
</toggleable_menu>

View File

@ -49,5 +49,64 @@
<on_check
function="Inventory.GearDefault.Check"
parameter="sort_system_folders_to_top" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="multi_folder_view" />
</menu_item_check>
<menu_item_separator>
<menu_item_separator.on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_separator>
<menu_item_check
label="List view"
layout="topleft"
name="list_view">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="list_view" />
<on_check
function="Inventory.GearDefault.Check"
parameter="list_view" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_check
label="Gallery view"
layout="topleft"
name="gallery_view">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="gallery_view" />
<on_check
function="Inventory.GearDefault.Check"
parameter="gallery_view" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_check
label="Combination view"
layout="topleft"
name="combination_view">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="combination_view" />
<on_check
function="Inventory.GearDefault.Check"
parameter="combination_view" />
<on_visible
function="Inventory.GearDefault.Visible"
parameter="single_folder_view" />
</menu_item_check>
<menu_item_separator/>
<menu_item_call
label="Inventory settings..."
layout="topleft"
name="inv_settings">
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="inv_settings" />
</menu_item_call>
</toggleable_menu>

View File

@ -40,32 +40,11 @@
parameter="take_off" />
</menu_item_call>
<menu_item_call
label="Upload Photo (L$[UPLOAD_COST])"
label="Image..."
layout="topleft"
name="upload_photo">
name="thumbnail">
<on_click
function="Gear.UploadPhoto" />
</menu_item_call>
<menu_item_call
label="Select Photo"
layout="topleft"
name="select_photo">
<on_click
function="Gear.SelectPhoto" />
</menu_item_call>
<menu_item_call
label="Take a Snapshot"
layout="topleft"
name="take_snapshot">
<on_click
function="Gear.TakeSnapshot" />
</menu_item_call>
<menu_item_call
label="Remove Photo"
layout="topleft"
name="remove_photo">
<on_click
function="Gear.RemovePhoto" />
function="Gear.Thumbnail" />
</menu_item_call>
<menu_item_separator name="sepatator1" />
<!-- copied (with minor modifications) from menu_inventory_add.xml -->

View File

@ -69,6 +69,15 @@
function="Inventory.NewWindow"
parameter="" />
</menu_item_call>
<menu_item_call
label="New Folder Window"
name="new_single_folder"
shortcut="control|shift|J"
visible="false">
<menu_item_call.on_click
function="Inventory.NewFolderWindow"
parameter="" />
</menu_item_call>
<menu_item_check
label="Protected Folders"
name="Protected Folders">

View File

@ -6403,7 +6403,21 @@ Are you sure you want to delete them?
notext="Cancel"
yestext="OK"/>
</notification>
<notification
icon="alertmodal.tga"
name="DeleteThumbnail"
type="alertmodal">
<unique/>
Delete the image for this item? There is no undo.
<tag>confirm</tag>
<usetemplate
ignoretext="Confirm before deleting a thumbnail."
name="okcancelignore"
notext="Cancel"
yestext="Delete"/>
</notification>
<notification
icon="alertmodal.tga"
name="ConfirmUnlink"

View File

@ -23,140 +23,277 @@
name="ItemcountUnknown">
Fetched [ITEM_COUNT] Elements [FILTER]
</panel.string>
<filter_editor
text_pad_left="10"
<panel.string name="inventory_title">Inventory</panel.string>
<panel.string name="default_mode_btn">Multi_Folder_Mode</panel.string>
<panel.string name="single_folder_mode_btn">Single_Folder_Mode</panel.string>
<layout_stack
follows="left|top|right"
height="23"
label="Filter Inventory"
layout="topleft"
height="25"
animate="false"
top_pad="4"
left="10"
max_length_chars="300"
highlight_text_field="true"
name="inventory search editor"
tool_tip="Type in one or more words to search for, separated by '+' "
top_pad="4"
width="322" />
name="nav_stack"
orientation="horizontal">
<layout_panel
border="false"
bevel_style="in"
user_resize="false"
auto_resize="false"
height="25"
width="62"
name="nav_buttons"
visible="false">
<button
follows="top|left"
height="23"
image_selected="Single_Folder_Back"
image_pressed="Single_Folder_Back"
image_unselected="Single_Folder_Back"
scale_image="false"
layout="topleft"
left="0"
top="2"
name="back_btn"
tool_tip="Back"
width="20" />
<button
follows="top|left"
height="23"
image_selected="Single_Folder_Forward"
image_pressed="Single_Folder_Forward"
image_unselected="Single_Folder_Forward"
scale_image="false"
layout="topleft"
left_pad="1"
name="forward_btn"
tool_tip="Forward"
width="20" />
<button
follows="top|left"
height="23"
image_selected="Single_Folder_Up"
image_pressed="Single_Folder_Up"
image_unselected="Single_Folder_Up"
scale_image="false"
layout="topleft"
left_pad="1"
name="up_btn"
tool_tip="Go up one level"
width="20" />
</layout_panel>
<layout_panel
border="false"
bevel_style="in"
user_resize="false"
height="25"
width="324"
name="filter_panel"
visible="true">
<filter_editor
text_pad_left="10"
follows="left|top|right"
height="23"
label="Filter Inventory"
layout="topleft"
left="2"
max_length_chars="300"
highlight_text_field="true"
name="inventory search editor"
tool_tip="Type in one or more words to search for, separated by '+' "
top="0"
width="322" />
</layout_panel>
</layout_stack>
<button
name="collapse_btn"
label="Collapse"
width="80"
<layout_stack
follows="left|top|right"
height="16"
animate="false"
top_pad="4"
left="4"
top_pad="4"
follows="top|left"
layout="topleft"/>
name="ctrl_stack"
orientation="horizontal">
<layout_panel
border="false"
bevel_style="in"
user_resize="false"
auto_resize="false"
height="16"
width="168"
name="collapse_expand_buttons">
<button
name="collapse_btn"
label="Collapse"
width="80"
height="16"
left="0"
top="0"
follows="top|left"
layout="topleft"/>
<button
name="expand_btn"
label="Expand"
width="80"
height="16"
left_pad="4"
follows="top|left"
layout="topleft" />
<button
name="expand_btn"
label="Expand"
width="80"
height="16"
left_pad="4"
follows="top|left"
layout="topleft" />
<text
name="filter_label"
value="Filter:"
width="40"
height="16"
left_pad="4"
follows="top|left"
layout="topleft" />
</layout_panel>
<layout_panel
border="false"
bevel_style="in"
user_resize="false"
height="16"
width="164"
name="filter_ctrls">
<combo_box
name="filter_combo_box"
width="80"
height="16"
left_pad="4"
follows="top|left"
layout="topleft">
<text
name="filter_label"
value="Filter:"
width="40"
height="16"
left="0"
top="0"
follows="top|left"
layout="topleft" />
<combo_box.item value="filter_type_all" label="All Types" />
<combo_box.item value="filter_separator" label="------------" enabled="false" />
<combo_box.item value="filter_type_animations" label="Animations" />
<combo_box.item value="filter_type_calling_cards" label="Calling Cards" />
<combo_box.item value="filter_type_clothing" label="Clothing / Body Parts" />
<combo_box.item value="filter_type_gestures" label="Gestures" />
<combo_box.item value="filter_type_landmarks" label="Landmarks" />
<combo_box.item value="filter_type_notecards" label="Notecards" />
<combo_box.item value="filter_type_objects" label="Objects" />
<combo_box.item value="filter_type_scripts" label="Scripts" />
<combo_box.item value="filter_type_sounds" label="Sounds" />
<combo_box.item value="filter_type_textures" label="Textures" />
<combo_box.item value="filter_type_snapshots" label="Snapshots" />
<combo_box.item value="filter_type_meshes" label="Meshes" />
<combo_box.item value="filter_type_settings" label="Settings" />
<combo_box.item value="filter_separator" label="------------" enabled="false" />
<combo_box.item value="filter_type_custom" label="Custom..." />
<combo_box
name="filter_combo_box"
right="-35"
height="16"
left_pad="4"
follows="top|left|right"
layout="topleft">
<combo_box.item value="filter_type_all" label="All Types" />
<combo_box.item value="filter_separator" label="------------" enabled="false" />
<combo_box.item value="filter_type_animations" label="Animations" />
<combo_box.item value="filter_type_calling_cards" label="Calling Cards" />
<combo_box.item value="filter_type_clothing" label="Clothing / Body Parts" />
<combo_box.item value="filter_type_gestures" label="Gestures" />
<combo_box.item value="filter_type_landmarks" label="Landmarks" />
<combo_box.item value="filter_type_notecards" label="Notecards" />
<combo_box.item value="filter_type_objects" label="Objects" />
<combo_box.item value="filter_type_scripts" label="Scripts" />
<combo_box.item value="filter_type_sounds" label="Sounds" />
<combo_box.item value="filter_type_textures" label="Textures" />
<combo_box.item value="filter_type_snapshots" label="Snapshots" />
<combo_box.item value="filter_type_meshes" label="Meshes" />
<combo_box.item value="filter_type_settings" label="Settings" />
<combo_box.item value="filter_separator" label="------------" enabled="false" />
<combo_box.item value="filter_type_custom" label="Custom..." />
</combo_box>
</combo_box>
<menu_button
follows="top|left"
tool_tip="Show search visibility options"
height="16"
image_overlay="Inv_Toolbar_SearchVisibility"
<menu_button
follows="top|right"
tool_tip="Show search visibility options"
height="16"
image_overlay="Inv_Toolbar_SearchVisibility"
layout="topleft"
right="-1"
top_delta="0"
name="options_visibility_btn"
width="31" />
</layout_panel>
</layout_stack>
<panel
follows="all"
halign="center"
height="338"
layout="topleft"
left_pad="3"
name="options_visibility_btn"
width="31" />
<tab_container
bg_alpha_color="DkGray"
bg_opaque_color="DkGray"
background_visible="false"
background_opaque="false"
left="4"
name="default_inventory_panel"
top_pad="4"
width="322">
<tab_container
bg_alpha_color="DkGray"
bg_opaque_color="DkGray"
background_visible="false"
background_opaque="false"
follows="all"
halign="center"
height="338"
layout="topleft"
left="0"
name="inventory filter tabs"
open_tabs_on_drag_and_drop="true"
tab_position="top"
top="0"
width="322">
<inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Inventory"
help_topic="my_inventory_tab"
layout="topleft"
left="0"
name="All Items"
sort_order_setting="InventorySortOrder"
show_item_link_overlays="true"
top="16"
width="288" />
<recent_inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Recent"
sort_order_setting="RecentItemsSortOrder"
help_topic="recent_inventory_tab"
layout="topleft"
left_delta="0"
name="Recent Items"
show_item_link_overlays="true"
width="290" />
<worn_inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Worn"
help_topic="worn_inventory_tab"
layout="topleft"
left_delta="0"
name="Worn Items"
show_item_link_overlays="true"
width="290" />
</tab_container>
</panel>
<panel
follows="all"
halign="center"
height="338"
layout="topleft"
left="4"
name="single_folder_inventory"
top_delta="0"
visible="false"
width="322">
<single_folder_inventory_panel
name="single_folder_inv"
show_empty_message="false"
follows="all"
halign="center"
height="340"
layout="topleft"
left="4"
name="inventory filter tabs"
open_tabs_on_drag_and_drop="true"
tab_position="top"
top_pad="4"
width="322">
<inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Inventory"
help_topic="my_inventory_tab"
layout="topleft"
left="0"
name="All Items"
sort_order_setting="InventorySortOrder"
show_item_link_overlays="true"
top="16"
width="288" />
<recent_inventory_panel
top="0"
top_pad="5"
height="338"
width="322"
layout="topleft"
background_visible="true"
border="false"
bevel_style="none"
follows="all"
height="338"
label="Recent"
sort_order_setting="RecentItemsSortOrder"
help_topic="recent_inventory_tab"
layout="topleft"
left_delta="0"
name="Recent Items"
show_item_link_overlays="true"
width="290" />
<worn_inventory_panel
border="false"
bevel_style="none"
follows="all"
height="338"
label="Worn"
help_topic="worn_inventory_tab"
layout="topleft"
left_delta="0"
name="Worn Items"
show_item_link_overlays="true"
width="290" />
</tab_container>
scroll.reserve_scroll_corner="false">
<item folder_indentation="0"/>
<folder
single_folder_mode="true"
folder_indentation="0"/>
</single_folder_inventory_panel>
</panel>
<panel
follows="left|right|bottom"
height="25"
@ -232,6 +369,27 @@
parameter="secondary_inventory" />
</button>
</panel>
<panel
follows="top|left"
height="25"
layout="topleft"
left_pad="0"
name="view_mode_panel"
width="32">
<button
follows="top|left"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Single_Folder_Mode"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
left="0"
name="view_mode_btn"
tool_tip="Switch between views"
top="0"
width="31"/>
</panel>
<panel
follows="top|left|right"
height="25"

View File

@ -89,14 +89,14 @@
name="layout_item_details"
layout="topleft"
follows="all"
height="130">
height="133">
<thumbnail
name="item_thumbnail"
follows="top|left"
layout="topleft"
left="5"
top="0"
top="2"
height="128"
width="128"
/>
@ -105,7 +105,7 @@
type="string"
length="1"
follows="left|top"
height="17"
height="16"
layout="topleft"
left_pad="5"
name="LabelOwnerTitle"
@ -131,7 +131,7 @@ TestString PleaseIgnore
type="string"
length="1"
follows="left|top"
height="17"
height="16"
layout="topleft"
left_delta="0"
name="LabelCreatorTitle"
@ -157,7 +157,7 @@ TestString PleaseIgnore
type="string"
length="1"
follows="left|top"
height="17"
height="16"
layout="topleft"
left_delta="0"
name="LabelAcquiredTitle"
@ -169,13 +169,23 @@ TestString PleaseIgnore
type="string"
length="1"
follows="left|top|right"
height="23"
height="18"
layout="topleft"
left_delta="0"
name="LabelAcquiredDate"
top_pad="0"
width="187">
00/00/00
</text>
<button
follows="left|top"
height="21"
label="Image..."
layout="topleft"
left_delta="0"
name="change_thumbnail_btn"
top_pad="0"
width="120" />
</layout_panel>
<layout_panel

View File

@ -3256,7 +3256,7 @@ Your current position: [AVATAR_POS]
<string name="Yes">Yes</string>
<string name="No">No</string>
<string name="FSUrlEntryWearLabel">Wear inventory folder</string>
<string name="TexturePickerOutfitHeader">Picture for Outfit</string>
<string name="TexturePickerOutfitHeader">Item Snapshot</string>
<string name="unknown_script">(Unknown script)</string>
<string name="FSAreaSearch_Cost_Label">L$[COST]</string>