Merge branch 'DRTVWR-587-maint-V' of https://github.com/secondlife/viewer

# Conflicts:
#	indra/llui/lllineeditor.cpp
#	indra/llui/lllineeditor.h
#	indra/llui/llurlentry.h
#	indra/llui/llurlregistry.cpp
#	indra/llui/llurlregistry.h
#	indra/newview/llviewerinventory.cpp
#	indra/newview/llvoavatarself.h
meow-7.2.2
Ansariel 2023-07-18 00:16:15 +02:00
commit 63151d5c6d
21 changed files with 426 additions and 97 deletions

View File

@ -29,15 +29,6 @@ else()
set( USE_AUTOBUILD_3P ON )
endif()
# The viewer code base can now be successfully compiled with -std=c++14. But
# turning that on in the generic viewer-build-variables/variables file would
# potentially require tweaking each of our ~50 third-party library builds.
# Until we decide to set -std=c++14 in viewer-build-variables/variables, set
# it locally here: we want to at least prevent inadvertently reintroducing
# viewer code that would fail with C++14.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(Variables)
include(BuildVersion)

View File

@ -165,6 +165,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mPreeditBgColor(p.preedit_bg_color()),
mGLFont(p.font),
mContextMenuHandle(),
mShowContextMenu(true),
mAutoreplaceCallback()
{
llassert( mMaxLengthBytes > 0 );
@ -828,7 +829,7 @@ BOOL LLLineEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLLineEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
setFocus(TRUE);
if (!LLUICtrl::handleRightMouseDown(x, y, mask))
if (!LLUICtrl::handleRightMouseDown(x, y, mask) && getShowContextMenu())
{
showContextMenu(x, y);
}

View File

@ -295,13 +295,16 @@ public:
void setBgImage(LLPointer<LLUIImage> image) { mBgImage = image; }
void setBgImageFocused(LLPointer<LLUIImage> image) { mBgImageFocused = image; }
void setShowContextMenu(bool show) { mShowContextMenu = show; }
bool getShowContextMenu() const { return mShowContextMenu; }
// <FS:Ansariel> Make these protected
void removeChar();
void removeWord(bool prev);
void addChar(const llwchar c);
// </FS:Ansariel>
private:
private:
// private helper methods
void pasteHelper(bool is_primary);
@ -422,6 +425,8 @@ protected:
LLHandle<LLContextMenu> mContextMenuHandle;
bool mShowContextMenu;
private:
// Instances that by default point to the statics but can be overidden in XML.
LLPointer<LLUIImage> mBgImage;

View File

@ -35,7 +35,9 @@
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "llkeyboard.h"
#include "llregex.h"
#include "llscrolllistctrl.h" // for LLUrlEntryKeybinding file parsing
#include "lltrans.h"
#include "lluicolortable.h"
#include "message.h"
@ -1837,3 +1839,122 @@ std::string LLUrlEntryIPv6::getUrl(const std::string &string) const
{
return string;
}
//
// LLUrlEntryKeybinding Displays currently assigned key
//
LLUrlEntryKeybinding::LLUrlEntryKeybinding()
: LLUrlEntryBase()
, pHandler(NULL)
{
mPattern = boost::regex(APP_HEADER_REGEX "/keybinding/\\w+(\\?mode=\\w+)?$",
boost::regex::perl | boost::regex::icase);
mMenuName = "menu_url_experience.xml";
initLocalization();
}
std::string LLUrlEntryKeybinding::getLabel(const std::string& url, const LLUrlLabelCallback& cb)
{
std::string control = getControlName(url);
std::map<std::string, LLLocalizationData>::iterator iter = mLocalizations.find(control);
std::string keybind;
if (pHandler)
{
keybind = pHandler->getKeyBindingAsString(getMode(url), control);
}
if (iter != mLocalizations.end())
{
return iter->second.mLocalization + ": " + keybind;
}
return control + ": " + keybind;
}
std::string LLUrlEntryKeybinding::getTooltip(const std::string& url) const
{
std::string control = getControlName(url);
std::map<std::string, LLLocalizationData>::const_iterator iter = mLocalizations.find(control);
if (iter != mLocalizations.end())
{
return iter->second.mTooltip;
}
return url;
}
std::string LLUrlEntryKeybinding::getControlName(const std::string& url) const
{
std::string search = "/keybinding/";
size_t pos_start = url.find(search);
if (pos_start == std::string::npos)
{
return std::string();
}
pos_start += search.size();
size_t pos_end = url.find("?mode=");
if (pos_end == std::string::npos)
{
pos_end = url.size();
}
return url.substr(pos_start, pos_end - pos_start);
}
std::string LLUrlEntryKeybinding::getMode(const std::string& url) const
{
std::string search = "?mode=";
size_t pos_start = url.find(search);
if (pos_start == std::string::npos)
{
return std::string();
}
pos_start += search.size();
return url.substr(pos_start, url.size() - pos_start);
}
void LLUrlEntryKeybinding::initLocalization()
{
initLocalizationFromFile("control_table_contents_movement.xml");
initLocalizationFromFile("control_table_contents_camera.xml");
initLocalizationFromFile("control_table_contents_editing.xml");
initLocalizationFromFile("control_table_contents_media.xml");
}
void LLUrlEntryKeybinding::initLocalizationFromFile(const std::string& filename)
{
LLXMLNodePtr xmlNode;
LLScrollListCtrl::Contents contents;
if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode))
{
LL_WARNS() << "Failed to load " << filename << LL_ENDL;
return;
}
LLXUIParser parser;
parser.readXUI(xmlNode, contents, filename);
if (!contents.validateBlock())
{
LL_WARNS() << "Failed to validate " << filename << LL_ENDL;
return;
}
for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = contents.rows.begin();
row_it != contents.rows.end();
++row_it)
{
std::string control = row_it->value.getValue().asString();
if (!control.empty() && control != "menu_separator")
{
mLocalizations[control] =
LLLocalizationData(
row_it->columns.begin()->value.getValue().asString(),
row_it->columns.begin()->tool_tip.getValue()
);
}
}
}

