661 lines
20 KiB
C++
661 lines
20 KiB
C++
/**
|
|
* @file llfloatergesture.cpp
|
|
* @brief Read-only list of gestures from your inventory.
|
|
*
|
|
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "llfloatergesture.h"
|
|
|
|
#include "llinventory.h"
|
|
#include "llinventorybridge.h"
|
|
#include "llinventoryfunctions.h"
|
|
#include "llinventorymodel.h"
|
|
#include "llclipboard.h"
|
|
|
|
#include "llagent.h"
|
|
#include "llappearancemgr.h"
|
|
#include "llclipboard.h"
|
|
#include "llgesturemgr.h"
|
|
#include "llkeyboard.h"
|
|
#include "llmenugl.h"
|
|
#include "llmultigesture.h"
|
|
#include "llpreviewgesture.h"
|
|
#include "llscrolllistctrl.h"
|
|
#include "lltrans.h"
|
|
#include "llviewergesture.h"
|
|
#include "llviewermenu.h"
|
|
#include "llviewerinventory.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llfloaterperms.h"
|
|
|
|
BOOL item_name_precedes( LLInventoryItem* a, LLInventoryItem* b )
|
|
{
|
|
return LLStringUtil::precedesDict( a->getName(), b->getName() );
|
|
}
|
|
|
|
class LLFloaterGestureObserver : public LLGestureManagerObserver
|
|
{
|
|
public:
|
|
LLFloaterGestureObserver(LLFloaterGesture* floater) : mFloater(floater) {}
|
|
virtual ~LLFloaterGestureObserver() {}
|
|
virtual void changed() { mFloater->refreshAll(); }
|
|
|
|
private:
|
|
LLFloaterGesture* mFloater;
|
|
};
|
|
//-----------------------------
|
|
// GestureCallback
|
|
//-----------------------------
|
|
|
|
class GestureShowCallback : public LLInventoryCallback
|
|
{
|
|
public:
|
|
void fire(const LLUUID &inv_item)
|
|
{
|
|
LLPreviewGesture::show(inv_item, LLUUID::null);
|
|
|
|
LLInventoryItem* item = gInventory.getItem(inv_item);
|
|
if (item)
|
|
{
|
|
LLPermissions perm = item->getPermissions();
|
|
perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Gestures"));
|
|
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures"));
|
|
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures"));
|
|
item->setPermissions(perm);
|
|
item->updateServer(FALSE);
|
|
}
|
|
}
|
|
};
|
|
|
|
class GestureCopiedCallback : public LLInventoryCallback
|
|
{
|
|
private:
|
|
LLFloaterGesture* mFloater;
|
|
|
|
public:
|
|
GestureCopiedCallback(LLFloaterGesture* floater): mFloater(floater)
|
|
{}
|
|
void fire(const LLUUID &inv_item)
|
|
{
|
|
if(mFloater)
|
|
{
|
|
mFloater->addGesture(inv_item,NULL,mFloater->getChild<LLScrollListCtrl>("gesture_list"));
|
|
|
|
// EXP-1909 (Pasted gesture displayed twice)
|
|
// The problem is that addGesture is called here for the second time for the same item (which is copied)
|
|
// First time addGesture is called from LLFloaterGestureObserver::changed(), which is a callback for inventory
|
|
// change. So we need to refresh the gesture list to avoid duplicates.
|
|
mFloater->refreshAll();
|
|
}
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// LLFloaterGesture
|
|
//---------------------------------------------------------------------------
|
|
LLFloaterGesture::LLFloaterGesture(const LLSD& key)
|
|
: LLFloater(key)
|
|
{
|
|
mObserver = new LLFloaterGestureObserver(this);
|
|
LLGestureMgr::instance().addObserver(mObserver);
|
|
|
|
mCommitCallbackRegistrar.add("Gesture.Action.ToogleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this));
|
|
mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this));
|
|
mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2));
|
|
mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this));
|
|
|
|
mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2));
|
|
}
|
|
|
|
void LLFloaterGesture::done()
|
|
{
|
|
//this method can be called twice: for GestureFolder and once after loading all sudir of GestureFolder
|
|
if (gInventory.isCategoryComplete(mGestureFolderID))
|
|
{
|
|
LL_DEBUGS("Gesture")<< "mGestureFolderID loaded" << LL_ENDL;
|
|
// we load only gesture folder without childred.
|
|
LLInventoryModel::cat_array_t* categories;
|
|
LLInventoryModel::item_array_t* items;
|
|
uuid_vec_t unloaded_folders;
|
|
LL_DEBUGS("Gesture")<< "Get subdirs of Gesture Folder...." << LL_ENDL;
|
|
gInventory.getDirectDescendentsOf(mGestureFolderID, categories, items);
|
|
if (categories->empty())
|
|
{
|
|
gInventory.removeObserver(this);
|
|
LL_INFOS("Gesture")<< "Gesture dos NOT contains sub-directories."<< LL_ENDL;
|
|
return;
|
|
}
|
|
LL_DEBUGS("Gesture")<< "There are " << categories->size() << " Folders "<< LL_ENDL;
|
|
for (LLInventoryModel::cat_array_t::iterator it = categories->begin(); it != categories->end(); it++)
|
|
{
|
|
if (!gInventory.isCategoryComplete(it->get()->getUUID()))
|
|
{
|
|
unloaded_folders.push_back(it->get()->getUUID());
|
|
LL_DEBUGS("Gesture")<< it->get()->getName()<< " Folder added to fetchlist"<< LL_ENDL;
|
|
}
|
|
|
|
}
|
|
if (!unloaded_folders.empty())
|
|
{
|
|
LL_DEBUGS("Gesture")<< "Fetching subdirectories....." << LL_ENDL;
|
|
setFetchIDs(unloaded_folders);
|
|
startFetch();
|
|
}
|
|
else
|
|
{
|
|
LL_DEBUGS("Gesture")<< "All Gesture subdirectories have been loaded."<< LL_ENDL;
|
|
gInventory.removeObserver(this);
|
|
buildGestureList();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LL_WARNS("Gesture")<< "Gesture list was NOT loaded"<< LL_ENDL;
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
LLFloaterGesture::~LLFloaterGesture()
|
|
{
|
|
LLGestureMgr::instance().removeObserver(mObserver);
|
|
delete mObserver;
|
|
mObserver = NULL;
|
|
gInventory.removeObserver(this);
|
|
}
|
|
|
|
// virtual
|
|
BOOL LLFloaterGesture::postBuild()
|
|
{
|
|
std::string label;
|
|
|
|
label = getTitle();
|
|
|
|
setTitle(label);
|
|
mGestureList = getChild<LLScrollListCtrl>("gesture_list");
|
|
mGestureList->setCommitCallback(boost::bind(&LLFloaterGesture::onCommitList, this));
|
|
mGestureList->setDoubleClickCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
|
|
|
|
getChild<LLUICtrl>("edit_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickEdit, this));
|
|
|
|
getChild<LLUICtrl>("play_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
|
|
getChild<LLUICtrl>("stop_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
|
|
getChild<LLButton>("activate_btn")->setClickedCallback(boost::bind(&LLFloaterGesture::onActivateBtnClick, this));
|
|
|
|
getChild<LLUICtrl>("new_gesture_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickNew, this));
|
|
getChild<LLButton>("del_btn")->setClickedCallback(boost::bind(&LLFloaterGesture::onDeleteSelected, this));
|
|
|
|
getChildView("play_btn")->setVisible( true);
|
|
getChildView("stop_btn")->setVisible( false);
|
|
setDefaultBtn("play_btn");
|
|
mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE, false);
|
|
|
|
uuid_vec_t folders;
|
|
folders.push_back(mGestureFolderID);
|
|
//perform loading Gesture directory anyway to make sure that all subdirectory are loaded too. See method done() for details.
|
|
gInventory.addObserver(this);
|
|
setFetchIDs(folders);
|
|
startFetch();
|
|
|
|
if (mGestureList)
|
|
{
|
|
buildGestureList();
|
|
|
|
mGestureList->setFocus(TRUE);
|
|
|
|
const BOOL ascending = TRUE;
|
|
mGestureList->sortByColumn(std::string("name"), ascending);
|
|
mGestureList->selectFirstItem();
|
|
}
|
|
|
|
// Update button labels
|
|
onCommitList();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void LLFloaterGesture::refreshAll()
|
|
{
|
|
if (!mGestureList) return;
|
|
|
|
buildGestureList();
|
|
|
|
if (mSelectedID.isNull())
|
|
{
|
|
mGestureList->selectFirstItem();
|
|
}
|
|
else
|
|
{
|
|
if (! mGestureList->setCurrentByID(mSelectedID))
|
|
{
|
|
mGestureList->selectFirstItem();
|
|
}
|
|
}
|
|
|
|
// Update button labels
|
|
onCommitList();
|
|
}
|
|
|
|
void LLFloaterGesture::buildGestureList()
|
|
{
|
|
S32 scroll_pos = mGestureList->getScrollPos();
|
|
uuid_vec_t selected_items;
|
|
getSelectedIds(selected_items);
|
|
LL_DEBUGS("Gesture")<< "Rebuilding gesture list "<< LL_ENDL;
|
|
mGestureList->deleteAllItems();
|
|
|
|
LLGestureMgr::item_map_t::const_iterator it;
|
|
const LLGestureMgr::item_map_t& active_gestures = LLGestureMgr::instance().getActiveGestures();
|
|
for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
|
|
{
|
|
addGesture(it->first,it->second, mGestureList);
|
|
}
|
|
if (gInventory.isCategoryComplete(mGestureFolderID))
|
|
{
|
|
LLIsType is_gesture(LLAssetType::AT_GESTURE);
|
|
LLInventoryModel::cat_array_t categories;
|
|
LLInventoryModel::item_array_t items;
|
|
gInventory.collectDescendentsIf(mGestureFolderID, categories, items,
|
|
LLInventoryModel::EXCLUDE_TRASH, is_gesture);
|
|
|
|
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it!= items.end(); ++it)
|
|
{
|
|
LLInventoryItem* item = it->get();
|
|
if (active_gestures.find(item->getUUID()) == active_gestures.end())
|
|
{
|
|
// if gesture wasn't loaded yet, we can display only name
|
|
addGesture(item->getUUID(), NULL, mGestureList);
|
|
}
|
|
}
|
|
}
|
|
|
|
// attempt to preserve scroll position through re-builds
|
|
// since we do re-build whenever something gets dirty
|
|
for(uuid_vec_t::iterator it = selected_items.begin(); it != selected_items.end(); it++)
|
|
{
|
|
mGestureList->selectByID(*it);
|
|
}
|
|
mGestureList->setScrollPos(scroll_pos);
|
|
}
|
|
|
|
void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gesture,LLCtrlListInterface * list )
|
|
{
|
|
// Note: Can have NULL item if inventory hasn't arrived yet.
|
|
static std::string item_name = getString("loading");
|
|
LLInventoryItem* item = gInventory.getItem(item_id);
|
|
if (item)
|
|
{
|
|
item_name = item->getName();
|
|
}
|
|
|
|
static std::string font_style = "NORMAL";
|
|
// If gesture is playing, bold it
|
|
|
|
LLSD element;
|
|
element["id"] = item_id;
|
|
|
|
if (gesture)
|
|
{
|
|
if (gesture->mPlaying)
|
|
{
|
|
font_style = "BOLD";
|
|
}
|
|
item_name = gesture->mName;
|
|
element["columns"][0]["column"] = "trigger";
|
|
element["columns"][0]["value"] = gesture->mTrigger;
|
|
element["columns"][0]["font"]["name"] = "SANSSERIF";
|
|
element["columns"][0]["font"]["style"] = font_style;
|
|
|
|
std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
|
|
std::string buffer;
|
|
|
|
if (gesture->mKey == KEY_NONE)
|
|
{
|
|
buffer = "---";
|
|
key_string = "~~~"; // alphabetize to end
|
|
}
|
|
else
|
|
{
|
|
buffer = LLKeyboard::stringFromAccelerator(gesture->mMask,
|
|
gesture->mKey);
|
|
}
|
|
|
|
element["columns"][1]["column"] = "shortcut";
|
|
element["columns"][1]["value"] = buffer;
|
|
element["columns"][1]["font"]["name"] = "SANSSERIF";
|
|
element["columns"][1]["font"]["style"] = font_style;
|
|
|
|
// hidden column for sorting
|
|
element["columns"][2]["column"] = "key";
|
|
element["columns"][2]["value"] = key_string;
|
|
element["columns"][2]["font"]["name"] = "SANSSERIF";
|
|
element["columns"][2]["font"]["style"] = font_style;
|
|
|
|
// Only add "playing" if we've got the name, less confusing. JC
|
|
if (item && gesture->mPlaying)
|
|
{
|
|
item_name += " " + getString("playing");
|
|
}
|
|
element["columns"][3]["column"] = "name";
|
|
element["columns"][3]["value"] = item_name;
|
|
element["columns"][3]["font"]["name"] = "SANSSERIF";
|
|
element["columns"][3]["font"]["style"] = font_style;
|
|
}
|
|
else
|
|
{
|
|
element["columns"][0]["column"] = "trigger";
|
|
element["columns"][0]["value"] = "";
|
|
element["columns"][0]["font"]["name"] = "SANSSERIF";
|
|
element["columns"][0]["font"]["style"] = font_style;
|
|
element["columns"][1]["column"] = "shortcut";
|
|
element["columns"][1]["value"] = "---";
|
|
element["columns"][1]["font"]["name"] = "SANSSERIF";
|
|
element["columns"][1]["font"]["style"] = font_style;
|
|
element["columns"][2]["column"] = "key";
|
|
element["columns"][2]["value"] = "~~~";
|
|
element["columns"][2]["font"]["name"] = "SANSSERIF";
|
|
element["columns"][2]["font"]["style"] = font_style;
|
|
element["columns"][3]["column"] = "name";
|
|
element["columns"][3]["value"] = item_name;
|
|
element["columns"][3]["font"]["name"] = "SANSSERIF";
|
|
element["columns"][3]["font"]["style"] = font_style;
|
|
}
|
|
|
|
LL_DEBUGS("Gesture") << "Added gesture [" << item_name << "]" << LL_ENDL;
|
|
|
|
LLScrollListItem* sl_item = list->addElement(element, ADD_BOTTOM);
|
|
if(sl_item)
|
|
{
|
|
LLFontGL::StyleFlags style = LLGestureMgr::getInstance()->isGestureActive(item_id) ? LLFontGL::BOLD : LLFontGL::NORMAL;
|
|
// *TODO find out why ["font"]["style"] does not affect font style
|
|
((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(style);
|
|
}
|
|
}
|
|
|
|
void LLFloaterGesture::getSelectedIds(uuid_vec_t& ids)
|
|
{
|
|
std::vector<LLScrollListItem*> items = mGestureList->getAllSelected();
|
|
for(std::vector<LLScrollListItem*>::const_iterator it = items.begin(); it != items.end(); it++)
|
|
{
|
|
ids.push_back((*it)->getUUID());
|
|
}
|
|
}
|
|
|
|
bool LLFloaterGesture::isActionEnabled(const LLSD& command)
|
|
{
|
|
// paste copy_uuid edit_gesture
|
|
std::string command_name = command.asString();
|
|
if("paste" == command_name)
|
|
{
|
|
if(!LLClipboard::instance().hasContents())
|
|
return false;
|
|
|
|
std::vector<LLUUID> ids;
|
|
LLClipboard::instance().pasteFromClipboard(ids);
|
|
for(std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
|
|
{
|
|
LLInventoryItem* item = gInventory.getItem(*it);
|
|
|
|
if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
else if("copy_uuid" == command_name || "edit_gesture" == command_name)
|
|
{
|
|
return mGestureList->getAllSelected().size() == 1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void LLFloaterGesture::onClickPlay()
|
|
{
|
|
const LLUUID& item_id = mGestureList->getCurrentID();
|
|
if(item_id.isNull()) return;
|
|
|
|
LL_DEBUGS("Gesture")<<" Trying to play gesture id: "<< item_id <<LL_ENDL;
|
|
if(!LLGestureMgr::instance().isGestureActive(item_id))
|
|
{
|
|
// we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList.
|
|
BOOL inform_server = TRUE;
|
|
BOOL deactivate_similar = FALSE;
|
|
LLGestureMgr::instance().setGestureLoadedCallback(item_id, boost::bind(&LLFloaterGesture::playGesture, this, item_id));
|
|
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
|
llassert(item);
|
|
if (item)
|
|
{
|
|
LLGestureMgr::instance().activateGestureWithAsset(item_id, item->getAssetUUID(), inform_server, deactivate_similar);
|
|
LL_DEBUGS("Gesture")<< "Activating gesture with inventory ID: " << item_id <<LL_ENDL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
playGesture(item_id);
|
|
}
|
|
}
|
|
|
|
void LLFloaterGesture::onClickNew()
|
|
{
|
|
LLPointer<LLInventoryCallback> cb = new GestureShowCallback();
|
|
create_inventory_item(gAgent.getID(),
|
|
gAgent.getSessionID(),
|
|
LLUUID::null,
|
|
LLTransactionID::tnull,
|
|
"New Gesture",
|
|
"",
|
|
LLAssetType::AT_GESTURE,
|
|
LLInventoryType::IT_GESTURE,
|
|
NOT_WEARABLE,
|
|
PERM_MOVE | LLFloaterPerms::getNextOwnerPerms("Gestures"),
|
|
cb);
|
|
}
|
|
|
|
void LLFloaterGesture::onActivateBtnClick()
|
|
{
|
|
uuid_vec_t ids;
|
|
getSelectedIds(ids);
|
|
if(ids.empty())
|
|
return;
|
|
|
|
LLGestureMgr* gm = LLGestureMgr::getInstance();
|
|
uuid_vec_t::const_iterator it = ids.begin();
|
|
BOOL first_gesture_state = gm->isGestureActive(*it);
|
|
BOOL is_mixed = FALSE;
|
|
while( ++it != ids.end() )
|
|
{
|
|
if(first_gesture_state != gm->isGestureActive(*it))
|
|
{
|
|
is_mixed = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
|
|
{
|
|
if(is_mixed)
|
|
{
|
|
gm->activateGesture(*it);
|
|
}
|
|
else
|
|
{
|
|
if(first_gesture_state)
|
|
{
|
|
gm->deactivateGesture(*it);
|
|
}
|
|
else
|
|
{
|
|
gm->activateGesture(*it);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
|
|
{
|
|
std::string command_name = command.asString();
|
|
// Since we select this command, the inventory items must have already arrived
|
|
if("copy_gesture" == command_name)
|
|
{
|
|
uuid_vec_t ids;
|
|
getSelectedIds(ids);
|
|
// Make sure the clipboard is empty
|
|
LLClipboard::instance().reset();
|
|
for(uuid_vec_t::iterator it = ids.begin(); it != ids.end(); it++)
|
|
{
|
|
LLInventoryItem* item = gInventory.getItem(*it);
|
|
if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
|
|
{
|
|
LLWString item_name = utf8str_to_wstring(item->getName());
|
|
LLClipboard::instance().addToClipboard(item_name, 0, item_name.size());
|
|
}
|
|
}
|
|
}
|
|
else if ("paste" == command_name)
|
|
{
|
|
std::vector<LLUUID> ids;
|
|
LLClipboard::instance().pasteFromClipboard(ids);
|
|
if(ids.empty() || !gInventory.isCategoryComplete(mGestureFolderID))
|
|
return;
|
|
LLInventoryCategory* gesture_dir = gInventory.getCategory(mGestureFolderID);
|
|
llassert(gesture_dir);
|
|
LLPointer<GestureCopiedCallback> cb = new GestureCopiedCallback(this);
|
|
|
|
for(std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
|
|
{
|
|
LLInventoryItem* item = gInventory.getItem(*it);
|
|
if(gesture_dir && item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
|
|
{
|
|
LLStringUtil::format_map_t string_args;
|
|
string_args["[COPY_NAME]"] = item->getName();
|
|
LL_DEBUGS("Gesture")<< "Copying gesture " << item->getName() << " "<< item->getUUID() << " into "
|
|
<< gesture_dir->getName() << " "<< gesture_dir->getUUID() << LL_ENDL;
|
|
copy_inventory_item(gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(),
|
|
gesture_dir->getUUID(), getString("copy_name", string_args), cb);
|
|
}
|
|
}
|
|
LLClipboard::instance().reset();
|
|
}
|
|
else if ("copy_uuid" == command_name)
|
|
{
|
|
LLClipboard::instance().copyToClipboard(mGestureList->getCurrentID(),LLAssetType::AT_GESTURE);
|
|
}
|
|
}
|
|
|
|
void LLFloaterGesture::onClickEdit()
|
|
{
|
|
const LLUUID& item_id = mGestureList->getCurrentID();
|
|
|
|
LLInventoryItem* item = gInventory.getItem(item_id);
|
|
if (!item) return;
|
|
|
|
LLPreviewGesture* previewp = LLPreviewGesture::show(item_id, LLUUID::null);
|
|
if (!previewp->getHost())
|
|
{
|
|
previewp->setRect(gFloaterView->findNeighboringPosition(this, previewp));
|
|
}
|
|
}
|
|
|
|
void LLFloaterGesture::onCommitList()
|
|
{
|
|
const LLUUID& item_id = mGestureList->getCurrentID();
|
|
|
|
mSelectedID = item_id;
|
|
if (LLGestureMgr::instance().isGesturePlaying(item_id))
|
|
{
|
|
getChildView("play_btn")->setVisible( false);
|
|
getChildView("stop_btn")->setVisible( true);
|
|
}
|
|
else
|
|
{
|
|
getChildView("play_btn")->setVisible( true);
|
|
getChildView("stop_btn")->setVisible( false);
|
|
}
|
|
}
|
|
|
|
void LLFloaterGesture::onDeleteSelected()
|
|
{
|
|
uuid_vec_t ids;
|
|
getSelectedIds(ids);
|
|
if(ids.empty())
|
|
return;
|
|
|
|
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
|
LLGestureMgr* gm = LLGestureMgr::getInstance();
|
|
for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
|
|
{
|
|
const LLUUID& selected_item = *it;
|
|
LLInventoryItem* inv_item = gInventory.getItem(selected_item);
|
|
if (inv_item && inv_item->getInventoryType() == LLInventoryType::IT_GESTURE)
|
|
{
|
|
if(gm->isGestureActive(selected_item))
|
|
{
|
|
gm->deactivateGesture(selected_item);
|
|
}
|
|
LLInventoryModel::update_list_t update;
|
|
LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
|
|
update.push_back(old_folder);
|
|
LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
|
|
update.push_back(new_folder);
|
|
gInventory.accountForUpdate(update);
|
|
|
|
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
|
|
new_item->setParent(trash_id);
|
|
// no need to restamp it though it's a move into trash because
|
|
// it's a brand new item already.
|
|
new_item->updateParentOnServer(FALSE);
|
|
gInventory.updateItem(new_item);
|
|
}
|
|
}
|
|
gInventory.notifyObservers();
|
|
buildGestureList();
|
|
}
|
|
|
|
void LLFloaterGesture::addToCurrentOutFit()
|
|
{
|
|
uuid_vec_t ids;
|
|
getSelectedIds(ids);
|
|
LLAppearanceMgr* am = LLAppearanceMgr::getInstance();
|
|
LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
|
|
for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
|
|
{
|
|
am->addCOFItemLink(*it, cb);
|
|
}
|
|
}
|
|
|
|
void LLFloaterGesture::playGesture(LLUUID item_id)
|
|
{
|
|
LL_DEBUGS("Gesture")<<"Playing gesture "<< item_id<<LL_ENDL;
|
|
|
|
if (LLGestureMgr::instance().isGesturePlaying(item_id))
|
|
{
|
|
LLGestureMgr::instance().stopGesture(item_id);
|
|
}
|
|
else
|
|
{
|
|
LLGestureMgr::instance().playGesture(item_id);
|
|
}
|
|
}
|