View File

@ -625,6 +625,39 @@ public:
std::string mHostPath;
};
class LLKeyBindingToStringHandler;
///
/// LLUrlEntryKeybinding A way to access keybindings and show currently used one in text.
/// secondlife:///app/keybinding/control_name
class LLUrlEntryKeybinding: public LLUrlEntryBase
{
public:
LLUrlEntryKeybinding();
/*virtual*/ std::string getLabel(const std::string& url, const LLUrlLabelCallback& cb);
/*virtual*/ std::string getTooltip(const std::string& url) const;
void setHandler(LLKeyBindingToStringHandler* handler) {pHandler = handler;}
private:
std::string getControlName(const std::string& url) const;
std::string getMode(const std::string& url) const;
void initLocalization();
void initLocalizationFromFile(const std::string& filename);
struct LLLocalizationData
{
LLLocalizationData() {}
LLLocalizationData(const std::string& localization, const std::string& tooltip)
: mLocalization(localization)
, mTooltip(tooltip)
{}
std::string mLocalization;
std::string mTooltip;
};
std::map<std::string, LLLocalizationData> mLocalizations;
LLKeyBindingToStringHandler* pHandler;
};
///
/// LLUrlEntryJira Describes Jira issue names -KC
///

View File

@ -41,7 +41,7 @@ LLUrlRegistry::LLUrlRegistry()
{
// mUrlEntry.reserve(20);
// [RLVa:KB] - Checked: 2010-11-01 (RLVa-1.2.2a) | Added: RLVa-1.2.2a
mUrlEntry.reserve(29);
mUrlEntry.reserve(30);
// [/RLVa:KB]
// Urls are matched in the order that they were registered
@ -85,6 +85,8 @@ LLUrlRegistry::LLUrlRegistry()
registerUrl(new LLUrlEntryPlace());
registerUrl(new LLUrlEntryInventory());
registerUrl(new LLUrlEntryExperienceProfile());
mUrlEntryKeybinding = new LLUrlEntryKeybinding();
registerUrl(mUrlEntryKeybinding);
registerUrl(new FSHelpDebugUrlEntrySL()); // <FS:Ansariel> FS Help SLUrl
// <FS:Ansariel> Wear folder SLUrl
mUrlEntryWear = new FSUrlEntryWear();
@ -397,3 +399,9 @@ bool LLUrlRegistry::isUrl(const LLWString &text)
}
return false;
}
void LLUrlRegistry::setKeybindingHandler(LLKeyBindingToStringHandler* handler)
{
LLUrlEntryKeybinding *entry = (LLUrlEntryKeybinding*)mUrlEntryKeybinding;
entry->setHandler(handler);
}

View File

@ -36,6 +36,8 @@
#include <string>
#include <vector>
class LLKeyBindingToStringHandler;
/// This default callback for findUrl() simply ignores any label updates
void LLUrlRegistryNullCallback(const std::string &url,
const std::string &label,
@ -88,6 +90,9 @@ public:
bool isUrl(const std::string &text);
bool isUrl(const LLWString &text);
// Set handler for url registry to be capable of parsing and populating keybindings
void setKeybindingHandler(LLKeyBindingToStringHandler* handler);
private:
std::vector<LLUrlEntryBase *> mUrlEntry;
LLUrlEntryBase* mUrlEntryTrusted;
@ -96,6 +101,7 @@ private:
LLUrlEntryBase* mUrlEntryHTTPLabel;
LLUrlEntryBase* mUrlEntrySLLabel;
LLUrlEntryBase* mUrlEntryNoLink;
LLUrlEntryBase* mUrlEntryKeybinding;
// <FS:Ansariel> Normalize only trusted URL
LLUrlEntryBase* mUrlEntryTrustedUrl;
// <FS:Ansariel> Wear folder SLUrl

View File

@ -367,6 +367,45 @@ std::string LLKeyboard::stringFromKey(KEY key, bool translate)
return res;
}
//static
std::string LLKeyboard::stringFromMouse(EMouseClickType click, bool translate)
{
std::string res;
switch (click)
{
case CLICK_LEFT:
res = "LMB";
break;
case CLICK_MIDDLE:
res = "MMB";
break;
case CLICK_RIGHT:
res = "RMB";
break;
case CLICK_BUTTON4:
res = "MB4";
break;
case CLICK_BUTTON5:
res = "MB5";
break;
case CLICK_DOUBLELEFT:
res = "Double LMB";
break;
default:
break;
}
if (translate && !res.empty())
{
LLKeyStringTranslatorFunc* trans = gKeyboard->mStringTranslator;
if (trans != NULL)
{
res = trans(res.c_str());
}
}
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator(MASK accel_mask)
{
@ -434,6 +473,18 @@ std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator(MASK accel_mask, EMouseClickType click)
{
std::string res;
if (CLICK_NONE == click)
{
return res;
}
res.append(stringFromAccelerator(accel_mask));
res.append(stringFromMouse(click));
return res;
}
//static
BOOL LLKeyboard::maskFromString(const std::string& str, MASK *mask)

View File

@ -111,8 +111,10 @@ public:
static BOOL maskFromString(const std::string& str, MASK *mask); // False on failure
static BOOL keyFromString(const std::string& str, KEY *key); // False on failure
static std::string stringFromKey(KEY key, bool translate = true);
static std::string stringFromMouse(EMouseClickType click, bool translate = true);
static std::string stringFromAccelerator( MASK accel_mask ); // separated for convinience, returns with "+": "Shift+" or "Shift+Alt+"...
static std::string stringFromAccelerator( MASK accel_mask, KEY key );
static std::string stringFromAccelerator(MASK accel_mask, EMouseClickType click);
void setCallbacks(LLWindowCallbacks *cbs) { mCallbacks = cbs; }
F32 getKeyElapsedTime( KEY key ); // Returns time in seconds since key was pressed.
@ -150,6 +152,13 @@ protected:
static std::map<std::string,KEY> sNamesToKeys;
};
// Interface to get key from assigned command
class LLKeyBindingToStringHandler
{
public:
virtual std::string getKeyBindingAsString(const std::string& mode, const std::string& control) const = 0;
};
extern LLKeyboard *gKeyboard;
#endif

View File

@ -211,6 +211,7 @@
#include "llhudeffecttrail.h"
#include "llvectorperfoptions.h"
#include "llslurl.h"
#include "llurlregistry.h"
#include "llwatchdog.h"
// Included so that constants/settings might be initialized
@ -5131,6 +5132,7 @@ void LLAppViewer::loadKeyBindings()
LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
}
}
LLUrlRegistry::instance().setKeybindingHandler(&gViewerInput);
}
void LLAppViewer::purgeCache()

View File

@ -418,11 +418,49 @@ void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator)
}
}
}
// static
std::string LLFloaterPreference::sSkin = "";
// handle secondlife:///app/worldmap/{NAME}/{COORDS} URLs
// Also see LLUrlEntryKeybinding, the value of this command type
// is ability to show up to date value in chat
class LLKeybindingHandler: public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLKeybindingHandler(): LLCommandHandler("keybinding", UNTRUSTED_CLICK_ONLY)
{
}
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{
if (params.size() < 1) return false;
LLFloaterPreference* prefsfloater = dynamic_cast<LLFloaterPreference*>
(LLFloaterReg::showInstance("preferences"));
if (prefsfloater)
{
// find 'controls' panel and bring it the front
LLTabContainer* tabcontainer = prefsfloater->getChild<LLTabContainer>("pref core");
LLPanel* panel = prefsfloater->getChild<LLPanel>("controls");
if (tabcontainer && panel)
{
tabcontainer->selectTabPanel(panel);
}
}
return true;
}
};
LLKeybindingHandler gKeybindHandler;
//////////////////////////////////////////////
// LLFloaterPreference
// static
std::string LLFloaterPreference::sSkin = "";
LLFloaterPreference::LLFloaterPreference(const LLSD& key)
: LLFloater(key),
mGotPersonalInfo(false),

View File

@ -534,20 +534,7 @@ void LLFriendCardsManager::syncFriendsFolder()
// Create own calling card if it was not found in Friends/All folder
if (!collector.isAgentCallingCardFound())
{
LLAvatarName av_name;
LLAvatarNameCache::get( gAgentID, &av_name );
create_inventory_item(gAgentID,
gAgent.getSessionID(),
calling_cards_folder_id,
LLTransactionID::tnull,
av_name.getCompleteName(),
gAgentID.asString(),
LLAssetType::AT_CALLINGCARD,
LLInventoryType::IT_CALLINGCARD,
NO_INV_SUBTYPE,
PERM_MOVE | PERM_TRANSFER,
NULL);
create_inventory_callingcard(gAgentID, calling_cards_folder_id);
}
// All folders created and updated.

View File

@ -4576,7 +4576,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|| is_recent_panel
|| !trash
|| trash->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN
|| trash->getDescendentCount() == LLViewerInventoryCategory::VERSION_UNKNOWN)
|| trash->getDescendentCount() == LLViewerInventoryCategory::VERSION_UNKNOWN
|| gAgentAvatarp->hasAttachmentsInTrash())
{
disabled_items.push_back(std::string("Empty Trash"));
}

View File

@ -74,40 +74,6 @@ std::string string_from_mask(MASK mask)
return res;
}
std::string string_from_mouse(EMouseClickType click, bool translate)
{
std::string res;
switch (click)
{
case CLICK_LEFT:
res = "LMB";
break;
case CLICK_MIDDLE:
res = "MMB";
break;
case CLICK_RIGHT:
res = "RMB";
break;
case CLICK_BUTTON4:
res = "MB4";
break;
case CLICK_BUTTON5:
res = "MB5";
break;
case CLICK_DOUBLELEFT:
res = "Double LMB";
break;
default:
break;
}
if (translate && !res.empty())
{
res = LLTrans::getString(res);
}
return res;
}
// LLKeyConflictHandler
S32 LLKeyConflictHandler::sTemporaryFileUseCount = 0;
@ -270,7 +236,7 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata)
result = LLKeyboard::stringFromAccelerator(keydata.mMask);
}
result += string_from_mouse(keydata.mMouse, true);
result += LLKeyboard::stringFromMouse(keydata.mMouse);
return result;
}
@ -545,7 +511,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary)
{
// set() because 'optional', for compatibility purposes
// just copy old keys.xml and rename to key_bindings.xml, it should work
binding.mouse.set(string_from_mouse(data.mMouse, false), true);
binding.mouse.set(LLKeyboard::stringFromMouse(data.mMouse, false), true);
}
binding.command = iter->first;
mode.bindings.add(binding);

View File

@ -406,7 +406,9 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
LL_WARNS() << "Error loading navigation bar context menu" << LL_ENDL;
}
getTextEntry()->setRightMouseUpCallback(boost::bind(&LLLocationInputCtrl::onTextEditorRightClicked,this,_2,_3,_4));
//don't show default context menu
getTextEntry()->setShowContextMenu(false);
getTextEntry()->setRightMouseDownCallback(boost::bind(&LLLocationInputCtrl::onTextEditorRightClicked, this, _2, _3, _4));
updateWidgetlayout();
// Connecting signal for updating location on "Show Coordinates" setting change.

View File

@ -1083,34 +1083,50 @@ LLViewerInput::LLViewerInput()
}
}
// static
BOOL LLViewerInput::modeFromString(const std::string& string, S32 *mode)
LLViewerInput::~LLViewerInput()
{
if (string == "FIRST_PERSON")
}
// static
bool LLViewerInput::modeFromString(const std::string& string, S32 *mode)
{
if (string.empty())
{
return false;
}
std::string cmp_string = string;
LLStringUtil::toLower(cmp_string);
if (cmp_string == "first_person")
{
*mode = MODE_FIRST_PERSON;
return TRUE;
return true;
}
else if (string == "THIRD_PERSON")
else if (cmp_string == "third_person")
{
*mode = MODE_THIRD_PERSON;
return TRUE;
return true;
}
else if (string == "EDIT_AVATAR")
else if (cmp_string == "edit_avatar")
{
*mode = MODE_EDIT_AVATAR;
return TRUE;
return true;
}
else if (string == "SITTING")
else if (cmp_string == "sitting")
{
*mode = MODE_SITTING;
return TRUE;
}
else
{
*mode = MODE_THIRD_PERSON;
return FALSE;
return true;
}
S32 val = atoi(string.c_str());
if (val >= 0 || val < MODE_COUNT)
{
*mode = val;
return true;
}
return false;
}
// static
@ -1315,6 +1331,7 @@ BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, cons
bind.mKey = key;
bind.mMask = mask;
bind.mFunction = function;
bind.mFunctionName = function_name;
if (result->mIsGlobal)
{
@ -1396,6 +1413,7 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
bind.mMouse = mouse;
bind.mMask = mask;
bind.mFunction = function;
bind.mFunctionName = function_name;
if (result->mIsGlobal)
{
@ -1894,3 +1912,49 @@ bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask
}
return false;
}
std::string LLViewerInput::getKeyBindingAsString(const std::string& mode, const std::string& control) const
{
S32 keyboard_mode;
if (!modeFromString(mode, &keyboard_mode))
{
keyboard_mode = getMode();
}
std::string res;
bool needs_separator = false;
// keybindings are sorted from having most mask to no mask (from restrictive to less restrictive),
// but it's visually better to present this data in reverse
std::vector<LLKeyboardBinding>::const_reverse_iterator iter_key = mKeyBindings[keyboard_mode].rbegin();
while (iter_key != mKeyBindings[keyboard_mode].rend())
{
if (iter_key->mFunctionName == control)
{
if (needs_separator)
{
res.append(" | ");
}
res.append(LLKeyboard::stringFromAccelerator(iter_key->mMask, iter_key->mKey));
needs_separator = true;
}
iter_key++;
}
std::vector<LLMouseBinding>::const_reverse_iterator iter_mouse = mMouseBindings[keyboard_mode].rbegin();
while (iter_mouse != mMouseBindings[keyboard_mode].rend())
{
if (iter_mouse->mFunctionName == control)
{
if (needs_separator)
{
res.append(" | ");
}
res.append(LLKeyboard::stringFromAccelerator(iter_mouse->mMask, iter_mouse->mMouse));
needs_separator = true;
}
iter_mouse++;
}
return res;
}

View File

@ -28,12 +28,13 @@
#define LL_LLVIEWERINPUT_H
#include "llkeyboard.h" // For EKeystate
#include "llinitparam.h"
const S32 MAX_KEY_BINDINGS = 128; // was 60
const S32 keybindings_xml_version = 1;
const std::string script_mouse_handler_name = "script_trigger_lbutton";
class LLWindow;
class LLNamedFunction
{
public:
@ -51,6 +52,7 @@ public:
MASK mMask;
LLKeyFunc mFunction;
std::string mFunctionName;
};
class LLMouseBinding
@ -60,6 +62,7 @@ public:
MASK mMask;
LLKeyFunc mFunction;
std::string mFunctionName;
};
@ -72,11 +75,7 @@ typedef enum e_keyboard_mode
MODE_COUNT
} EKeyboardMode;
class LLWindow;
void bind_keyboard_functions();
class LLViewerInput
class LLViewerInput : public LLKeyBindingToStringHandler
{
public:
struct KeyBinding : public LLInitParam::Block<KeyBinding>
@ -107,6 +106,7 @@ public:
};
LLViewerInput();
virtual ~LLViewerInput();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
BOOL handleKeyUp(KEY key, MASK mask);
@ -121,7 +121,7 @@ public:
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
EKeyboardMode getMode() const;
static BOOL modeFromString(const std::string& string, S32 *mode); // False on failure
static bool modeFromString(const std::string& string, S32 *mode); // False on failure
static BOOL mouseFromString(const std::string& string, EMouseClickType *mode);// False on failure
bool scanKey(KEY key,
@ -136,6 +136,9 @@ public:
bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const;
bool isLMouseHandlingDefault(const S32 mode) const { return mLMouseDefaultHandling[mode]; }
// inherited from LLKeyBindingToStringHandler
virtual std::string getKeyBindingAsString(const std::string& mode, const std::string& control) const override;
private:
bool scanKey(const std::vector<LLKeyboardBinding> &binding,
S32 binding_count,

View File

@ -1146,17 +1146,32 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
gAgent.sendReliableMessage();
}
void create_inventory_callingcard_callback(LLPointer<LLInventoryCallback> cb,
const LLUUID &parent,
const LLUUID &avatar_id,
const LLAvatarName &av_name)
{
std::string item_desc = avatar_id.asString();
create_inventory_item(gAgent.getID(),
gAgent.getSessionID(),
// <FS:Ansariel> Must provide a parent LLUUID; Default to calling card folder
//parent,
(parent.isNull() ? gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD) : parent),
// </FS:Ansariel>
LLTransactionID::tnull,
av_name.getUserName(),
item_desc,
LLAssetType::AT_CALLINGCARD,
LLInventoryType::IT_CALLINGCARD,
NO_INV_SUBTYPE,
PERM_MOVE | PERM_TRANSFER,
cb);
}
void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer<LLInventoryCallback> cb/*=NULL*/)
{
std::string item_desc = avatar_id.asString();
LLAvatarName av_name;
LLAvatarNameCache::get(avatar_id, &av_name);
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
// <FS:Ansariel> Must provide a parent LLUUID; Default to calling card folder
//parent, LLTransactionID::tnull, av_name.getUserName(), item_desc, LLAssetType::AT_CALLINGCARD,
(parent.isNull() ? gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD) : parent), LLTransactionID::tnull, av_name.getUserName(), item_desc, LLAssetType::AT_CALLINGCARD,
// </FS:Ansariel>
LLInventoryType::IT_CALLINGCARD, NO_INV_SUBTYPE, PERM_MOVE | PERM_TRANSFER, cb);
LLAvatarNameCache::get(avatar_id, boost::bind(&create_inventory_callingcard_callback, cb, parent, _1, _2));
}
void create_inventory_wearable(const LLUUID& agent_id, const LLUUID& session_id,

View File

@ -1785,6 +1785,27 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object)
return FALSE;
}
bool LLVOAvatarSelf::hasAttachmentsInTrash()
{
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter)
{
LLViewerJointAttachment *attachment = iter->second;
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *attached_object = attachment_iter->get();
if (attached_object && gInventory.isObjectDescendentOf(attached_object->getAttachmentItemID(), trash_id))
{
return true;
}
}
}
return false;
}
// static
BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id)
{

View File

@ -336,6 +336,8 @@ public:
/*virtual*/ BOOL detachObject(LLViewerObject *viewer_object);
static BOOL detachAttachmentIntoInventory(const LLUUID& item_id);
bool hasAttachmentsInTrash();
// [RLVa:KB] - Checked: 2012-07-28 (RLVa-1.4.7)
enum EAttachAction { ACTION_ATTACH, ACTION_DETACH };
typedef boost::signals2::signal<void (LLViewerObject*, const LLViewerJointAttachment*, EAttachAction)> attachment_signal_t;

View File

@ -1100,6 +1100,8 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)
readCacheHeader();
LL_INFOS() << "Viewer Object Cache Versions - expected: " << cache_version << " found: " << mMetaInfo.mVersion << LL_ENDL;
if( mMetaInfo.mVersion != cache_version
|| mMetaInfo.mAddressSize != expected_address)
{
@ -1110,7 +1112,8 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)
clearCacheInMemory();
}
else //delete the current cache if the format does not match.
{
{
LL_INFOS() << "Viewer Object Cache Versions unmatched. clearing cache." << LL_ENDL;
removeCache();
}
}