Merge branch 'DRTVWR-591-maint-X' into marchcat/591-x-pbr-merge
# Conflicts: # indra/llrender/llgl.cpp # indra/llrender/llvertexbuffer.cpp # indra/llui/llflatlistview.cpp # indra/newview/app_settings/settings.xml # indra/newview/lldrawpoolground.cpp # indra/newview/llinventorybridge.cpp # indra/newview/llinventorygallery.cpp # indra/newview/llspatialpartition.cpp # indra/newview/llviewercontrol.cpp # indra/newview/llviewertexture.cpp # indra/newview/llvosky.cpp # indra/newview/skins/default/xui/en/menu_inventory.xmlmaster
commit
27dae1d967
|
|
@ -240,6 +240,7 @@ Ansariel Hiller
|
|||
SL-18432
|
||||
SL-19140
|
||||
SL-4126
|
||||
SL-20524
|
||||
Aralara Rajal
|
||||
Arare Chantilly
|
||||
CHUIBUG-191
|
||||
|
|
@ -382,6 +383,7 @@ Chaser Zaks
|
|||
BUG-225599
|
||||
BUG-227485
|
||||
SL-16874
|
||||
SL-20442
|
||||
Cherry Cheevers
|
||||
ChickyBabes Zuzu
|
||||
Chorazin Allen
|
||||
|
|
|
|||
|
|
@ -42,16 +42,6 @@ const S32 GESTURE_VERSION = 2;
|
|||
// LLMultiGesture
|
||||
//---------------------------------------------------------------------------
|
||||
LLMultiGesture::LLMultiGesture()
|
||||
: mKey(),
|
||||
mMask(),
|
||||
mName(),
|
||||
mTrigger(),
|
||||
mReplaceText(),
|
||||
mSteps(),
|
||||
mPlaying(FALSE),
|
||||
mCurrentStep(0),
|
||||
mDoneCallback(NULL),
|
||||
mCallbackData(NULL)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
|
@ -67,8 +57,11 @@ void LLMultiGesture::reset()
|
|||
mPlaying = FALSE;
|
||||
mCurrentStep = 0;
|
||||
mWaitTimer.reset();
|
||||
mWaitingTimer = FALSE;
|
||||
mWaitingAnimations = FALSE;
|
||||
mWaitingKeyRelease = FALSE;
|
||||
mWaitingTimer = FALSE;
|
||||
mTriggeredByKey = FALSE;
|
||||
mKeyReleased = FALSE;
|
||||
mWaitingAtEnd = FALSE;
|
||||
mRequestedAnimIDs.clear();
|
||||
mPlayingAnimIDs.clear();
|
||||
|
|
|
|||
|
|
@ -59,11 +59,11 @@ protected:
|
|||
const LLMultiGesture& operator=(const LLMultiGesture& rhs);
|
||||
|
||||
public:
|
||||
KEY mKey;
|
||||
MASK mMask;
|
||||
KEY mKey { 0 };
|
||||
MASK mMask { 0 };
|
||||
|
||||
// This name can be empty if the inventory item is not around and
|
||||
// the gesture manager has not yet set the name
|
||||
// the gesture manager has not yet set the name
|
||||
std::string mName;
|
||||
|
||||
// String, like "/foo" or "hello" that makes it play
|
||||
|
|
@ -75,25 +75,34 @@ public:
|
|||
std::vector<LLGestureStep*> mSteps;
|
||||
|
||||
// Is the gesture currently playing?
|
||||
BOOL mPlaying;
|
||||
BOOL mPlaying { FALSE };
|
||||
|
||||
// "instruction pointer" for steps
|
||||
S32 mCurrentStep;
|
||||
S32 mCurrentStep { 0 };
|
||||
|
||||
// We're waiting for triggered animations to stop playing
|
||||
BOOL mWaitingAnimations;
|
||||
BOOL mWaitingAnimations { FALSE };
|
||||
|
||||
// We're waiting for key release
|
||||
BOOL mWaitingKeyRelease { FALSE };
|
||||
|
||||
// We're waiting a fixed amount of time
|
||||
BOOL mWaitingTimer;
|
||||
BOOL mWaitingTimer { FALSE };
|
||||
|
||||
// We're waiting for triggered animations to stop playing
|
||||
BOOL mTriggeredByKey { FALSE };
|
||||
|
||||
// Has the key been released?
|
||||
BOOL mKeyReleased { FALSE };
|
||||
|
||||
// Waiting after the last step played for all animations to complete
|
||||
BOOL mWaitingAtEnd;
|
||||
BOOL mWaitingAtEnd { FALSE };
|
||||
|
||||
// Timer for waiting
|
||||
LLFrameTimer mWaitTimer;
|
||||
|
||||
void (*mDoneCallback)(LLMultiGesture* gesture, void* data);
|
||||
void* mCallbackData;
|
||||
void (*mDoneCallback)(LLMultiGesture* gesture, void* data) { NULL };
|
||||
void* mCallbackData { NULL };
|
||||
|
||||
// Animations that we requested to start
|
||||
std::set<LLUUID> mRequestedAnimIDs;
|
||||
|
|
@ -210,6 +219,7 @@ public:
|
|||
|
||||
const U32 WAIT_FLAG_TIME = 0x01;
|
||||
const U32 WAIT_FLAG_ALL_ANIM = 0x02;
|
||||
const U32 WAIT_FLAG_KEY_RELEASE = 0x04;
|
||||
|
||||
class LLGestureStepWait : public LLGestureStep
|
||||
{
|
||||
|
|
|
|||
|
|
@ -600,6 +600,7 @@ std::string mbcsstring_makeASCII(const std::string& wstr)
|
|||
}
|
||||
return out_str;
|
||||
}
|
||||
|
||||
std::string utf8str_removeCRLF(const std::string& utf8str)
|
||||
{
|
||||
if (0 == utf8str.length())
|
||||
|
|
@ -621,6 +622,43 @@ std::string utf8str_removeCRLF(const std::string& utf8str)
|
|||
return out;
|
||||
}
|
||||
|
||||
// Search for any emoji symbol, return true if found
|
||||
bool wstring_has_emoji(const LLWString& wstr)
|
||||
{
|
||||
for (const llwchar& wch : wstr)
|
||||
{
|
||||
if (LLStringOps::isEmoji(wch))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cut emoji symbols if exist
|
||||
bool wstring_remove_emojis(LLWString& wstr)
|
||||
{
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < wstr.size(); ++i)
|
||||
{
|
||||
if (LLStringOps::isEmoji(wstr[i]))
|
||||
{
|
||||
wstr.erase(i--, 1);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// Cut emoji symbols if exist
|
||||
bool utf8str_remove_emojis(std::string& utf8str)
|
||||
{
|
||||
LLWString wstr = utf8str_to_wstring(utf8str);
|
||||
if (!wstring_remove_emojis(wstr))
|
||||
return false;
|
||||
utf8str = wstring_to_utf8str(wstr);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
unsigned int ll_wstring_default_code_page()
|
||||
{
|
||||
|
|
@ -833,6 +871,66 @@ std::string LLStringOps::sDayFormat;
|
|||
std::string LLStringOps::sAM;
|
||||
std::string LLStringOps::sPM;
|
||||
|
||||
// static
|
||||
bool LLStringOps::isEmoji(llwchar wch)
|
||||
{
|
||||
// Most of the following symbols are not actually emoticons, but rather small pictures
|
||||
|
||||
// 0x1F000 .. 0x1F02F - mahjong tiles
|
||||
// https://symbl.cc/en/unicode/table/#mahjong-tiles
|
||||
|
||||
// 0x1F030 .. 0x1F09F - domino tiles
|
||||
// https://symbl.cc/en/unicode/table/#domino-tiles
|
||||
|
||||
// 0x1F0A0 .. 0x1F0FF - playing cards
|
||||
// https://symbl.cc/en/unicode/table/#playing-cards
|
||||
|
||||
// 0x1F100 .. 0x1F1FF - enclosed alphanumeric supplement
|
||||
// https://symbl.cc/en/unicode/table/#enclosed-alphanumeric-supplement
|
||||
|
||||
// 0x1F200 .. 0x1F2FF - enclosed ideographic supplement
|
||||
// https://symbl.cc/en/unicode/table/#enclosed-ideographic-supplement
|
||||
|
||||
// 0x1F300 .. 0x1F5FF - miscellaneous symbols and pictographs
|
||||
// https://symbl.cc/en/unicode/table/#miscellaneous-symbols-and-pictographs
|
||||
|
||||
// 0x1F600 .. 0x1F64F - emoticons
|
||||
// https://symbl.cc/en/unicode/table/#emoticons
|
||||
|
||||
// 0x1F650 .. 0x1F67F - ornamental dingbats
|
||||
// https://symbl.cc/en/unicode/table/#ornamental-dingbats
|
||||
|
||||
// 0x1F680 .. 0x1F6FF - transport and map symbols
|
||||
// https://symbl.cc/en/unicode/table/#transport-and-map-symbols
|
||||
|
||||
// 0x1F700 .. 0x1F77F - alchemical symbols
|
||||
// https://symbl.cc/en/unicode/table/#alchemical-symbols
|
||||
|
||||
// 0x1F780 .. 0x1F7FF - geometric shapes extended
|
||||
// https://symbl.cc/en/unicode/table/#geometric-shapes-extended
|
||||
|
||||
// 0x1F800 .. 0x1F8FF - supplemental arrows c
|
||||
// https://symbl.cc/en/unicode/table/#supplemental-arrows-c
|
||||
|
||||
// 0x1F900 .. 0x1F9FF - supplemental symbols and pictographs
|
||||
// https://symbl.cc/en/unicode/table/#supplemental-symbols-and-pictographs
|
||||
|
||||
// 0x1FA00 .. 0x1FA6F - chess symbols
|
||||
// https://symbl.cc/en/unicode/table/#chess-symbols
|
||||
|
||||
// 0x1FA70 .. 0x1FAFF - symbols and pictographs extended a
|
||||
// https://symbl.cc/en/unicode/table/#symbols-and-pictographs-extended-a
|
||||
|
||||
// 0x1FB00 .. 0x1FBFF - symbols for legacy computing
|
||||
// https://symbl.cc/en/unicode/table/#symbols-for-legacy-computing
|
||||
|
||||
// 0x1FC00 .. 0x1FFFF - undefined block 44
|
||||
// These symbols aren't defined yet
|
||||
// https://symbl.cc/en/unicode/table/#undefined-block-44
|
||||
|
||||
return wch >= 0x1F000 && wch < 0x1FC00;
|
||||
}
|
||||
|
||||
|
||||
S32 LLStringOps::collate(const llwchar* a, const llwchar* b)
|
||||
{
|
||||
|
|
@ -1235,9 +1333,17 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
|
|||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
// EXT-1565 : Zai Lynch, James Linden : 15/Oct/09
|
||||
// [BSI] Feedback: Viewer clock mentions SLT, but would prefer it to show PST/PDT
|
||||
// "slt" = Second Life Time, which is deprecated.
|
||||
// If not utc or user local time, fallback to Pacific time
|
||||
replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST";
|
||||
#else
|
||||
// SL-20370 : Steeltoe Linden : 29/Sep/23
|
||||
// Change "PDT" to "SLT" on menu bar
|
||||
replacement = "SLT";
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,6 +189,8 @@ public:
|
|||
static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
|
||||
static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
|
||||
|
||||
static bool isEmoji(llwchar wch);
|
||||
|
||||
static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
|
||||
static S32 collate(const llwchar* a, const llwchar* b);
|
||||
|
||||
|
|
@ -737,6 +739,11 @@ LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str);
|
|||
|
||||
LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
|
||||
|
||||
LL_COMMON_API bool wstring_has_emoji(const LLWString& wstr);
|
||||
|
||||
LL_COMMON_API bool wstring_remove_emojis(LLWString& wstr);
|
||||
|
||||
LL_COMMON_API bool utf8str_remove_emojis(std::string& utf8str);
|
||||
|
||||
#if LL_WINDOWS
|
||||
/* @name Windows string helpers
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH = 1.0f;
|
|||
const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE = FALSE;
|
||||
const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE;
|
||||
|
||||
const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e";
|
||||
const LLUUID SCULPT_DEFAULT_TEXTURE("be293869-d0d9-0a69-5989-ad27f1946fd4"); // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e";
|
||||
|
||||
// Texture rotations are sent over the wire as a S16. This is used to scale the actual float
|
||||
// value to a S16. Don't use 7FFF as it introduces some odd rounding with 180 since it
|
||||
|
|
@ -2073,7 +2073,7 @@ bool LLFlexibleObjectData::fromLLSD(LLSD& sd)
|
|||
LLSculptParams::LLSculptParams()
|
||||
{
|
||||
mType = PARAMS_SCULPT;
|
||||
mSculptTexture.set(SCULPT_DEFAULT_TEXTURE);
|
||||
mSculptTexture = SCULPT_DEFAULT_TEXTURE;
|
||||
mSculptType = LL_SCULPT_TYPE_SPHERE;
|
||||
}
|
||||
|
||||
|
|
@ -2159,7 +2159,7 @@ void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type)
|
|||
U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK;
|
||||
if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX)
|
||||
{
|
||||
mSculptTexture.set(SCULPT_DEFAULT_TEXTURE);
|
||||
mSculptTexture = SCULPT_DEFAULT_TEXTURE;
|
||||
mSculptType = LL_SCULPT_TYPE_SPHERE;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ extern const F32 OBJECT_REV_MIN;
|
|||
extern const F32 OBJECT_REV_MAX;
|
||||
extern const F32 OBJECT_REV_INC;
|
||||
|
||||
extern const char *SCULPT_DEFAULT_TEXTURE;
|
||||
extern const LLUUID SCULPT_DEFAULT_TEXTURE;
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ void LLGLTexture::setBoostLevel(S32 level)
|
|||
{
|
||||
mBoostLevel = level ;
|
||||
if(mBoostLevel != LLGLTexture::BOOST_NONE
|
||||
&& mBoostLevel != LLGLTexture::BOOST_ICON)
|
||||
&& mBoostLevel != LLGLTexture::BOOST_ICON
|
||||
&& mBoostLevel != LLGLTexture::BOOST_THUMBNAIL)
|
||||
{
|
||||
setNoDelete() ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ public:
|
|||
BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay.
|
||||
BOOST_HUD ,
|
||||
BOOST_ICON ,
|
||||
BOOST_THUMBNAIL ,
|
||||
BOOST_UI ,
|
||||
BOOST_PREVIEW ,
|
||||
BOOST_MAP ,
|
||||
|
|
|
|||
|
|
@ -936,3 +936,20 @@ S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 availabl
|
|||
expanded_tab_height /= num_expanded;
|
||||
return expanded_tab_height;
|
||||
}
|
||||
|
||||
void LLAccordionCtrl::collapseAllTabs()
|
||||
{
|
||||
if (mAccordionTabs.size() > 0)
|
||||
{
|
||||
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
|
||||
{
|
||||
LLAccordionCtrlTab *tab = mAccordionTabs[i];
|
||||
|
||||
if (tab->getDisplayChildren())
|
||||
{
|
||||
tab->setDisplayChildren(false);
|
||||
}
|
||||
}
|
||||
arrange();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ public:
|
|||
void setComparator(const LLTabComparator* comp) { mTabComparator = comp; }
|
||||
void sort();
|
||||
|
||||
void collapseAllTabs();
|
||||
|
||||
/**
|
||||
* Sets filter substring as a search_term for help text when there are no any visible tabs.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -126,12 +126,12 @@ public:
|
|||
|
||||
void setSelected(bool is_selected);
|
||||
|
||||
bool getCollapsible() {return mCollapsible;};
|
||||
bool getCollapsible() { return mCollapsible; };
|
||||
|
||||
void setCollapsible(bool collapsible) {mCollapsible = collapsible;};
|
||||
void setCollapsible(bool collapsible) { mCollapsible = collapsible; };
|
||||
void changeOpenClose(bool is_open);
|
||||
|
||||
void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;};
|
||||
void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close; };
|
||||
bool canOpenClose() const { return mCanOpenClose; };
|
||||
|
||||
virtual BOOL postBuild();
|
||||
|
|
@ -142,8 +142,8 @@ public:
|
|||
|
||||
void draw();
|
||||
|
||||
void storeOpenCloseState ();
|
||||
void restoreOpenCloseState ();
|
||||
void storeOpenCloseState();
|
||||
void restoreOpenCloseState();
|
||||
|
||||
protected:
|
||||
LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&);
|
||||
|
|
|
|||
|
|
@ -58,10 +58,11 @@ static LLDefaultChildRegistry::Register<LLButton> r("button");
|
|||
template class LLButton* LLView::getChild<class LLButton>(
|
||||
const std::string& name, BOOL recurse) const;
|
||||
|
||||
// globals loaded from settings.xml
|
||||
S32 LLBUTTON_H_PAD = 0;
|
||||
S32 BTN_HEIGHT_SMALL= 0;
|
||||
S32 BTN_HEIGHT = 0;
|
||||
// globals
|
||||
S32 LLBUTTON_H_PAD = 4;
|
||||
S32 BTN_HEIGHT_SMALL= 23;
|
||||
S32 BTN_HEIGHT = 23;
|
||||
S32 BTN_DROP_SHADOW = 2;
|
||||
|
||||
LLButton::Params::Params()
|
||||
: label_selected("label_selected"), // requires is_toggle true
|
||||
|
|
@ -91,8 +92,8 @@ LLButton::Params::Params()
|
|||
image_overlay_disabled_color("image_overlay_disabled_color", LLColor4::white % 0.3f),
|
||||
image_overlay_selected_color("image_overlay_selected_color", LLColor4::white),
|
||||
flash_color("flash_color"),
|
||||
pad_right("pad_right", LLUI::getInstance()->mSettingGroups["config"]->getS32("ButtonHPad")),
|
||||
pad_left("pad_left", LLUI::getInstance()->mSettingGroups["config"]->getS32("ButtonHPad")),
|
||||
pad_right("pad_right", LLBUTTON_H_PAD),
|
||||
pad_left("pad_left", LLBUTTON_H_PAD),
|
||||
pad_bottom("pad_bottom"),
|
||||
click_callback("click_callback"),
|
||||
mouse_down_callback("mouse_down_callback"),
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@
|
|||
//
|
||||
|
||||
// PLEASE please use these "constants" when building your own buttons.
|
||||
// They are loaded from settings.xml at run time.
|
||||
extern S32 LLBUTTON_H_PAD;
|
||||
extern S32 BTN_HEIGHT_SMALL;
|
||||
extern S32 BTN_HEIGHT;
|
||||
extern S32 BTN_DROP_SHADOW;
|
||||
|
||||
//
|
||||
// Helpful functions
|
||||
|
|
|
|||
|
|
@ -482,8 +482,6 @@ void LLComboBox::onFocusLost()
|
|||
|
||||
void LLComboBox::setButtonVisible(BOOL visible)
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
|
||||
|
||||
mButton->setVisible(visible);
|
||||
if (mTextEntry)
|
||||
{
|
||||
|
|
@ -491,7 +489,7 @@ void LLComboBox::setButtonVisible(BOOL visible)
|
|||
if (visible)
|
||||
{
|
||||
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW;
|
||||
}
|
||||
//mTextEntry->setRect(text_entry_rect);
|
||||
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
|
||||
|
|
@ -530,19 +528,18 @@ void LLComboBox::setEnabledByValue(const LLSD& value, BOOL enabled)
|
|||
|
||||
void LLComboBox::createLineEditor(const LLComboBox::Params& p)
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
|
||||
LLRect rect = getLocalRect();
|
||||
if (mAllowTextEntry)
|
||||
{
|
||||
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
||||
S32 shadow_size = drop_shadow_button;
|
||||
S32 shadow_size = BTN_DROP_SHADOW;
|
||||
mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size,
|
||||
rect.mTop, rect.mRight, rect.mBottom));
|
||||
mButton->setTabStop(FALSE);
|
||||
mButton->setHAlign(LLFontGL::HCENTER);
|
||||
|
||||
LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW;
|
||||
// clear label on button
|
||||
std::string cur_label = mButton->getLabelSelected();
|
||||
LLLineEditor::Params params = p.combo_editor;
|
||||
|
|
@ -1081,13 +1078,11 @@ void LLComboBox::onSetHighlight() const
|
|||
|
||||
void LLComboBox::imageLoaded()
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_button("DropShadowButton", 0);
|
||||
|
||||
if (mAllowTextEntry)
|
||||
{
|
||||
LLRect rect = getLocalRect();
|
||||
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
||||
S32 shadow_size = drop_shadow_button;
|
||||
S32 shadow_size = BTN_DROP_SHADOW;
|
||||
mButton->setRect(LLRect(getRect().getWidth() - llmax(8, arrow_width) - 2 * shadow_size,
|
||||
rect.mTop, rect.mRight, rect.mBottom));
|
||||
if (mButton->getVisible())
|
||||
|
|
@ -1096,7 +1091,7 @@ void LLComboBox::imageLoaded()
|
|||
if (mTextEntry)
|
||||
{
|
||||
LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * drop_shadow_button;
|
||||
text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * BTN_DROP_SHADOW;
|
||||
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1361,26 +1361,28 @@ void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show)
|
|||
mForceShowingUnmatchedItems = show;
|
||||
}
|
||||
|
||||
void LLFlatListViewEx::setFilterSubString(const std::string& filter_str)
|
||||
void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent)
|
||||
{
|
||||
if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString))
|
||||
{
|
||||
mFilterSubString = filter_str;
|
||||
updateNoItemsMessage(mFilterSubString);
|
||||
filterItems();
|
||||
filterItems(false, notify_parent);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action)
|
||||
bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action)
|
||||
{
|
||||
if (!item) return;
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
BOOL visible = TRUE;
|
||||
|
||||
// 0 signifies that filter is matched,
|
||||
// i.e. we don't hide items that don't support 'match_filter' action, separators etc.
|
||||
if (0 == item->notify(action))
|
||||
{
|
||||
mHasMatchedItems = true;
|
||||
item->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1388,34 +1390,45 @@ void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action)
|
|||
if (!mForceShowingUnmatchedItems)
|
||||
{
|
||||
selectItem(item, false);
|
||||
visible = FALSE;
|
||||
}
|
||||
item->setVisible(mForceShowingUnmatchedItems);
|
||||
}
|
||||
|
||||
if (item->getVisible() != visible)
|
||||
{
|
||||
item->setVisible(visible);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFlatListViewEx::filterItems()
|
||||
void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent)
|
||||
{
|
||||
typedef std::vector <LLPanel*> item_panel_list_t;
|
||||
|
||||
std::string cur_filter = mFilterSubString;
|
||||
LLStringUtil::toUpper(cur_filter);
|
||||
|
||||
LLSD action;
|
||||
action.with("match_filter", cur_filter);
|
||||
|
||||
item_panel_list_t items;
|
||||
getItems(items);
|
||||
|
||||
mHasMatchedItems = false;
|
||||
item_panel_list_t::iterator iter = items.begin(), iter_end = items.end();
|
||||
while (iter < iter_end)
|
||||
bool visibility_changed = false;
|
||||
pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end();
|
||||
while (iter != iter_end)
|
||||
{
|
||||
LLPanel* pItem = *(iter++);
|
||||
updateItemVisibility(pItem, action);
|
||||
LLPanel* pItem = (*(iter++))->first;
|
||||
visibility_changed |= updateItemVisibility(pItem, action);
|
||||
}
|
||||
|
||||
sort();
|
||||
notifyParentItemsRectChanged();
|
||||
if (re_sort)
|
||||
{
|
||||
sort();
|
||||
}
|
||||
|
||||
if (visibility_changed && notify_parent)
|
||||
{
|
||||
notifyParentItemsRectChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFlatListViewEx::hasMatchedItems()
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ public:
|
|||
virtual S32 notify(const LLSD& info) ;
|
||||
|
||||
virtual ~LLFlatListView();
|
||||
|
||||
protected:
|
||||
|
||||
/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
|
||||
|
|
@ -375,7 +376,9 @@ protected:
|
|||
|
||||
LLRect getLastSelectedItemRect();
|
||||
|
||||
void ensureSelectedVisible();
|
||||
void ensureSelectedVisible();
|
||||
|
||||
const pairs_list_t& getItemPairs() { return mItemPairs; }
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -482,14 +485,14 @@ public:
|
|||
/**
|
||||
* Sets up new filter string and filters the list.
|
||||
*/
|
||||
void setFilterSubString(const std::string& filter_str);
|
||||
void setFilterSubString(const std::string& filter_str, bool notify_parent);
|
||||
std::string getFilterSubString() { return mFilterSubString; }
|
||||
|
||||
/**
|
||||
* Filters the list, rearranges and notifies parent about shape changes.
|
||||
* Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration.
|
||||
*/
|
||||
void filterItems();
|
||||
void filterItems(bool re_sort, bool notify_parent);
|
||||
|
||||
/**
|
||||
* Returns true if last call of filterItems() found at least one matching item
|
||||
|
|
@ -513,7 +516,7 @@ protected:
|
|||
* @param item - item we are changing
|
||||
* @param item - action - parameters to determin visibility from
|
||||
*/
|
||||
void updateItemVisibility(LLPanel* item, const LLSD &action);
|
||||
bool updateItemVisibility(LLPanel* item, const LLSD &action);
|
||||
|
||||
private:
|
||||
std::string mNoFilteredItemsMsg;
|
||||
|
|
|
|||
|
|
@ -1961,10 +1961,9 @@ void LLFloater::drawShadow(LLPanel* panel)
|
|||
S32 right = panel->getRect().getWidth() - LLPANEL_BORDER_WIDTH;
|
||||
S32 bottom = LLPANEL_BORDER_WIDTH;
|
||||
|
||||
static LLUICachedControl<S32> shadow_offset_S32 ("DropShadowFloater", 0);
|
||||
static LLUIColor shadow_color_cached = LLUIColorTable::instance().getColor("ColorDropShadow");
|
||||
LLColor4 shadow_color = shadow_color_cached;
|
||||
F32 shadow_offset = (F32)shadow_offset_S32;
|
||||
F32 shadow_offset = (F32)DROP_SHADOW_FLOATER;
|
||||
|
||||
if (!panel->isBackgroundOpaque())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ const BOOL CLOSE_NO = FALSE;
|
|||
const BOOL ADJUST_VERTICAL_YES = TRUE;
|
||||
const BOOL ADJUST_VERTICAL_NO = FALSE;
|
||||
|
||||
const F32 CONTEXT_CONE_IN_ALPHA = 0.f;
|
||||
const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
|
||||
const F32 CONTEXT_CONE_FADE_TIME = .08f;
|
||||
|
||||
namespace LLFloaterEnums
|
||||
{
|
||||
enum EOpenPositioning
|
||||
|
|
|
|||
|
|
@ -335,9 +335,9 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height )
|
|||
void LLFolderView::filter( LLFolderViewFilter& filter )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
|
||||
static LLCachedControl<S32> time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
|
||||
static LLCachedControl<S32> time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1);
|
||||
filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100));
|
||||
const S32 TIME_VISIBLE = 10; // in milliseconds
|
||||
const S32 TIME_INVISIBLE = 1;
|
||||
filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? TIME_VISIBLE : TIME_INVISIBLE), 1, 100));
|
||||
|
||||
// Note: we filter the model, not the view
|
||||
getViewModelItem()->filter(filter);
|
||||
|
|
@ -765,7 +765,7 @@ void LLFolderView::removeSelectedItems()
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Cannot delete " << item->getName() << LL_ENDL;
|
||||
LL_DEBUGS() << "Cannot delete " << item->getName() << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -601,15 +601,13 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )
|
|||
|
||||
BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
static LLCachedControl<S32> drag_and_drop_threshold(*LLUI::getInstance()->mSettingGroups["config"],"DragAndDropDistanceThreshold", 3);
|
||||
|
||||
mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight));
|
||||
|
||||
if( hasMouseCapture() && isMovable() )
|
||||
{
|
||||
LLFolderView* root = getRoot();
|
||||
|
||||
if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold()
|
||||
if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD
|
||||
&& root->getAllowDrag()
|
||||
&& root->getCurSelectedItem()
|
||||
&& root->startDrag())
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ std::string LLFolderViewModelCommon::getStatusText(bool is_empty_folder)
|
|||
|
||||
void LLFolderViewModelCommon::filter()
|
||||
{
|
||||
static LLCachedControl<S32> max_time(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
|
||||
getFilter().resetTime(llclamp(max_time(), 1, 100));
|
||||
const S32 MAX_FILTER_TIME = 10;
|
||||
getFilter().resetTime(MAX_FILTER_TIME);
|
||||
mFolderView->getViewModelItem()->filter(getFilter());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ public:
|
|||
virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder
|
||||
virtual void move( LLFolderViewModelItem* parent_listener ) = 0;
|
||||
|
||||
virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed
|
||||
virtual BOOL isItemRemovable( bool check_worn = true ) const = 0; // Can be destroyed
|
||||
virtual BOOL removeItem() = 0;
|
||||
virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ LLLineEditor::Params::Params()
|
|||
commit_on_focus_lost("commit_on_focus_lost", true),
|
||||
ignore_tab("ignore_tab", true),
|
||||
is_password("is_password", false),
|
||||
allow_emoji("allow_emoji"),
|
||||
cursor_color("cursor_color"),
|
||||
use_bg_color("use_bg_color", false),
|
||||
bg_color("bg_color"),
|
||||
|
|
@ -141,6 +142,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
|
|||
mIgnoreArrowKeys( FALSE ),
|
||||
mIgnoreTab( p.ignore_tab ),
|
||||
mDrawAsterixes( p.is_password ),
|
||||
mAllowEmoji( p.allow_emoji ),
|
||||
mSpellCheck( p.spellcheck ),
|
||||
mSpellCheckStart(-1),
|
||||
mSpellCheckEnd(-1),
|
||||
|
|
@ -413,8 +415,13 @@ void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit
|
|||
all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived);
|
||||
|
||||
std::string truncated_utf8 = new_text;
|
||||
if (!mAllowEmoji)
|
||||
{
|
||||
// Cut emoji symbols if exist
|
||||
utf8str_remove_emojis(truncated_utf8);
|
||||
}
|
||||
if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes)
|
||||
{
|
||||
{
|
||||
truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes);
|
||||
}
|
||||
mText.assign(truncated_utf8);
|
||||
|
|
@ -586,13 +593,21 @@ void LLLineEditor::replaceWithSuggestion(U32 index)
|
|||
{
|
||||
if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) )
|
||||
{
|
||||
LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]);
|
||||
if (!mAllowEmoji)
|
||||
{
|
||||
// Cut emoji symbols if exist
|
||||
wstring_remove_emojis(suggestion);
|
||||
}
|
||||
if (suggestion.empty())
|
||||
return;
|
||||
|
||||
deselect();
|
||||
|
||||
// Delete the misspelled word
|
||||
mText.erase(it->first, it->second - it->first);
|
||||
|
||||
// Insert the suggestion in its place
|
||||
LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]);
|
||||
mText.insert(it->first, suggestion);
|
||||
setCursor(it->first + (S32)suggestion.length());
|
||||
|
||||
|
|
@ -955,9 +970,11 @@ void LLLineEditor::removeChar()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void LLLineEditor::addChar(const llwchar uni_char)
|
||||
{
|
||||
if (!mAllowEmoji && LLStringOps::isEmoji(uni_char))
|
||||
return;
|
||||
|
||||
llwchar new_c = uni_char;
|
||||
if (hasSelection())
|
||||
{
|
||||
|
|
@ -1257,6 +1274,11 @@ void LLLineEditor::pasteHelper(bool is_primary)
|
|||
|
||||
if (!paste.empty())
|
||||
{
|
||||
if (!mAllowEmoji)
|
||||
{
|
||||
wstring_remove_emojis(paste);
|
||||
}
|
||||
|
||||
if (!prevalidateInput(paste))
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ public:
|
|||
ignore_tab,
|
||||
bg_image_always_focused,
|
||||
is_password,
|
||||
allow_emoji,
|
||||
use_bg_color;
|
||||
|
||||
// colors
|
||||
|
|
@ -238,6 +239,7 @@ public:
|
|||
void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; }
|
||||
void setIgnoreTab(BOOL b) { mIgnoreTab = b; }
|
||||
void setPassDelete(BOOL b) { mPassDelete = b; }
|
||||
void setAllowEmoji(BOOL b) { mAllowEmoji = b; }
|
||||
void setDrawAsterixes(BOOL b);
|
||||
|
||||
// get the cursor position of the beginning/end of the prev/next word in the text
|
||||
|
|
@ -396,6 +398,7 @@ protected:
|
|||
|
||||
BOOL mShowImageFocused;
|
||||
|
||||
bool mAllowEmoji;
|
||||
bool mUseBgColor;
|
||||
|
||||
LLWString mPreeditWString;
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@
|
|||
LLMenuHolderGL *LLMenuGL::sMenuContainer = NULL;
|
||||
view_listener_t::listener_map_t view_listener_t::sListeners;
|
||||
|
||||
S32 MENU_BAR_HEIGHT = 0;
|
||||
S32 MENU_BAR_WIDTH = 0;
|
||||
S32 MENU_BAR_HEIGHT = 18;
|
||||
S32 MENU_BAR_WIDTH = 410;
|
||||
|
||||
///============================================================================
|
||||
/// Local function declarations, constants, enums, and typedefs
|
||||
|
|
@ -3229,10 +3229,9 @@ void LLMenuGL::draw( void )
|
|||
}
|
||||
if (mDropShadowed && !mTornOff)
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0);
|
||||
static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
|
||||
gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
|
||||
color_drop_shadow, drop_shadow_floater );
|
||||
color_drop_shadow, DROP_SHADOW_FLOATER);
|
||||
}
|
||||
|
||||
if( mBgVisible )
|
||||
|
|
|
|||
|
|
@ -284,10 +284,9 @@ BOOL LLModalDialog::handleKeyHere(KEY key, MASK mask )
|
|||
void LLModalDialog::draw()
|
||||
{
|
||||
static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow");
|
||||
static LLUICachedControl<S32> shadow_lines ("DropShadowFloater", 0);
|
||||
|
||||
gl_drop_shadow( 0, getRect().getHeight(), getRect().getWidth(), 0,
|
||||
shadow_color, shadow_lines);
|
||||
shadow_color, DROP_SHADOW_FLOATER);
|
||||
|
||||
LLFloater::draw();
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ LLNotificationForm::FormInput::FormInput()
|
|||
: type("type"),
|
||||
text("text"),
|
||||
max_length_chars("max_length_chars"),
|
||||
allow_emoji("allow_emoji"),
|
||||
width("width", 0),
|
||||
value("value")
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ public:
|
|||
Mandatory<std::string> type;
|
||||
Optional<S32> width;
|
||||
Optional<S32> max_length_chars;
|
||||
Optional<bool> allow_emoji;
|
||||
Optional<std::string> text;
|
||||
|
||||
Optional<std::string> value;
|
||||
|
|
|
|||
|
|
@ -225,7 +225,8 @@ LLTabContainer::Params::Params()
|
|||
tabs_flashing_color("tabs_flashing_color"),
|
||||
tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
|
||||
use_ellipses("use_ellipses"),
|
||||
font_halign("halign")
|
||||
font_halign("halign"),
|
||||
use_tab_offset("use_tab_offset", false)
|
||||
{}
|
||||
|
||||
LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
|
||||
|
|
@ -264,7 +265,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
|
|||
mTabIconCtrlPad(p.tab_icon_ctrl_pad),
|
||||
mEnableTabsFlashing(p.enable_tabs_flashing),
|
||||
mTabsFlashingColor(p.tabs_flashing_color),
|
||||
mUseTabEllipses(p.use_ellipses)
|
||||
mUseTabEllipses(p.use_ellipses),
|
||||
mUseTabOffset(p.use_tab_offset)
|
||||
{
|
||||
static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0);
|
||||
|
||||
|
|
@ -1023,11 +1025,10 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
|
|||
}
|
||||
else
|
||||
{
|
||||
tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH * 3,
|
||||
tab_panel_top,
|
||||
getRect().getWidth() - LLPANEL_BORDER_WIDTH * 2,
|
||||
tab_panel_bottom );
|
||||
}
|
||||
S32 left_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 3 : LLPANEL_BORDER_WIDTH;
|
||||
S32 right_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 2 : LLPANEL_BORDER_WIDTH;
|
||||
tab_panel_rect = LLRect(left_offset, tab_panel_top, getRect().getWidth() - right_offset, tab_panel_bottom);
|
||||
}
|
||||
child->setFollowsAll();
|
||||
child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom);
|
||||
child->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
|
||||
|
|
@ -1516,25 +1517,23 @@ BOOL LLTabContainer::selectTab(S32 which)
|
|||
|
||||
LLTabTuple* selected_tuple = getTab(which);
|
||||
if (!selected_tuple)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
LLSD cbdata;
|
||||
if (selected_tuple->mTabPanel)
|
||||
cbdata = selected_tuple->mTabPanel->getName();
|
||||
|
||||
BOOL res = FALSE;
|
||||
if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) )
|
||||
BOOL result = FALSE;
|
||||
if (!mValidateSignal || (*mValidateSignal)(this, cbdata))
|
||||
{
|
||||
res = setTab(which);
|
||||
if (res && mCommitSignal)
|
||||
result = setTab(which);
|
||||
if (result && mCommitSignal)
|
||||
{
|
||||
(*mCommitSignal)(this, cbdata);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// private
|
||||
|
|
|
|||
|
|
@ -121,6 +121,8 @@ public:
|
|||
*/
|
||||
Optional<S32> tab_icon_ctrl_pad;
|
||||
|
||||
Optional<bool> use_tab_offset;
|
||||
|
||||
Params();
|
||||
};
|
||||
|
||||
|
|
@ -321,6 +323,8 @@ private:
|
|||
S32 mTabIconCtrlPad;
|
||||
bool mUseTabEllipses;
|
||||
LLFrameTimer mMouseDownTimer;
|
||||
|
||||
bool mUseTabOffset;
|
||||
};
|
||||
|
||||
#endif // LL_TABCONTAINER_H
|
||||
|
|
|
|||
|
|
@ -1134,8 +1134,7 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask)
|
|||
BOOL handled = FALSE;
|
||||
|
||||
S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY);
|
||||
static LLCachedControl<S32> drag_threshold(*LLUI::getInstance()->mSettingGroups["config"], "DragAndDropDistanceThreshold", 3);
|
||||
if (mouse_distance_squared > drag_threshold * drag_threshold
|
||||
if (mouse_distance_squared > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD
|
||||
&& hasMouseCapture() &&
|
||||
mStartDragItemCallback && mHandleDragItemCallback)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<s
|
|||
bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root, LLDir::ALL_SKINS);
|
||||
if (!success)
|
||||
{
|
||||
gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
|
||||
LL_ERRS() << "Couldn't load string table " << xml_filename << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
//gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
|
||||
LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class LLWindow;
|
|||
class LLView;
|
||||
class LLHelp;
|
||||
|
||||
|
||||
const S32 DRAG_N_DROP_DISTANCE_THRESHOLD = 3;
|
||||
// this enum is used by the llview.h (viewer) and the llassetstorage.h (viewer and sim)
|
||||
enum EDragAndDropType
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
const BOOL TAKE_FOCUS_YES = TRUE;
|
||||
const BOOL TAKE_FOCUS_NO = FALSE;
|
||||
const S32 DROP_SHADOW_FLOATER = 5;
|
||||
|
||||
class LLUICtrl
|
||||
: public LLView, public boost::signals2::trackable
|
||||
|
|
|
|||
|
|
@ -199,7 +199,13 @@ public:
|
|||
|
||||
// windows only DirectInput8 for joysticks
|
||||
virtual void* getDirectInput8() { return NULL; };
|
||||
virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; };
|
||||
virtual bool getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
virtual S32 getRefreshRate() { return mRefreshRate; }
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <errno.h>
|
||||
#include "llopenglview-objc.h"
|
||||
#include "llwindowmacosx-objc.h"
|
||||
#include "llappdelegate-objc.h"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,13 @@
|
|||
#include <CoreServices/CoreServices.h>
|
||||
#include <CoreGraphics/CGDisplayConfiguration.h>
|
||||
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOMessage.h>
|
||||
#include <IOKit/hid/IOHIDUsageTables.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/usb/IOUSBLib.h>
|
||||
|
||||
extern BOOL gDebugWindowProc;
|
||||
BOOL gHiDPISupport = TRUE;
|
||||
|
||||
|
|
@ -212,13 +219,16 @@ bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
|
|||
|
||||
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wchar_t character)
|
||||
{
|
||||
if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
|
||||
//if (mask!=MASK_NONE)
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Y');
|
||||
}
|
||||
else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Z');
|
||||
if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Y');
|
||||
}
|
||||
else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Z');
|
||||
}
|
||||
}
|
||||
|
||||
mRawKeyEvent = event;
|
||||
|
|
@ -1841,6 +1851,488 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
|
|||
}
|
||||
}
|
||||
|
||||
// String should match ndof, so string mapping code was copied as is
|
||||
static char mapChar( char c )
|
||||
{
|
||||
unsigned char uc = ( unsigned char ) c;
|
||||
|
||||
switch( uc )
|
||||
{
|
||||
case '/': return '-'; // use dash instead of slash
|
||||
|
||||
case 0x7F: return ' ';
|
||||
case 0x80: return 'A';
|
||||
case 0x81: return 'A';
|
||||
case 0x82: return 'C';
|
||||
case 0x83: return 'E';
|
||||
case 0x84: return 'N';
|
||||
case 0x85: return 'O';
|
||||
case 0x86: return 'U';
|
||||
case 0x87: return 'a';
|
||||
case 0x88: return 'a';
|
||||
case 0x89: return 'a';
|
||||
case 0x8A: return 'a';
|
||||
case 0x8B: return 'a';
|
||||
case 0x8C: return 'a';
|
||||
case 0x8D: return 'c';
|
||||
case 0x8E: return 'e';
|
||||
case 0x8F: return 'e';
|
||||
case 0x90: return ' ';
|
||||
case 0x91: return ' '; // ? '
|
||||
case 0x92: return ' '; // ? '
|
||||
case 0x93: return ' '; // ? "
|
||||
case 0x94: return ' '; // ? "
|
||||
case 0x95: return ' ';
|
||||
case 0x96: return ' ';
|
||||
case 0x97: return ' ';
|
||||
case 0x98: return ' ';
|
||||
case 0x99: return ' ';
|
||||
case 0x9A: return ' ';
|
||||
case 0x9B: return 0x27;
|
||||
case 0x9C: return 0x22;
|
||||
case 0x9D: return ' ';
|
||||
case 0x9E: return ' ';
|
||||
case 0x9F: return ' ';
|
||||
case 0xA0: return ' ';
|
||||
case 0xA1: return ' ';
|
||||
case 0xA2: return ' ';
|
||||
case 0xA3: return ' ';
|
||||
case 0xA4: return ' ';
|
||||
case 0xA5: return ' ';
|
||||
case 0xA6: return ' ';
|
||||
case 0xA7: return ' ';
|
||||
case 0xA8: return ' ';
|
||||
case 0xA9: return ' ';
|
||||
case 0xAA: return ' ';
|
||||
case 0xAB: return ' ';
|
||||
case 0xAC: return ' ';
|
||||
case 0xAD: return ' ';
|
||||
case 0xAE: return ' ';
|
||||
case 0xAF: return ' ';
|
||||
case 0xB0: return ' ';
|
||||
case 0xB1: return ' ';
|
||||
case 0xB2: return ' ';
|
||||
case 0xB3: return ' ';
|
||||
case 0xB4: return ' ';
|
||||
case 0xB5: return ' ';
|
||||
case 0xB6: return ' ';
|
||||
case 0xB7: return ' ';
|
||||
case 0xB8: return ' ';
|
||||
case 0xB9: return ' ';
|
||||
case 0xBA: return ' ';
|
||||
case 0xBB: return ' ';
|
||||
case 0xBC: return ' ';
|
||||
case 0xBD: return ' ';
|
||||
case 0xBE: return ' ';
|
||||
case 0xBF: return ' ';
|
||||
case 0xC0: return ' ';
|
||||
case 0xC1: return ' ';
|
||||
case 0xC2: return ' ';
|
||||
case 0xC3: return ' ';
|
||||
case 0xC4: return ' ';
|
||||
case 0xC5: return ' ';
|
||||
case 0xC6: return ' ';
|
||||
case 0xC7: return ' ';
|
||||
case 0xC8: return ' ';
|
||||
case 0xC9: return ' ';
|
||||
case 0xCA: return ' ';
|
||||
case 0xCB: return 'A';
|
||||
case 0xCC: return 'A';
|
||||
case 0xCD: return 'O';
|
||||
case 0xCE: return ' ';
|
||||
case 0xCF: return ' ';
|
||||
case 0xD0: return '-';
|
||||
case 0xD1: return '-';
|
||||
case 0xD2: return 0x22;
|
||||
case 0xD3: return 0x22;
|
||||
case 0xD4: return 0x27;
|
||||
case 0xD5: return 0x27;
|
||||
case 0xD6: return '-'; // use dash instead of slash
|
||||
case 0xD7: return ' ';
|
||||
case 0xD8: return 'y';
|
||||
case 0xD9: return 'Y';
|
||||
case 0xDA: return '-'; // use dash instead of slash
|
||||
case 0xDB: return ' ';
|
||||
case 0xDC: return '<';
|
||||
case 0xDD: return '>';
|
||||
case 0xDE: return ' ';
|
||||
case 0xDF: return ' ';
|
||||
case 0xE0: return ' ';
|
||||
case 0xE1: return ' ';
|
||||
case 0xE2: return ',';
|
||||
case 0xE3: return ',';
|
||||
case 0xE4: return ' ';
|
||||
case 0xE5: return 'A';
|
||||
case 0xE6: return 'E';
|
||||
case 0xE7: return 'A';
|
||||
case 0xE8: return 'E';
|
||||
case 0xE9: return 'E';
|
||||
case 0xEA: return 'I';
|
||||
case 0xEB: return 'I';
|
||||
case 0xEC: return 'I';
|
||||
case 0xED: return 'I';
|
||||
case 0xEE: return 'O';
|
||||
case 0xEF: return 'O';
|
||||
case 0xF0: return ' ';
|
||||
case 0xF1: return 'O';
|
||||
case 0xF2: return 'U';
|
||||
case 0xF3: return 'U';
|
||||
case 0xF4: return 'U';
|
||||
case 0xF5: return '|';
|
||||
case 0xF6: return ' ';
|
||||
case 0xF7: return ' ';
|
||||
case 0xF8: return ' ';
|
||||
case 0xF9: return ' ';
|
||||
case 0xFA: return '.';
|
||||
case 0xFB: return ' ';
|
||||
case 0xFC: return ' ';
|
||||
case 0xFD: return 0x22;
|
||||
case 0xFE: return ' ';
|
||||
case 0xFF: return ' ';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// String should match ndof for manufacturer based search to work
|
||||
static void sanitizeString( char* inCStr )
|
||||
{
|
||||
char* charIt = inCStr;
|
||||
while ( *charIt )
|
||||
{
|
||||
*charIt = mapChar( *charIt );
|
||||
charIt++;
|
||||
}
|
||||
}
|
||||
|
||||
struct HidDevice
|
||||
{
|
||||
long mAxis;
|
||||
long mLocalID;
|
||||
char mProduct[256];
|
||||
char mManufacturer[256];
|
||||
long mUsage;
|
||||
long mUsagePage;
|
||||
};
|
||||
|
||||
static void populate_device_info( io_object_t io_obj_p, CFDictionaryRef device_dic, HidDevice* devicep )
|
||||
{
|
||||
CFMutableDictionaryRef io_properties = nil;
|
||||
io_registry_entry_t entry1;
|
||||
io_registry_entry_t entry2;
|
||||
kern_return_t rc;
|
||||
|
||||
// Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also
|
||||
// get dictionary for usb properties: step up two levels and get CF dictionary for USB properties
|
||||
// try to get parent1
|
||||
rc = IORegistryEntryGetParentEntry( io_obj_p, kIOServicePlane, &entry1 );
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
rc = IORegistryEntryGetParentEntry( entry1, kIOServicePlane, &entry2 );
|
||||
|
||||
IOObjectRelease( entry1 );
|
||||
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
rc = IORegistryEntryCreateCFProperties( entry2, &io_properties, kCFAllocatorDefault, kNilOptions );
|
||||
// either way, release parent2
|
||||
IOObjectRelease( entry2 );
|
||||
}
|
||||
}
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
// IORegistryEntryCreateCFProperties() succeeded
|
||||
if ( io_properties != nil )
|
||||
{
|
||||
CFTypeRef dict_element = 0;
|
||||
// get device info
|
||||
// try hid dictionary first, if fail then go to usb dictionary
|
||||
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR(kIOHIDProductKey) );
|
||||
if ( !dict_element )
|
||||
{
|
||||
dict_element = CFDictionaryGetValue( io_properties, CFSTR( "USB Product Name" ) );
|
||||
}
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFStringGetCString((CFStringRef)dict_element, devicep->mProduct, 256, kCFStringEncodingUTF8);
|
||||
sanitizeString(devicep->mProduct);
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mProduct" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDManufacturerKey ) );
|
||||
if ( !dict_element )
|
||||
{
|
||||
dict_element = CFDictionaryGetValue( io_properties, CFSTR( "USB Vendor Name" ) );
|
||||
}
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFStringGetCString( (CFStringRef)dict_element, devicep->mManufacturer, 256, kCFStringEncodingUTF8 );
|
||||
sanitizeString(devicep->mManufacturer);
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mManufacturer" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDLocationIDKey ) );
|
||||
if ( !dict_element )
|
||||
{
|
||||
dict_element = CFDictionaryGetValue( io_properties, CFSTR( "locationID" ) );
|
||||
}
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mLocalID );
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mLocalID" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDPrimaryUsagePageKey ) );
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mUsagePage );
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mUsagePage" << LL_ENDL;
|
||||
}
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDPrimaryUsageKey ) );
|
||||
if ( dict_element )
|
||||
{
|
||||
if ( !CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mUsage ) )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mUsage" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add axis, because ndof lib checks sutability by axises as well as other elements
|
||||
devicep->mAxis = 0;
|
||||
CFTypeRef hid_elements = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDElementKey ) );
|
||||
if ( hid_elements && CFGetTypeID( hid_elements ) == CFArrayGetTypeID( ) )
|
||||
{
|
||||
long count = CFArrayGetCount( (CFArrayRef) hid_elements );
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
CFTypeRef element = CFArrayGetValueAtIndex((CFArrayRef) hid_elements, i);
|
||||
if (element && CFGetTypeID( element ) == CFDictionaryGetTypeID( ))
|
||||
{
|
||||
long type = 0, usage_page = 0, usage = 0;
|
||||
|
||||
CFTypeRef ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementTypeKey ) );
|
||||
if ( ref_value )
|
||||
{
|
||||
CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &type );
|
||||
}
|
||||
|
||||
ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementUsagePageKey ) );
|
||||
if ( ref_value )
|
||||
{
|
||||
CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &usage_page );
|
||||
}
|
||||
|
||||
ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementUsageKey ) );
|
||||
if ( ref_value )
|
||||
{
|
||||
CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &usage );
|
||||
}
|
||||
if ( type != 0
|
||||
&& type != kIOHIDElementTypeCollection
|
||||
&& usage_page == kHIDPage_GenericDesktop)
|
||||
{
|
||||
switch( usage )
|
||||
{
|
||||
case kHIDUsage_GD_X:
|
||||
case kHIDUsage_GD_Y:
|
||||
case kHIDUsage_GD_Z:
|
||||
case kHIDUsage_GD_Rx:
|
||||
case kHIDUsage_GD_Ry:
|
||||
case kHIDUsage_GD_Rz:
|
||||
devicep->mAxis++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(io_properties);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate fields" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HidDevice populate_device( io_object_t io_obj )
|
||||
{
|
||||
void* interfacep = nullptr;
|
||||
HidDevice device;
|
||||
memset( &device, 0, sizeof( HidDevice ) );
|
||||
CFMutableDictionaryRef device_dic = 0;
|
||||
kern_return_t result = IORegistryEntryCreateCFProperties( io_obj, &device_dic, kCFAllocatorDefault, kNilOptions );
|
||||
|
||||
if ( KERN_SUCCESS == result
|
||||
&& device_dic )
|
||||
{
|
||||
IOReturn io_result = kIOReturnSuccess;
|
||||
HRESULT query_result = S_OK;
|
||||
SInt32 the_score = 0;
|
||||
IOCFPlugInInterface **the_interface = NULL;
|
||||
|
||||
|
||||
io_result = IOCreatePlugInInterfaceForService( io_obj, kIOHIDDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID, &the_interface, &the_score );
|
||||
if ( io_result == kIOReturnSuccess )
|
||||
{
|
||||
query_result = ( *the_interface )->QueryInterface( the_interface, CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID ), ( LPVOID * ) & ( interfacep ) );
|
||||
if ( query_result != S_OK )
|
||||
{
|
||||
LL_WARNS("Joystick") << "QueryInterface failed" << LL_ENDL;
|
||||
}
|
||||
IODestroyPlugInInterface( the_interface );
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOCreatePlugInInterfaceForService failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
if ( interfacep )
|
||||
{
|
||||
result = ( *( IOHIDDeviceInterface** )interfacep )->open( interfacep, 0 );
|
||||
|
||||
if ( result != kIOReturnSuccess)
|
||||
{
|
||||
LL_WARNS("Joystick") << "open failed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
// extract needed fields
|
||||
populate_device_info( io_obj, device_dic, &device );
|
||||
|
||||
// Release interface
|
||||
if ( interfacep )
|
||||
{
|
||||
( *( IOHIDDeviceInterface** ) interfacep )->close( interfacep );
|
||||
|
||||
( *( IOHIDDeviceInterface** ) interfacep )->Release( interfacep );
|
||||
|
||||
interfacep = NULL;
|
||||
}
|
||||
|
||||
CFRelease( device_dic );
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "populate_device failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void get_devices(std::list<HidDevice> &list_of_devices,
|
||||
io_iterator_t inIODeviceIterator)
|
||||
{
|
||||
IOReturn result = kIOReturnSuccess; // assume success( optimist! )
|
||||
io_object_t io_obj = 0;
|
||||
|
||||
while ( 0 != (io_obj = IOIteratorNext( inIODeviceIterator ) ) )
|
||||
{
|
||||
HidDevice device = populate_device( io_obj );
|
||||
|
||||
if (debugLoggingEnabled("Joystick"))
|
||||
{
|
||||
list_of_devices.push_back(device);
|
||||
LL_DEBUGS("Joystick") << "Device axises: " << (S32)device.mAxis
|
||||
<< "Device HIDUsepage: " << (S32)device.mUsagePage
|
||||
<< "Device HIDUsage: " << (S32)device.mUsage
|
||||
<< LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should match ndof
|
||||
if (device.mAxis >= 3
|
||||
|| (device.mUsagePage == kHIDPage_GenericDesktop
|
||||
&& (device.mUsage == kHIDUsage_GD_MultiAxisController
|
||||
|| device.mUsage == kHIDUsage_GD_GamePad
|
||||
|| device.mUsage == kHIDUsage_GD_Joystick))
|
||||
|| (device.mUsagePage == kHIDPage_Game
|
||||
&& device.mUsage == kHIDUsage_Game_3DGameController)
|
||||
|| strstr(device.mManufacturer, "3Dconnexion"))
|
||||
{
|
||||
list_of_devices.push_back(device);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// release the device object, it is no longer needed
|
||||
result = IOObjectRelease( io_obj );
|
||||
if ( KERN_SUCCESS != result )
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOObjectRelease failed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLWindowMacOSX::getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata)
|
||||
{
|
||||
bool return_value = false;
|
||||
CFMutableDictionaryRef device_dict_ref;
|
||||
IOReturn result = kIOReturnSuccess; // assume success( optimist! )
|
||||
|
||||
// Set up matching dictionary to search the I/O Registry for HID devices we are interested in. Dictionary reference is NULL if error.
|
||||
|
||||
// A dictionary to match devices to?
|
||||
device_dict_ref = IOServiceMatching( kIOHIDDeviceKey );
|
||||
|
||||
// BUG FIX! one reference is consumed by IOServiceGetMatchingServices
|
||||
CFRetain( device_dict_ref );
|
||||
io_iterator_t io_iter = 0;
|
||||
|
||||
// create an IO object iterator
|
||||
result = IOServiceGetMatchingServices( kIOMasterPortDefault, device_dict_ref, &io_iter );
|
||||
if ( kIOReturnSuccess != result )
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOServiceGetMatchingServices failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
if ( io_iter )
|
||||
{
|
||||
// add all existing devices
|
||||
std::list<HidDevice> device_list;
|
||||
|
||||
get_devices(device_list, io_iter);
|
||||
|
||||
std::list<HidDevice>::iterator iter;
|
||||
|
||||
for (iter = device_list.begin(); iter != device_list.end(); ++iter)
|
||||
{
|
||||
std::string label(iter->mProduct);
|
||||
LLSD data;
|
||||
data["manufacturer"] = std::string(iter->mManufacturer);
|
||||
data["product"] = label;
|
||||
|
||||
if (osx_callback(label, data, userdata))
|
||||
{
|
||||
break; //found device
|
||||
}
|
||||
}
|
||||
return_value = true;
|
||||
}
|
||||
|
||||
CFRelease( device_dict_ref );
|
||||
return return_value;
|
||||
}
|
||||
|
||||
LLSD LLWindowMacOSX::getNativeKeyData()
|
||||
{
|
||||
LLSD result = LLSD::emptyMap();
|
||||
|
|
|
|||
|
|
@ -115,6 +115,11 @@ public:
|
|||
void interruptLanguageTextInput() override;
|
||||
void spawnWebBrowser(const std::string& escaped_url, bool async) override;
|
||||
F32 getSystemUISize() override;
|
||||
|
||||
bool getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata) override;
|
||||
|
||||
static std::vector<std::string> getDisplaysResolutionList();
|
||||
|
||||
|
|
|
|||
|
|
@ -4490,7 +4490,10 @@ void* LLWindowWin32::getDirectInput8()
|
|||
return &gDirectInput8;
|
||||
}
|
||||
|
||||
bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata)
|
||||
bool LLWindowWin32::getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void * di8_devices_callback,
|
||||
void* userdata)
|
||||
{
|
||||
if (gDirectInput8 != NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -131,7 +131,10 @@ public:
|
|||
static void setDPIAwareness();
|
||||
|
||||
/*virtual*/ void* getDirectInput8();
|
||||
/*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata);
|
||||
/*virtual*/ bool getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata);
|
||||
|
||||
U32 getRawWParam() { return mRawWParam; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1497,8 +1497,6 @@ DECL_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
|
|||
LLSD test_llsd = LLSD()["testing1"] = LLSD()["testing2"];
|
||||
DECL_LLCC(LLSD, test_llsd);
|
||||
|
||||
static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment");
|
||||
|
||||
void test_cached_control()
|
||||
{
|
||||
#define TEST_LLCC(T, V) if((T)mySetting_##T != V) LL_ERRS() << "Fail "#T << LL_ENDL
|
||||
|
|
@ -1515,8 +1513,6 @@ void test_cached_control()
|
|||
TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
|
||||
TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
|
||||
//There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd);
|
||||
|
||||
if((std::string)test_BrowserHomePage != "http://www.secondlife.com") LL_ERRS() << "Fail BrowserHomePage" << LL_ENDL;
|
||||
}
|
||||
#endif // TEST_CACHED_CONTROL
|
||||
|
||||
|
|
|
|||
|
|
@ -837,7 +837,7 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,
|
|||
|
||||
if (!LLXMLNode::parseFile(filename, root, NULL))
|
||||
{
|
||||
LL_WARNS() << "Problem reading UI description file: " << filename << LL_ENDL;
|
||||
LL_WARNS() << "Problem reading UI description file: " << filename << " " << errno << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
<llsd>
|
||||
<map>
|
||||
<key>AppearanceCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AvatarSitRotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -90,17 +79,6 @@
|
|||
<key>Value</key>
|
||||
<real>0.90322577953338623</real>
|
||||
</map>
|
||||
<key>EditCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering build mode, camera moves up above avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FocusOffsetRearView</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
<llsd>
|
||||
<map>
|
||||
<key>AppearanceCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AvatarSitRotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -90,17 +79,6 @@
|
|||
<key>Value</key>
|
||||
<real>0.90322577953338623</real>
|
||||
</map>
|
||||
<key>EditCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering build mode, camera moves up above avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FocusOffsetRearView</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
<llsd>
|
||||
<map>
|
||||
<key>AppearanceCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AvatarSitRotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -90,17 +79,6 @@
|
|||
<key>Value</key>
|
||||
<real>0.90322577953338623</real>
|
||||
</map>
|
||||
<key>EditCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering build mode, camera moves up above avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FocusOffsetRearView</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -397,8 +397,18 @@ CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \
|
|||
|
||||
# Other shortcuts
|
||||
SetOutPath "$INSTDIR"
|
||||
CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \
|
||||
|
||||
Push $0
|
||||
${GetParameters} $COMMANDLINE
|
||||
${GetOptionsS} $COMMANDLINE "/marker" $0
|
||||
# Returns error if option does not exist
|
||||
IfErrors 0 DESKTOP_SHORTCUT_DONE
|
||||
# "/marker" is set by updater, do not recreate desktop shortcut
|
||||
CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \
|
||||
"$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
|
||||
|
||||
DESKTOP_SHORTCUT_DONE:
|
||||
Pop $0
|
||||
CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \
|
||||
"$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
|
||||
CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
|
||||
|
|
|
|||
|
|
@ -1925,7 +1925,8 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
|
|||
}
|
||||
else
|
||||
{
|
||||
target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f;
|
||||
LLCachedControl<F32> dynamic_camera_strength(gSavedSettings, "DynamicCameraStrength");
|
||||
target_lag = vel * dynamic_camera_strength / 30.f;
|
||||
}
|
||||
|
||||
mCameraLag = lerp(mCameraLag, target_lag, lag_interp);
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ public:
|
|||
|
||||
void sendAgentPicksRequest()
|
||||
{
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(gAgent.getID());
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgent.getID());
|
||||
}
|
||||
|
||||
typedef boost::function<void(LLAvatarPicks*)> server_respond_callback_t;
|
||||
typedef boost::function<void(LLAvatarData*)> server_respond_callback_t;
|
||||
|
||||
void setServerRespondCallback(const server_respond_callback_t& cb)
|
||||
{
|
||||
|
|
@ -61,10 +61,10 @@ public:
|
|||
|
||||
virtual void processProperties(void* data, EAvatarProcessorType type)
|
||||
{
|
||||
if(APT_PICKS == type)
|
||||
if(APT_PROPERTIES == type)
|
||||
{
|
||||
LLAvatarPicks* picks = static_cast<LLAvatarPicks*>(data);
|
||||
if(picks && gAgent.getID() == picks->target_id)
|
||||
LLAvatarData* picks = static_cast<LLAvatarData*>(data);
|
||||
if(picks && gAgent.getID() == picks->avatar_id)
|
||||
{
|
||||
if(mServerRespondCallback)
|
||||
{
|
||||
|
|
@ -115,7 +115,7 @@ bool LLAgentPicksInfo::isPickLimitReached()
|
|||
return getNumberOfPicks() >= getMaxNumberOfPicks();
|
||||
}
|
||||
|
||||
void LLAgentPicksInfo::onServerRespond(LLAvatarPicks* picks)
|
||||
void LLAgentPicksInfo::onServerRespond(LLAvatarData* picks)
|
||||
{
|
||||
if(!picks)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "llsingleton.h"
|
||||
|
||||
struct LLAvatarPicks;
|
||||
struct LLAvatarData;
|
||||
|
||||
/**
|
||||
* Class that provides information about Agent Picks
|
||||
|
|
@ -74,7 +74,7 @@ public:
|
|||
|
||||
void decrementNumberOfPicks() { --mNumberOfPicks; }
|
||||
|
||||
void onServerRespond(LLAvatarPicks* picks);
|
||||
void onServerRespond(LLAvatarData* picks);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -1399,7 +1399,7 @@ const std::string LLAppearanceMgr::sExpectedTextureName = "OutfitPreview";
|
|||
|
||||
const LLUUID LLAppearanceMgr::getCOF() const
|
||||
{
|
||||
return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
return mCOFID;
|
||||
}
|
||||
|
||||
S32 LLAppearanceMgr::getCOFVersion() const
|
||||
|
|
@ -1415,6 +1415,11 @@ S32 LLAppearanceMgr::getCOFVersion() const
|
|||
}
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::initCOFID()
|
||||
{
|
||||
mCOFID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
}
|
||||
|
||||
const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink()
|
||||
{
|
||||
const LLUUID& current_outfit_cat = getCOF();
|
||||
|
|
@ -3749,6 +3754,14 @@ LLSD LLAppearanceMgr::dumpCOF() const
|
|||
return result;
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::cleanup()
|
||||
{
|
||||
mIsInUpdateAppearanceFromCOF = false;
|
||||
mOutstandingAppearanceBakeRequest = false;
|
||||
mRerequestAppearanceBake = false;
|
||||
mCOFID.setNull();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLAppearanceMgr::onIdle(void *)
|
||||
{
|
||||
|
|
@ -4117,7 +4130,7 @@ void LLAppearanceMgr::wearBaseOutfit()
|
|||
updateCOF(base_outfit_id);
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
|
||||
void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nullary_func_t post_update_func)
|
||||
{
|
||||
LL_DEBUGS("UIUsage") << "removeItemsFromAvatar" << LL_ENDL;
|
||||
LLUIUsage::instance().logCommand("Avatar.RemoveItem");
|
||||
|
|
@ -4127,7 +4140,7 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
|
|||
LL_WARNS() << "called with empty list, nothing to do" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
|
||||
LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy(true, true, post_update_func);
|
||||
for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it)
|
||||
{
|
||||
const LLUUID& id_to_remove = *it;
|
||||
|
|
@ -4146,11 +4159,11 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
|
|||
}
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)
|
||||
void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove, nullary_func_t post_update_func)
|
||||
{
|
||||
uuid_vec_t ids_to_remove;
|
||||
ids_to_remove.push_back(id_to_remove);
|
||||
removeItemsFromAvatar(ids_to_remove);
|
||||
removeItemsFromAvatar(ids_to_remove, post_update_func);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4387,20 +4400,45 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
|
||||
bool LLAppearanceMgr::getIsInCOF(const LLInventoryObject* obj) const
|
||||
{
|
||||
if (!getIsInCOF(obj_id)) return FALSE;
|
||||
const LLUUID& cof = getCOF();
|
||||
if (obj->getUUID() == cof)
|
||||
return true;
|
||||
if (obj && obj->getParentUUID() == cof)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
|
||||
{
|
||||
if (!getIsInCOF(obj_id)) return false;
|
||||
|
||||
// If a non-link somehow ended up in COF, allow deletion.
|
||||
const LLInventoryObject *obj = gInventory.getObject(obj_id);
|
||||
if (obj && !obj->getIsLinkType())
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// For now, don't allow direct deletion from the COF. Instead, force users
|
||||
// to choose "Detach" or "Take Off".
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLAppearanceMgr::getIsProtectedCOFItem(const LLInventoryObject* obj) const
|
||||
{
|
||||
if (!getIsInCOF(obj)) return false;
|
||||
|
||||
// If a non-link somehow ended up in COF, allow deletion.
|
||||
if (obj && !obj->getIsLinkType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// For now, don't allow direct deletion from the COF. Instead, force users
|
||||
// to choose "Detach" or "Take Off".
|
||||
return true;
|
||||
}
|
||||
|
||||
class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver
|
||||
|
|
|
|||
|
|
@ -111,9 +111,11 @@ public:
|
|||
// Find the Current Outfit folder.
|
||||
const LLUUID getCOF() const;
|
||||
S32 getCOFVersion() const;
|
||||
void initCOFID();
|
||||
|
||||
// Debugging - get truncated LLSD summary of COF contents.
|
||||
LLSD dumpCOF() const;
|
||||
void cleanup();
|
||||
|
||||
// Finds the folder link to the currently worn outfit
|
||||
const LLViewerInventoryItem *getBaseOutfitLink();
|
||||
|
|
@ -195,8 +197,8 @@ public:
|
|||
bool updateBaseOutfit();
|
||||
|
||||
//Remove clothing or detach an object from the agent (a bodypart cannot be removed)
|
||||
void removeItemsFromAvatar(const uuid_vec_t& item_ids);
|
||||
void removeItemFromAvatar(const LLUUID& item_id);
|
||||
void removeItemsFromAvatar(const uuid_vec_t& item_ids, nullary_func_t post_update_func = no_op);
|
||||
void removeItemFromAvatar(const LLUUID& item_id, nullary_func_t post_update_func = no_op);
|
||||
|
||||
|
||||
void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);
|
||||
|
|
@ -276,6 +278,7 @@ private:
|
|||
attachments_changed_signal_t mAttachmentsChangeSignal;
|
||||
|
||||
LLUUID mCOFImageID;
|
||||
LLUUID mCOFID;
|
||||
|
||||
std::unique_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
|
||||
|
||||
|
|
@ -290,8 +293,10 @@ private:
|
|||
public:
|
||||
// Is this in the COF?
|
||||
BOOL getIsInCOF(const LLUUID& obj_id) const;
|
||||
// Is this in the COF and can the user delete it from the COF?
|
||||
BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const;
|
||||
bool getIsInCOF(const LLInventoryObject* obj) const;
|
||||
// Is this in the COF and can the user delete it from the COF?
|
||||
bool getIsProtectedCOFItem(const LLUUID& obj_id) const;
|
||||
bool getIsProtectedCOFItem(const LLInventoryObject* obj) const;
|
||||
|
||||
// Outfits will prioritize textures with such name to use for preview in gallery
|
||||
static const std::string sExpectedTextureName;
|
||||
|
|
|
|||
|
|
@ -526,13 +526,6 @@ bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
|
|||
// or for things that are performance critical. JC
|
||||
static void settings_to_globals()
|
||||
{
|
||||
LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad");
|
||||
BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall");
|
||||
BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight");
|
||||
|
||||
MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
|
||||
MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
|
||||
|
||||
LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
|
||||
|
||||
#if LL_DARWIN
|
||||
|
|
@ -4290,7 +4283,8 @@ bool LLAppViewer::initCache()
|
|||
|
||||
LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
|
||||
|
||||
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion());
|
||||
const U32 CACHE_NUMBER_OF_REGIONS_FOR_OBJECTS = 128;
|
||||
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, CACHE_NUMBER_OF_REGIONS_FOR_OBJECTS, getObjectCacheVersion());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
|
|||
// messages. People API already hits the user table.
|
||||
LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI);
|
||||
app->addObserver(mAvatarId, this);
|
||||
app->sendAvatarPropertiesRequest(mAvatarId);
|
||||
app->sendAvatarLegacyPropertiesRequest(mAvatarId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -294,9 +294,9 @@ bool LLAvatarIconCtrl::updateFromCache()
|
|||
//virtual
|
||||
void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
|
||||
{
|
||||
if (APT_PROPERTIES == type)
|
||||
if (APT_PROPERTIES_LEGACY == type)
|
||||
{
|
||||
LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
|
||||
LLAvatarLegacyData* avatar_data = static_cast<LLAvatarLegacyData*>(data);
|
||||
if (avatar_data)
|
||||
{
|
||||
if (avatar_data->avatar_id != mAvatarId)
|
||||
|
|
|
|||
|
|
@ -52,24 +52,23 @@ LLAvatarPropertiesProcessor::~LLAvatarPropertiesProcessor()
|
|||
|
||||
void LLAvatarPropertiesProcessor::addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer)
|
||||
{
|
||||
if (!observer)
|
||||
return;
|
||||
|
||||
// Check if that observer is already in mObservers for that avatar_id
|
||||
observer_multimap_t::iterator it;
|
||||
using pair = std::pair<LLUUID, LLAvatarPropertiesObserver*>;
|
||||
observer_multimap_t::iterator begin = mObservers.begin();
|
||||
observer_multimap_t::iterator end = mObservers.end();
|
||||
observer_multimap_t::iterator it = std::find_if(begin, end, [&](const pair& p)
|
||||
{
|
||||
return p.first == avatar_id && p.second == observer;
|
||||
});
|
||||
|
||||
// IAN BUG this should update the observer's UUID if this is a dupe - sent to PE
|
||||
it = mObservers.find(avatar_id);
|
||||
while (it != mObservers.end())
|
||||
if (it == end)
|
||||
{
|
||||
if (it->second == observer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
mObservers.emplace(avatar_id, observer);
|
||||
}
|
||||
|
||||
mObservers.insert(std::pair<LLUUID, LLAvatarPropertiesObserver*>(avatar_id, observer));
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer)
|
||||
|
|
@ -79,19 +78,18 @@ void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvat
|
|||
return;
|
||||
}
|
||||
|
||||
observer_multimap_t::iterator it;
|
||||
it = mObservers.find(avatar_id);
|
||||
while (it != mObservers.end())
|
||||
// Check if that observer is in mObservers for that avatar_id
|
||||
using pair = std::pair<LLUUID, LLAvatarPropertiesObserver*>;
|
||||
observer_multimap_t::iterator begin = mObservers.begin();
|
||||
observer_multimap_t::iterator end = mObservers.end();
|
||||
observer_multimap_t::iterator it = std::find_if(begin, end, [&](const pair& p)
|
||||
{
|
||||
return p.first == avatar_id && p.second == observer;
|
||||
});
|
||||
|
||||
if (it != end)
|
||||
{
|
||||
if (it->second == observer)
|
||||
{
|
||||
mObservers.erase(it);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
mObservers.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,32 +114,30 @@ void LLAvatarPropertiesProcessor::sendRequest(const LLUUID& avatar_id, EAvatarPr
|
|||
return;
|
||||
}
|
||||
|
||||
std::string cap;
|
||||
|
||||
switch (type)
|
||||
// Try to send HTTP request if cap_url is available
|
||||
if (type == APT_PROPERTIES)
|
||||
{
|
||||
case APT_PROPERTIES:
|
||||
// indicate we're going to make a request
|
||||
sendAvatarPropertiesRequestMessage(avatar_id);
|
||||
// can use getRegionCapability("AgentProfile"), but it is heavy
|
||||
// initAgentProfileCapRequest(avatar_id, cap);
|
||||
break;
|
||||
case APT_PICKS:
|
||||
case APT_GROUPS:
|
||||
case APT_NOTES:
|
||||
if (cap.empty())
|
||||
std::string cap_url = gAgent.getRegionCapability("AgentProfile");
|
||||
if (!cap_url.empty())
|
||||
{
|
||||
// indicate we're going to make a request
|
||||
sendGenericRequest(avatar_id, type, method);
|
||||
initAgentProfileCapRequest(avatar_id, cap_url, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
initAgentProfileCapRequest(avatar_id, cap);
|
||||
// Don't sent UDP request for APT_PROPERTIES
|
||||
LL_WARNS() << "No cap_url for APT_PROPERTIES, request for " << avatar_id << " is not sent" << LL_ENDL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Send UDP request
|
||||
if (type == APT_PROPERTIES_LEGACY)
|
||||
{
|
||||
sendAvatarPropertiesRequestMessage(avatar_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendGenericRequest(avatar_id, type, method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -150,33 +146,29 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EA
|
|||
// indicate we're going to make a request
|
||||
addPendingRequest(avatar_id, type);
|
||||
|
||||
std::vector<std::string> strings;
|
||||
strings.push_back(avatar_id.asString());
|
||||
std::vector<std::string> strings{ avatar_id.asString() };
|
||||
send_generic_message(method, strings);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id)
|
||||
{
|
||||
addPendingRequest(avatar_id, APT_PROPERTIES);
|
||||
addPendingRequest(avatar_id, APT_PROPERTIES_LEGACY);
|
||||
|
||||
LLMessageSystem *msg = gMessageSystem;
|
||||
|
||||
msg->newMessageFast(_PREHASH_AvatarPropertiesRequest);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
|
||||
msg->addUUIDFast(_PREHASH_AvatarID, avatar_id);
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url)
|
||||
void LLAvatarPropertiesProcessor::initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url, EAvatarProcessorType type)
|
||||
{
|
||||
addPendingRequest(avatar_id, APT_PROPERTIES);
|
||||
addPendingRequest(avatar_id, APT_PICKS);
|
||||
addPendingRequest(avatar_id, APT_GROUPS);
|
||||
addPendingRequest(avatar_id, APT_NOTES);
|
||||
addPendingRequest(avatar_id, type);
|
||||
LLCoros::instance().launch("requestAgentUserInfoCoro",
|
||||
boost::bind(requestAvatarPropertiesCoro, cap_url, avatar_id));
|
||||
[cap_url, avatar_id, type]() { requestAvatarPropertiesCoro(cap_url, avatar_id, type); });
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id)
|
||||
|
|
@ -184,19 +176,9 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avat
|
|||
sendRequest(avatar_id, APT_PROPERTIES, "AvatarPropertiesRequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPicksRequest(const LLUUID& avatar_id)
|
||||
void LLAvatarPropertiesProcessor::sendAvatarLegacyPropertiesRequest(const LLUUID& avatar_id)
|
||||
{
|
||||
sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarNotesRequest(const LLUUID& avatar_id)
|
||||
{
|
||||
sendGenericRequest(avatar_id, APT_NOTES, "avatarnotesrequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarGroupsRequest(const LLUUID& avatar_id)
|
||||
{
|
||||
sendGenericRequest(avatar_id, APT_GROUPS, "avatargroupsrequest");
|
||||
sendRequest(avatar_id, APT_PROPERTIES_LEGACY, "AvatarPropertiesRequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarTexturesRequest(const LLUUID& avatar_id)
|
||||
|
|
@ -211,42 +193,6 @@ void LLAvatarPropertiesProcessor::sendAvatarClassifiedsRequest(const LLUUID& ava
|
|||
sendGenericRequest(avatar_id, APT_CLASSIFIEDS, "avatarclassifiedsrequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props)
|
||||
{
|
||||
if (!gAgent.isInitialized() || (gAgent.getID() == LLUUID::null))
|
||||
{
|
||||
LL_WARNS() << "Sending avatarinfo update DENIED - invalid agent" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LL_WARNS() << "Sending avatarinfo update. This trims profile descriptions!!!" << LL_ENDL;
|
||||
|
||||
// This value is required by sendAvatarPropertiesUpdate method.
|
||||
//A profile should never be mature. (From the original code)
|
||||
BOOL mature = FALSE;
|
||||
|
||||
LLMessageSystem *msg = gMessageSystem;
|
||||
|
||||
msg->newMessageFast (_PREHASH_AvatarPropertiesUpdate);
|
||||
msg->nextBlockFast (_PREHASH_AgentData);
|
||||
msg->addUUIDFast (_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast (_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast (_PREHASH_PropertiesData);
|
||||
|
||||
msg->addUUIDFast (_PREHASH_ImageID, avatar_props->image_id);
|
||||
msg->addUUIDFast (_PREHASH_FLImageID, avatar_props->fl_image_id);
|
||||
msg->addStringFast (_PREHASH_AboutText, avatar_props->about_text);
|
||||
msg->addStringFast (_PREHASH_FLAboutText, avatar_props->fl_about_text);
|
||||
|
||||
msg->addBOOL(_PREHASH_AllowPublish, avatar_props->allow_publish);
|
||||
msg->addBOOL(_PREHASH_MaturePublish, mature);
|
||||
msg->addString(_PREHASH_ProfileURL, avatar_props->profile_url);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//static
|
||||
std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_data)
|
||||
{
|
||||
|
|
@ -271,19 +217,21 @@ std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_
|
|||
std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_data)
|
||||
{
|
||||
// Special accounts like M Linden don't have payment info revealed.
|
||||
if (!avatar_data->caption_text.empty()) return "";
|
||||
if (!avatar_data->caption_text.empty())
|
||||
return "";
|
||||
|
||||
// Linden employees don't have payment info revealed
|
||||
const S32 LINDEN_EMPLOYEE_INDEX = 3;
|
||||
if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return "";
|
||||
constexpr S32 LINDEN_EMPLOYEE_INDEX = 3;
|
||||
if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX)
|
||||
return "";
|
||||
|
||||
BOOL transacted = (avatar_data->flags & AVATAR_TRANSACTED);
|
||||
BOOL identified = (avatar_data->flags & AVATAR_IDENTIFIED);
|
||||
bool transacted = (avatar_data->flags & AVATAR_TRANSACTED);
|
||||
bool identified = (avatar_data->flags & AVATAR_IDENTIFIED);
|
||||
// Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations
|
||||
//BOOL age_verified = (avatar_data->flags & AVATAR_AGEVERIFIED);
|
||||
|
||||
const char* payment_text;
|
||||
if(transacted)
|
||||
if (transacted)
|
||||
{
|
||||
payment_text = "PaymentInfoUsed";
|
||||
}
|
||||
|
|
@ -302,18 +250,22 @@ std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_
|
|||
bool LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(const LLAvatarData* avatar_data)
|
||||
{
|
||||
// Special accounts like M Linden don't have payment info revealed.
|
||||
if (!avatar_data->caption_text.empty()) return true;
|
||||
if (!avatar_data->caption_text.empty())
|
||||
return true;
|
||||
|
||||
// Linden employees don't have payment info revealed
|
||||
const S32 LINDEN_EMPLOYEE_INDEX = 3;
|
||||
if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return true;
|
||||
constexpr S32 LINDEN_EMPLOYEE_INDEX = 3;
|
||||
if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX)
|
||||
return true;
|
||||
|
||||
return ((avatar_data->flags & AVATAR_TRANSACTED) || (avatar_data->flags & AVATAR_IDENTIFIED));
|
||||
}
|
||||
|
||||
// static
|
||||
void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id)
|
||||
void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_url, LLUUID avatar_id, EAvatarProcessorType type)
|
||||
{
|
||||
LLAvatarPropertiesProcessor& inst = instance();
|
||||
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestAvatarPropertiesCoro", httpPolicy));
|
||||
|
|
@ -323,104 +275,104 @@ void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_ur
|
|||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
httpOpts->setFollowRedirects(true);
|
||||
|
||||
std::string finalUrl = cap_url + "/" + agent_id.asString();
|
||||
std::string finalUrl = cap_url + "/" + avatar_id.asString();
|
||||
|
||||
LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl, httpOpts, httpHeaders);
|
||||
|
||||
// Response is being processed, no longer pending is required
|
||||
inst.removePendingRequest(avatar_id, type);
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (!status
|
||||
|| !result.has("id")
|
||||
|| agent_id != result["id"].asUUID())
|
||||
|| avatar_id != result["id"].asUUID())
|
||||
{
|
||||
LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << agent_id << LL_ENDL;
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
self->removePendingRequest(agent_id, APT_PROPERTIES);
|
||||
self->removePendingRequest(agent_id, APT_PICKS);
|
||||
self->removePendingRequest(agent_id, APT_GROUPS);
|
||||
self->removePendingRequest(agent_id, APT_NOTES);
|
||||
LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << avatar_id
|
||||
<< (!status ? " (no HTTP status)" : !result.has("id") ? " (no result.id)" :
|
||||
std::string(" (result.id=") + result["id"].asUUID().asString() + ")")
|
||||
<< LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Avatar Data
|
||||
|
||||
LLAvatarData avatar_data;
|
||||
|
||||
std::string birth_date;
|
||||
|
||||
avatar_data.agent_id = agent_id;
|
||||
avatar_data.avatar_id = agent_id;
|
||||
avatar_data.agent_id = gAgentID;
|
||||
avatar_data.avatar_id = avatar_id;
|
||||
avatar_data.image_id = result["sl_image_id"].asUUID();
|
||||
avatar_data.fl_image_id = result["fl_image_id"].asUUID();
|
||||
avatar_data.partner_id = result["partner_id"].asUUID();
|
||||
avatar_data.about_text = result["sl_about_text"].asString();
|
||||
avatar_data.fl_about_text = result["fl_about_text"].asString();
|
||||
avatar_data.born_on = result["member_since"].asDate();
|
||||
avatar_data.profile_url = getProfileURL(agent_id.asString());
|
||||
// TODO: SL-20163 Remove the "has" check when SRV-684 is done
|
||||
// and the field "hide_age" is included to the http response
|
||||
inst.mIsHideAgeSupportedByServer = result.has("hide_age");
|
||||
avatar_data.hide_age = inst.isHideAgeSupportedByServer() && result["hide_age"].asBoolean();
|
||||
avatar_data.profile_url = getProfileURL(avatar_id.asString());
|
||||
avatar_data.customer_type = result["customer_type"].asString();
|
||||
avatar_data.notes = result["notes"].asString();
|
||||
|
||||
avatar_data.flags = 0;
|
||||
avatar_data.caption_index = 0;
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(agent_id, APT_PROPERTIES);
|
||||
self->notifyObservers(agent_id, &avatar_data, APT_PROPERTIES);
|
||||
|
||||
// Picks
|
||||
|
||||
LLSD picks_array = result["picks"];
|
||||
LLAvatarPicks avatar_picks;
|
||||
avatar_picks.agent_id = agent_id; // Not in use?
|
||||
avatar_picks.target_id = agent_id;
|
||||
|
||||
for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it)
|
||||
if (result["online"].asBoolean())
|
||||
{
|
||||
const LLSD& pick_data = *it;
|
||||
avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString());
|
||||
avatar_data.flags |= AVATAR_ONLINE;
|
||||
}
|
||||
if (result["allow_publish"].asBoolean())
|
||||
{
|
||||
avatar_data.flags |= AVATAR_ALLOW_PUBLISH;
|
||||
}
|
||||
if (result["identified"].asBoolean())
|
||||
{
|
||||
avatar_data.flags |= AVATAR_IDENTIFIED;
|
||||
}
|
||||
if (result["transacted"].asBoolean())
|
||||
{
|
||||
avatar_data.flags |= AVATAR_TRANSACTED;
|
||||
}
|
||||
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(agent_id, APT_PICKS);
|
||||
self->notifyObservers(agent_id, &avatar_picks, APT_PICKS);
|
||||
avatar_data.caption_index = 0;
|
||||
if (result.has("charter_member")) // won't be present if "caption" is set
|
||||
{
|
||||
avatar_data.caption_index = result["charter_member"].asInteger();
|
||||
}
|
||||
else if (result.has("caption"))
|
||||
{
|
||||
avatar_data.caption_text = result["caption"].asString();
|
||||
}
|
||||
|
||||
// Groups
|
||||
|
||||
LLSD groups_array = result["groups"];
|
||||
LLAvatarGroups avatar_groups;
|
||||
avatar_groups.agent_id = agent_id; // Not in use?
|
||||
avatar_groups.avatar_id = agent_id; // target_id
|
||||
|
||||
for (LLSD::array_const_iterator it = groups_array.beginArray(); it != groups_array.endArray(); ++it)
|
||||
{
|
||||
const LLSD& group_info = *it;
|
||||
LLAvatarGroups::LLGroupData group_data;
|
||||
LLAvatarData::LLGroupData group_data;
|
||||
group_data.group_powers = 0; // Not in use?
|
||||
group_data.group_title = group_info["name"].asString(); // Missing data, not in use?
|
||||
group_data.group_id = group_info["id"].asUUID();
|
||||
group_data.group_name = group_info["name"].asString();
|
||||
group_data.group_insignia_id = group_info["image_id"].asUUID();
|
||||
|
||||
avatar_groups.group_list.push_back(group_data);
|
||||
avatar_data.group_list.push_back(group_data);
|
||||
}
|
||||
|
||||
self->removePendingRequest(agent_id, APT_GROUPS);
|
||||
self->notifyObservers(agent_id, &avatar_groups, APT_GROUPS);
|
||||
// Picks
|
||||
LLSD picks_array = result["picks"];
|
||||
for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it)
|
||||
{
|
||||
const LLSD& pick_data = *it;
|
||||
avatar_data.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString());
|
||||
}
|
||||
|
||||
// Notes
|
||||
LLAvatarNotes avatar_notes;
|
||||
|
||||
avatar_notes.agent_id = agent_id;
|
||||
avatar_notes.target_id = agent_id;
|
||||
avatar_notes.notes = result["notes"].asString();
|
||||
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(agent_id, APT_NOTES);
|
||||
self->notifyObservers(agent_id, &avatar_notes, APT_NOTES);
|
||||
inst.notifyObservers(avatar_id, &avatar_data, type);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**)
|
||||
void LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLAvatarData avatar_data;
|
||||
LLAvatarLegacyData avatar_data;
|
||||
std::string birth_date;
|
||||
|
||||
msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, avatar_data.agent_id);
|
||||
|
|
@ -434,51 +386,23 @@ void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem*
|
|||
msg->getString( _PREHASH_PropertiesData, _PREHASH_ProfileURL, avatar_data.profile_url);
|
||||
msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_Flags, avatar_data.flags);
|
||||
|
||||
|
||||
LLDateUtil::dateFromPDTString(avatar_data.born_on, birth_date);
|
||||
avatar_data.caption_index = 0;
|
||||
|
||||
S32 charter_member_size = 0;
|
||||
charter_member_size = msg->getSize(_PREHASH_PropertiesData, _PREHASH_CharterMember);
|
||||
if(1 == charter_member_size)
|
||||
if (1 == charter_member_size)
|
||||
{
|
||||
msg->getBinaryData(_PREHASH_PropertiesData, _PREHASH_CharterMember, &avatar_data.caption_index, 1);
|
||||
}
|
||||
else if(1 < charter_member_size)
|
||||
else if (1 < charter_member_size)
|
||||
{
|
||||
msg->getString(_PREHASH_PropertiesData, _PREHASH_CharterMember, avatar_data.caption_text);
|
||||
}
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES);
|
||||
self->notifyObservers(avatar_data.avatar_id,&avatar_data,APT_PROPERTIES);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
/*
|
||||
AvatarInterestsReply is automatically sent by the server in response to the
|
||||
AvatarPropertiesRequest sent when the panel is opened (in addition to the AvatarPropertiesReply message).
|
||||
If the interests panel is no longer part of the design (?) we should just register the message
|
||||
to a handler function that does nothing.
|
||||
That will suppress the warnings and be compatible with old server versions.
|
||||
WARNING: LLTemplateMessageReader::decodeData: Message from 216.82.37.237:13000 with no handler function received: AvatarInterestsReply
|
||||
*/
|
||||
|
||||
LLInterestsData interests_data;
|
||||
|
||||
msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, interests_data.agent_id );
|
||||
msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AvatarID, interests_data.avatar_id );
|
||||
msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_WantToMask, interests_data.want_to_mask );
|
||||
msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_WantToText, interests_data.want_to_text );
|
||||
msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_SkillsMask, interests_data.skills_mask );
|
||||
msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_SkillsText, interests_data.skills_text );
|
||||
msg->getString( _PREHASH_PropertiesData, _PREHASH_LanguagesText, interests_data.languages_text );
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(interests_data.avatar_id, APT_INTERESTS_INFO);
|
||||
self->notifyObservers(interests_data.avatar_id, &interests_data, APT_INTERESTS_INFO);
|
||||
self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES_LEGACY);
|
||||
self->notifyObservers(avatar_data.avatar_id, &avatar_data, APT_PROPERTIES_LEGACY);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**)
|
||||
|
|
@ -497,7 +421,7 @@ void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem*
|
|||
msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, data.classified_id, n);
|
||||
msg->getString(_PREHASH_Data, _PREHASH_Name, data.name, n);
|
||||
|
||||
classifieds.classifieds_list.push_back(data);
|
||||
classifieds.classifieds_list.emplace_back(data);
|
||||
}
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
|
|
@ -534,44 +458,6 @@ void LLAvatarPropertiesProcessor::processClassifiedInfoReply(LLMessageSystem* ms
|
|||
self->notifyObservers(c_info.creator_id, &c_info, APT_CLASSIFIED_INFO);
|
||||
}
|
||||
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLAvatarNotes avatar_notes;
|
||||
|
||||
msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_notes.agent_id);
|
||||
msg->getUUID(_PREHASH_Data, _PREHASH_TargetID, avatar_notes.target_id);
|
||||
msg->getString(_PREHASH_Data, _PREHASH_Notes, avatar_notes.notes);
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(avatar_notes.target_id, APT_NOTES);
|
||||
self->notifyObservers(avatar_notes.target_id,&avatar_notes,APT_NOTES);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLAvatarPicks avatar_picks;
|
||||
msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_picks.agent_id);
|
||||
msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, avatar_picks.target_id);
|
||||
|
||||
S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data);
|
||||
for (int block = 0; block < block_count; ++block)
|
||||
{
|
||||
LLUUID pick_id;
|
||||
std::string pick_name;
|
||||
|
||||
msg->getUUID(_PREHASH_Data, _PREHASH_PickID, pick_id, block);
|
||||
msg->getString(_PREHASH_Data, _PREHASH_PickName, pick_name, block);
|
||||
|
||||
avatar_picks.picks_list.push_back(std::make_pair(pick_id,pick_name));
|
||||
}
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(avatar_picks.target_id, APT_PICKS);
|
||||
self->notifyObservers(avatar_picks.target_id,&avatar_picks,APT_PICKS);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLPickData pick_data;
|
||||
|
|
@ -602,46 +488,18 @@ void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, voi
|
|||
self->notifyObservers(pick_data.creator_id, &pick_data, APT_PICK_INFO);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLAvatarGroups avatar_groups;
|
||||
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, avatar_groups.agent_id );
|
||||
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_groups.avatar_id );
|
||||
|
||||
S32 group_count = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
|
||||
for(S32 i = 0; i < group_count; ++i)
|
||||
{
|
||||
LLAvatarGroups::LLGroupData group_data;
|
||||
|
||||
msg->getU64( _PREHASH_GroupData, _PREHASH_GroupPowers, group_data.group_powers, i );
|
||||
msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupTitle, group_data.group_title, i );
|
||||
msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupID, group_data.group_id, i);
|
||||
msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupName, group_data.group_name, i );
|
||||
msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupInsigniaID, group_data.group_insignia_id, i );
|
||||
|
||||
avatar_groups.group_list.push_back(group_data);
|
||||
}
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
self->removePendingRequest(avatar_groups.avatar_id, APT_GROUPS);
|
||||
self->notifyObservers(avatar_groups.avatar_id,&avatar_groups,APT_GROUPS);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type)
|
||||
void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id, void* data, EAvatarProcessorType type)
|
||||
{
|
||||
// Copy the map (because observers may delete themselves when updated?)
|
||||
LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers;
|
||||
|
||||
observer_multimap_t::iterator oi = observers.begin();
|
||||
observer_multimap_t::iterator end = observers.end();
|
||||
for (; oi != end; ++oi)
|
||||
for (const auto& [agent_id, observer] : observers)
|
||||
{
|
||||
// only notify observers for the same agent, or if the observer
|
||||
// didn't know the agent ID and passed a NULL id.
|
||||
const LLUUID &agent_id = oi->first;
|
||||
if (agent_id == id || agent_id.isNull())
|
||||
{
|
||||
oi->second->processProperties(data,type);
|
||||
observer->processProperties(data, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -655,8 +513,8 @@ void LLAvatarPropertiesProcessor::sendFriendRights(const LLUUID& avatar_id, S32
|
|||
// setup message header
|
||||
msg->newMessageFast(_PREHASH_GrantUserRights);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlockFast(_PREHASH_Rights);
|
||||
msg->addUUID(_PREHASH_AgentRelated, avatar_id);
|
||||
|
|
@ -666,34 +524,13 @@ void LLAvatarPropertiesProcessor::sendFriendRights(const LLUUID& avatar_id, S32
|
|||
}
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendNotes(const LLUUID& avatar_id, const std::string notes)
|
||||
{
|
||||
if(!avatar_id.isNull())
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
// setup message header
|
||||
msg->newMessageFast(_PREHASH_AvatarNotesUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
|
||||
msg->nextBlockFast(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_TargetID, avatar_id);
|
||||
msg->addString(_PREHASH_Notes, notes);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id )
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessage(_PREHASH_PickDelete);
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_PickID, pick_id);
|
||||
gAgent.sendReliableMessage();
|
||||
|
|
@ -709,8 +546,8 @@ void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_
|
|||
msg->newMessage(_PREHASH_ClassifiedDelete);
|
||||
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_ClassifiedID, classified_id);
|
||||
|
|
@ -718,39 +555,17 @@ void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_
|
|||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendInterestsInfoUpdate(const LLInterestsData* interests_data)
|
||||
{
|
||||
if(!interests_data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
msg->newMessage(_PREHASH_AvatarInterestsUpdate);
|
||||
msg->nextBlockFast( _PREHASH_AgentData);
|
||||
msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast( _PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast( _PREHASH_PropertiesData);
|
||||
msg->addU32Fast( _PREHASH_WantToMask, interests_data->want_to_mask);
|
||||
msg->addStringFast( _PREHASH_WantToText, interests_data->want_to_text);
|
||||
msg->addU32Fast( _PREHASH_SkillsMask, interests_data->skills_mask);
|
||||
msg->addStringFast( _PREHASH_SkillsText, interests_data->skills_text);
|
||||
msg->addString( _PREHASH_LanguagesText, interests_data->languages_text);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)
|
||||
{
|
||||
if (!new_pick) return;
|
||||
if (!new_pick)
|
||||
return;
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
msg->newMessage(_PREHASH_PickInfoUpdate);
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_PickID, new_pick->pick_id);
|
||||
|
|
@ -787,8 +602,8 @@ void LLAvatarPropertiesProcessor::sendClassifiedInfoUpdate(const LLAvatarClassif
|
|||
msg->newMessage(_PREHASH_ClassifiedInfoUpdate);
|
||||
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_ClassifiedID, c_data->classified_id);
|
||||
|
|
@ -809,9 +624,7 @@ void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id,
|
|||
{
|
||||
// Must ask for a pick based on the creator id because
|
||||
// the pick database is distributed to the inventory cluster. JC
|
||||
std::vector<std::string> request_params;
|
||||
request_params.push_back(creator_id.asString() );
|
||||
request_params.push_back(pick_id.asString() );
|
||||
std::vector<std::string> request_params{ creator_id.asString(), pick_id.asString() };
|
||||
send_generic_message("pickinforequest", request_params);
|
||||
}
|
||||
|
||||
|
|
@ -822,8 +635,8 @@ void LLAvatarPropertiesProcessor::sendClassifiedInfoRequest(const LLUUID& classi
|
|||
msg->newMessage(_PREHASH_ClassifiedInfoRequest);
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_ClassifiedID, classified_id);
|
||||
|
|
@ -840,7 +653,7 @@ bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAva
|
|||
if (it == mRequestTimestamps.end()) return false;
|
||||
|
||||
// We found a request, check if it has timed out
|
||||
U32 now = time(NULL);
|
||||
U32 now = time(nullptr);
|
||||
const U32 REQUEST_EXPIRE_SECS = 5;
|
||||
U32 expires = it->second + REQUEST_EXPIRE_SECS;
|
||||
|
||||
|
|
@ -854,7 +667,7 @@ bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAva
|
|||
void LLAvatarPropertiesProcessor::addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
|
||||
{
|
||||
timestamp_map_t::key_type key = std::make_pair(avatar_id, type);
|
||||
U32 now = time(NULL);
|
||||
U32 now = time(nullptr);
|
||||
// Add or update existing (expired) request
|
||||
mRequestTimestamps[ key ] = now;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,54 +50,71 @@ class LLMessageSystem;
|
|||
|
||||
enum EAvatarProcessorType
|
||||
{
|
||||
APT_PROPERTIES,
|
||||
APT_NOTES,
|
||||
APT_GROUPS,
|
||||
APT_PICKS,
|
||||
APT_PROPERTIES_LEGACY, // APT_PROPERTIES via udp request (Truncates data!!!)
|
||||
APT_PROPERTIES, // APT_PROPERTIES via http request
|
||||
APT_PICK_INFO,
|
||||
APT_TEXTURES,
|
||||
APT_INTERESTS_INFO,
|
||||
APT_CLASSIFIEDS,
|
||||
APT_CLASSIFIED_INFO
|
||||
};
|
||||
|
||||
struct LLInterestsData
|
||||
// legacy data is supposed to match AvatarPropertiesReply,
|
||||
// but it is obsolete, fields like about_text will truncate
|
||||
// data, if you need them, use AgenProfile cap.
|
||||
// Todo: remove it once once icon ids get moved elsewhere,
|
||||
// since AgentProfile is too large for bulk icon requests
|
||||
struct LLAvatarLegacyData
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID avatar_id; //target id
|
||||
U32 want_to_mask;
|
||||
std::string want_to_text;
|
||||
U32 skills_mask;
|
||||
std::string skills_text;
|
||||
std::string languages_text;
|
||||
LLUUID agent_id;
|
||||
LLUUID avatar_id; //target id
|
||||
LLUUID image_id;
|
||||
LLUUID fl_image_id;
|
||||
LLUUID partner_id;
|
||||
std::string about_text;
|
||||
std::string fl_about_text;
|
||||
LLDate born_on;
|
||||
std::string profile_url;
|
||||
U8 caption_index;
|
||||
std::string caption_text;
|
||||
std::string customer_type;
|
||||
U32 flags;
|
||||
};
|
||||
|
||||
struct LLAvatarData
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID avatar_id; //target id
|
||||
LLUUID image_id;
|
||||
LLUUID fl_image_id;
|
||||
LLUUID partner_id;
|
||||
std::string about_text;
|
||||
std::string fl_about_text;
|
||||
LLDate born_on;
|
||||
std::string profile_url;
|
||||
U8 caption_index;
|
||||
std::string caption_text;
|
||||
LLUUID agent_id;
|
||||
LLUUID avatar_id; //target id
|
||||
LLUUID image_id;
|
||||
LLUUID fl_image_id;
|
||||
LLUUID partner_id;
|
||||
std::string about_text;
|
||||
std::string fl_about_text;
|
||||
LLDate born_on;
|
||||
std::string profile_url;
|
||||
U8 caption_index;
|
||||
std::string caption_text;
|
||||
std::string customer_type;
|
||||
U32 flags;
|
||||
BOOL allow_publish;
|
||||
U32 flags;
|
||||
bool hide_age;
|
||||
std::string notes;
|
||||
|
||||
struct LLGroupData;
|
||||
typedef std::list<LLGroupData> group_list_t;
|
||||
group_list_t group_list;
|
||||
|
||||
typedef std::pair<LLUUID, std::string> pick_data_t;
|
||||
typedef std::list< pick_data_t> picks_list_t;
|
||||
picks_list_t picks_list;
|
||||
};
|
||||
|
||||
struct LLAvatarPicks
|
||||
struct LLAvatarData::LLGroupData
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID target_id; //target id
|
||||
|
||||
typedef std::pair<LLUUID,std::string> pick_data_t;
|
||||
typedef std::list< pick_data_t> picks_list_t;
|
||||
picks_list_t picks_list;
|
||||
U64 group_powers;
|
||||
BOOL accept_notices;
|
||||
std::string group_title;
|
||||
LLUUID group_id;
|
||||
std::string group_name;
|
||||
LLUUID group_insignia_id;
|
||||
};
|
||||
|
||||
struct LLPickData
|
||||
|
|
@ -121,36 +138,6 @@ struct LLPickData
|
|||
|
||||
//used only in write (update) requests
|
||||
LLUUID session_id;
|
||||
|
||||
};
|
||||
|
||||
struct LLAvatarNotes
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID target_id; //target id
|
||||
std::string notes;
|
||||
};
|
||||
|
||||
struct LLAvatarGroups
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID avatar_id; //target id
|
||||
BOOL list_in_profile;
|
||||
|
||||
struct LLGroupData;
|
||||
typedef std::list<LLGroupData> group_list_t;
|
||||
|
||||
group_list_t group_list;
|
||||
|
||||
struct LLGroupData
|
||||
{
|
||||
U64 group_powers;
|
||||
BOOL accept_notices;
|
||||
std::string group_title;
|
||||
LLUUID group_id;
|
||||
std::string group_name;
|
||||
LLUUID group_insignia_id;
|
||||
};
|
||||
};
|
||||
|
||||
struct LLAvatarClassifieds
|
||||
|
|
@ -211,9 +198,7 @@ public:
|
|||
// Request various types of avatar data. Duplicate requests will be
|
||||
// suppressed while waiting for a response from the network.
|
||||
void sendAvatarPropertiesRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarPicksRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarNotesRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarGroupsRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarLegacyPropertiesRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarTexturesRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarClassifiedsRequest(const LLUUID& avatar_id);
|
||||
|
||||
|
|
@ -222,21 +207,17 @@ public:
|
|||
|
||||
void sendClassifiedInfoRequest(const LLUUID& classified_id);
|
||||
|
||||
void sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props);
|
||||
|
||||
void sendPickInfoUpdate(const LLPickData* new_pick);
|
||||
|
||||
void sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data);
|
||||
|
||||
void sendFriendRights(const LLUUID& avatar_id, S32 rights);
|
||||
|
||||
void sendNotes(const LLUUID& avatar_id, const std::string notes);
|
||||
|
||||
void sendPickDelete(const LLUUID& pick_id);
|
||||
|
||||
void sendClassifiedDelete(const LLUUID& classified_id);
|
||||
|
||||
void sendInterestsInfoUpdate(const LLInterestsData* interests_data);
|
||||
bool isHideAgeSupportedByServer() { return mIsHideAgeSupportedByServer; }
|
||||
|
||||
// Returns translated, human readable string for account type, such
|
||||
// as "Resident" or "Linden Employee". Used for profiles, inspectors.
|
||||
|
|
@ -249,30 +230,23 @@ public:
|
|||
|
||||
static bool hasPaymentInfoOnFile(const LLAvatarData* avatar_data);
|
||||
|
||||
static void requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id);
|
||||
static void requestAvatarPropertiesCoro(std::string cap_url, LLUUID avatar_id, EAvatarProcessorType type);
|
||||
|
||||
static void processAvatarPropertiesReply(LLMessageSystem* msg, void**);
|
||||
|
||||
static void processAvatarInterestsReply(LLMessageSystem* msg, void**);
|
||||
// Processing of UDP variant of properties, truncates certain fields!
|
||||
static void processAvatarLegacyPropertiesReply(LLMessageSystem* msg, void**);
|
||||
|
||||
static void processAvatarClassifiedsReply(LLMessageSystem* msg, void**);
|
||||
|
||||
static void processClassifiedInfoReply(LLMessageSystem* msg, void**);
|
||||
|
||||
static void processAvatarGroupsReply(LLMessageSystem* msg, void**);
|
||||
|
||||
static void processAvatarNotesReply(LLMessageSystem* msg, void**);
|
||||
|
||||
static void processAvatarPicksReply(LLMessageSystem* msg, void**);
|
||||
|
||||
static void processPickInfoReply(LLMessageSystem* msg, void**);
|
||||
|
||||
protected:
|
||||
|
||||
void sendRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method);
|
||||
void sendRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method);
|
||||
void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method);
|
||||
void sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id);
|
||||
void initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url);
|
||||
void initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url, EAvatarProcessorType type);
|
||||
|
||||
void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type);
|
||||
|
||||
|
|
@ -302,6 +276,9 @@ protected:
|
|||
// Map avatar_id+request_type -> U32 timestamp in seconds
|
||||
typedef std::map< std::pair<LLUUID, EAvatarProcessorType>, U32> timestamp_map_t;
|
||||
timestamp_map_t mRequestTimestamps;
|
||||
|
||||
// Is returned by isHideAgeSupportedByServer()
|
||||
bool mIsHideAgeSupportedByServer { false };
|
||||
};
|
||||
|
||||
#endif // LL_LLAVATARPROPERTIESPROCESSOR_H
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ LLScreenChannel* LLChannelManager::createNotificationChannel()
|
|||
{
|
||||
// creating params for a channel
|
||||
LLScreenChannelBase::Params p;
|
||||
p.id = LLUUID(gSavedSettings.getString("NotificationChannelUUID"));
|
||||
p.id = NOTIFICATION_CHANNEL_UUID;
|
||||
p.channel_align = CA_RIGHT;
|
||||
p.toast_align = NA_TOP;
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ void LLChannelManager::onLoginCompleted()
|
|||
if (!channel) continue;
|
||||
|
||||
// don't calc notifications for Nearby Chat
|
||||
if(channel->getChannelID() == LLUUID(gSavedSettings.getString("NearByChatChannelUUID")))
|
||||
if(channel->getChannelID() == NEARBY_CHAT_CHANNEL_UUID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ void LLChannelManager::onLoginCompleted()
|
|||
{
|
||||
// create a channel for the StartUp Toast
|
||||
LLScreenChannelBase::Params p;
|
||||
p.id = LLUUID(gSavedSettings.getString("StartUpChannelUUID"));
|
||||
p.id = STARTUP_CHANNEL_UUID;
|
||||
p.channel_align = CA_RIGHT;
|
||||
mStartUpChannel = createChannel(p);
|
||||
|
||||
|
|
@ -143,9 +143,8 @@ void LLChannelManager::onLoginCompleted()
|
|||
gViewerWindow->getRootView()->addChild(mStartUpChannel);
|
||||
|
||||
// init channel's position and size
|
||||
S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
|
||||
S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
|
||||
mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
|
||||
S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
|
||||
mStartUpChannel->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound);
|
||||
mStartUpChannel->setMouseDownCallback(boost::bind(&LLFloaterNotificationsTabbed::onStartUpToastClick, LLFloaterNotificationsTabbed::getInstance(), _2, _3, _4));
|
||||
|
||||
mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
|
||||
|
|
@ -164,7 +163,7 @@ void LLChannelManager::onStartUpToastClose()
|
|||
{
|
||||
mStartUpChannel->setVisible(FALSE);
|
||||
mStartUpChannel->closeStartUpToast();
|
||||
removeChannelByID(LLUUID(gSavedSettings.getString("StartUpChannelUUID")));
|
||||
removeChannelByID(STARTUP_CHANNEL_UUID);
|
||||
mStartUpChannel = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -258,12 +257,12 @@ LLNotificationsUI::LLScreenChannel* LLChannelManager::getNotificationScreenChann
|
|||
{
|
||||
LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
|
||||
(LLNotificationsUI::LLChannelManager::getInstance()->
|
||||
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
|
||||
findChannelByID(NOTIFICATION_CHANNEL_UUID));
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
LL_WARNS() << "Can't find screen channel by NotificationChannelUUID" << LL_ENDL;
|
||||
llassert(!"Can't find screen channel by NotificationChannelUUID");
|
||||
LL_WARNS() << "Can't find screen channel by Notification Channel UUID" << LL_ENDL;
|
||||
llassert(!"Can't find screen channel by Notification Channel UUID");
|
||||
}
|
||||
|
||||
return channel;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ protected:
|
|||
|
||||
registrar.add("Attachment.Touch", boost::bind(handleMultiple, handle_attachment_touch, mUUIDs));
|
||||
registrar.add("Attachment.Edit", boost::bind(handleMultiple, handle_item_edit, mUUIDs));
|
||||
registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
|
||||
registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs, no_op));
|
||||
|
||||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
|
||||
enable_registrar.add("Attachment.OnEnable", boost::bind(&CofAttachmentContextMenu::onEnable, this, _2));
|
||||
|
|
@ -195,7 +195,7 @@ protected:
|
|||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
|
||||
LLUUID selected_id = mUUIDs.back();
|
||||
|
||||
registrar.add("Clothing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
|
||||
registrar.add("Clothing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs, no_op));
|
||||
registrar.add("Clothing.Replace", boost::bind(replaceWearable, selected_id));
|
||||
registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
|
||||
registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id));
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ namespace
|
|||
{
|
||||
|
||||
const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue");
|
||||
const F32 QUEUE_INVENTORY_FETCH_TIMEOUT = 300.f;
|
||||
|
||||
// ObjectIventoryFetcher is an adapter between the LLVOInventoryListener::inventoryChanged
|
||||
// callback mechanism and the LLEventPump coroutine architecture allowing the
|
||||
|
|
@ -359,8 +360,6 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
// Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
|
||||
// which is caught in objectScriptProcessingQueueCoro
|
||||
bool monocompile = floater->mMono;
|
||||
F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
|
||||
|
||||
|
||||
// Initial test to see if we can (or should) attempt to compile the script.
|
||||
LLInventoryItem *item = dynamic_cast<LLInventoryItem *>(inventory);
|
||||
|
|
@ -385,7 +384,7 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
LLExperienceCache::instance().fetchAssociatedExperience(inventory->getParentUUID(), inventory->getUUID(),
|
||||
boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1));
|
||||
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT,
|
||||
LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
|
||||
floater.check();
|
||||
|
|
@ -435,7 +434,7 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
&LLFloaterCompileQueue::handleScriptRetrieval,
|
||||
&userData);
|
||||
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT,
|
||||
LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
}
|
||||
|
||||
|
|
@ -481,7 +480,7 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
|
||||
}
|
||||
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
|
||||
floater.check();
|
||||
|
||||
|
|
@ -736,8 +735,6 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L
|
|||
// Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
|
||||
// This is expected if the dialog closes.
|
||||
LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true);
|
||||
F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -759,7 +756,7 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L
|
|||
args["[OBJECT_NAME]"] = (*itObj).mObjectName;
|
||||
floater->addStringMessage(floater->getString("LoadingObjInv", args));
|
||||
|
||||
LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout,
|
||||
LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, QUEUE_INVENTORY_FETCH_TIMEOUT,
|
||||
LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
|
||||
if (result.has("timeout"))
|
||||
|
|
|
|||
|
|
@ -99,21 +99,6 @@ LLVOAvatar *LLControlAvatar::getAttachedAvatar()
|
|||
|
||||
void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_scale_fixup) const
|
||||
{
|
||||
|
||||
F32 max_legal_offset = MAX_LEGAL_OFFSET;
|
||||
if (gSavedSettings.getControl("AnimatedObjectsMaxLegalOffset"))
|
||||
{
|
||||
max_legal_offset = gSavedSettings.getF32("AnimatedObjectsMaxLegalOffset");
|
||||
}
|
||||
max_legal_offset = llmax(max_legal_offset,0.f);
|
||||
|
||||
F32 max_legal_size = MAX_LEGAL_SIZE;
|
||||
if (gSavedSettings.getControl("AnimatedObjectsMaxLegalSize"))
|
||||
{
|
||||
max_legal_size = gSavedSettings.getF32("AnimatedObjectsMaxLegalSize");
|
||||
}
|
||||
max_legal_size = llmax(max_legal_size, 1.f);
|
||||
|
||||
new_pos_fixup = LLVector3();
|
||||
new_scale_fixup = 1.0f;
|
||||
LLVector3 vol_pos = mRootVolp->getRenderPosition();
|
||||
|
|
@ -138,9 +123,9 @@ void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_
|
|||
{
|
||||
LLVector3 pos_box_offset = point_to_box_offset(vol_pos, unshift_extents);
|
||||
F32 offset_dist = pos_box_offset.length();
|
||||
if (offset_dist > max_legal_offset && offset_dist > 0.f)
|
||||
if (offset_dist > MAX_LEGAL_OFFSET && offset_dist > 0.f)
|
||||
{
|
||||
F32 target_dist = (offset_dist - max_legal_offset);
|
||||
F32 target_dist = (offset_dist - MAX_LEGAL_OFFSET);
|
||||
new_pos_fixup = (target_dist/offset_dist)*pos_box_offset;
|
||||
}
|
||||
if (new_pos_fixup != mPositionConstraintFixup)
|
||||
|
|
@ -153,11 +138,11 @@ void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_
|
|||
|
||||
}
|
||||
}
|
||||
if (box_size/mScaleConstraintFixup > max_legal_size)
|
||||
if (box_size/mScaleConstraintFixup > MAX_LEGAL_SIZE)
|
||||
{
|
||||
new_scale_fixup = mScaleConstraintFixup*max_legal_size/box_size;
|
||||
new_scale_fixup = mScaleConstraintFixup* MAX_LEGAL_SIZE /box_size;
|
||||
LL_DEBUGS("ConstraintFix") << getFullname() << " scale fix, box_size " << box_size << " fixup "
|
||||
<< mScaleConstraintFixup << " max legal " << max_legal_size
|
||||
<< mScaleConstraintFixup << " max legal " << MAX_LEGAL_SIZE
|
||||
<< " -> new scale " << new_scale_fixup << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
|
@ -202,8 +187,7 @@ void LLControlAvatar::matchVolumeTransform()
|
|||
mRoot->setWorldRotation(obj_rot * joint_rot);
|
||||
setRotation(mRoot->getRotation());
|
||||
|
||||
F32 global_scale = gSavedSettings.getF32("AnimatedObjectsGlobalScale");
|
||||
setGlobalScale(global_scale * mScaleConstraintFixup);
|
||||
setGlobalScale(mScaleConstraintFixup);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -253,8 +237,7 @@ void LLControlAvatar::matchVolumeTransform()
|
|||
}
|
||||
mRoot->setPosition(vol_pos + mPositionConstraintFixup);
|
||||
|
||||
F32 global_scale = gSavedSettings.getF32("AnimatedObjectsGlobalScale");
|
||||
setGlobalScale(global_scale * mScaleConstraintFixup);
|
||||
setGlobalScale(mScaleConstraintFixup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -379,6 +362,7 @@ void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time)
|
|||
|
||||
void LLControlAvatar::markDead()
|
||||
{
|
||||
mRootVolp = NULL;
|
||||
super::markDead();
|
||||
mControlAVBridge = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public:
|
|||
virtual BOOL isItemRenameable() const { return TRUE; }
|
||||
virtual BOOL renameItem(const std::string& new_name) { mName = new_name; mNeedsRefresh = true; return TRUE; }
|
||||
virtual BOOL isItemMovable( void ) const { return FALSE; }
|
||||
virtual BOOL isItemRemovable( void ) const { return FALSE; }
|
||||
virtual BOOL isItemRemovable(bool check_worn = true) const { return FALSE; }
|
||||
virtual BOOL isItemInTrash( void) const { return FALSE; }
|
||||
virtual BOOL removeItem() { return FALSE; }
|
||||
virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { }
|
||||
|
|
|
|||
|
|
@ -760,19 +760,6 @@ void LLDrawable::movePartition()
|
|||
if (part)
|
||||
{
|
||||
part->move(this, getSpatialGroup());
|
||||
|
||||
// SL-18251 "On-screen animesh characters using pelvis offset animations
|
||||
// disappear when root goes off-screen"
|
||||
//
|
||||
// Update extents of the root node when Control Avatar changes it's bounds
|
||||
if (mRenderType == LLPipeline::RENDER_TYPE_CONTROL_AV && isRoot())
|
||||
{
|
||||
LLControlAvatar* controlAvatar = dynamic_cast<LLControlAvatar*>(getVObj().get());
|
||||
if (controlAvatar && controlAvatar->mControlAVBridge)
|
||||
{
|
||||
((LLSpatialGroup*)controlAvatar->mControlAVBridge->mOctree->getListener(0))->setState(LLViewerOctreeGroup::DIRTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2104,7 +2104,7 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ
|
|||
{
|
||||
LL_WARNS("ENVIRONMENT") << "Couldn't retrieve environment settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL;
|
||||
}
|
||||
else if (LLApp::isExiting())
|
||||
else if (LLApp::isExiting() || gDisconnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -627,6 +627,9 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
|
|||
switch(filter)
|
||||
{
|
||||
case FFLOAD_ALL:
|
||||
case FFLOAD_EXE:
|
||||
allowedv->push_back("app");
|
||||
allowedv->push_back("exe");
|
||||
allowedv->push_back("wav");
|
||||
allowedv->push_back("bvh");
|
||||
allowedv->push_back("anim");
|
||||
|
|
@ -647,9 +650,6 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
|
|||
allowedv->push_back("tpic");
|
||||
allowedv->push_back("png");
|
||||
break;
|
||||
case FFLOAD_EXE:
|
||||
allowedv->push_back("app");
|
||||
allowedv->push_back("exe");
|
||||
break;
|
||||
case FFLOAD_WAV:
|
||||
allowedv->push_back("wav");
|
||||
|
|
|
|||
|
|
@ -107,15 +107,11 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key)
|
|||
mCloseOnSelect(FALSE),
|
||||
mExcludeAgentFromSearchResults(FALSE),
|
||||
mContextConeOpacity (0.f),
|
||||
mContextConeInAlpha(0.f),
|
||||
mContextConeOutAlpha(0.f),
|
||||
mContextConeFadeTime(0.f)
|
||||
mContextConeInAlpha(CONTEXT_CONE_IN_ALPHA),
|
||||
mContextConeOutAlpha(CONTEXT_CONE_OUT_ALPHA),
|
||||
mContextConeFadeTime(CONTEXT_CONE_FADE_TIME)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
|
||||
|
||||
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
|
||||
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
|
||||
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
|
||||
}
|
||||
|
||||
BOOL LLFloaterAvatarPicker::postBuild()
|
||||
|
|
|
|||
|
|
@ -102,9 +102,9 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show
|
|||
mActive ( TRUE ),
|
||||
mCanApplyImmediately ( show_apply_immediate ),
|
||||
mContextConeOpacity ( 0.f ),
|
||||
mContextConeInAlpha ( 0.f ),
|
||||
mContextConeOutAlpha ( 0.f ),
|
||||
mContextConeFadeTime ( 0.f )
|
||||
mContextConeInAlpha (CONTEXT_CONE_IN_ALPHA),
|
||||
mContextConeOutAlpha (CONTEXT_CONE_OUT_ALPHA),
|
||||
mContextConeFadeTime (CONTEXT_CONE_FADE_TIME)
|
||||
{
|
||||
buildFromFile ( "floater_color_picker.xml");
|
||||
|
||||
|
|
@ -116,10 +116,6 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show
|
|||
mApplyImmediateCheck->setEnabled(FALSE);
|
||||
mApplyImmediateCheck->set(FALSE);
|
||||
}
|
||||
|
||||
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
|
||||
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
|
||||
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
|
||||
}
|
||||
|
||||
LLFloaterColorPicker::~LLFloaterColorPicker()
|
||||
|
|
|
|||
|
|
@ -37,13 +37,14 @@
|
|||
|
||||
const std::string LL_FCP_COMPLETE_NAME("complete_name");
|
||||
const std::string LL_FCP_ACCOUNT_NAME("user_name");
|
||||
const S32 CONVERSATION_HISTORY_PAGE_SIZE = 100;
|
||||
|
||||
LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id)
|
||||
: LLFloater(session_id),
|
||||
mChatHistory(NULL),
|
||||
mSessionID(session_id.asUUID()),
|
||||
mCurrentPage(0),
|
||||
mPageSize(gSavedSettings.getS32("ConversationHistoryPageSize")),
|
||||
mPageSize(CONVERSATION_HISTORY_PAGE_SIZE),
|
||||
mAccountName(session_id[LL_FCP_ACCOUNT_NAME]),
|
||||
mCompleteName(session_id[LL_FCP_COMPLETE_NAME]),
|
||||
mMutex(),
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ BOOL LLFloaterEnvironmentAdjust::postBuild()
|
|||
getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setAllowNoTexture(TRUE);
|
||||
|
||||
getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setDefaultImageAssetID(LLSettingsWater::GetDefaultWaterNormalAssetId());
|
||||
getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setBlankImageAssetID(LLUUID(gSavedSettings.getString("DefaultBlankNormalTexture")));
|
||||
getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setBlankImageAssetID(DEFAULT_BLANK_NORMAL_TEXTURE);
|
||||
getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onWaterMapChanged(); });
|
||||
|
||||
getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setCommitCallback([this](LLUICtrl*, const LLSD&) { onReflectionProbeAmbianceChanged(); });
|
||||
|
|
|
|||
|
|
@ -88,13 +88,10 @@ LLFloaterExperiencePicker::LLFloaterExperiencePicker( const LLSD& key )
|
|||
:LLFloater(key)
|
||||
,mSearchPanel(NULL)
|
||||
,mContextConeOpacity(0.f)
|
||||
,mContextConeInAlpha(0.f)
|
||||
,mContextConeOutAlpha(0.f)
|
||||
,mContextConeFadeTime(0.f)
|
||||
,mContextConeInAlpha(CONTEXT_CONE_IN_ALPHA)
|
||||
,mContextConeOutAlpha(CONTEXT_CONE_OUT_ALPHA)
|
||||
,mContextConeFadeTime(CONTEXT_CONE_FADE_TIME)
|
||||
{
|
||||
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
|
||||
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
|
||||
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
|
||||
}
|
||||
|
||||
LLFloaterExperiencePicker::~LLFloaterExperiencePicker()
|
||||
|
|
|
|||
|
|
@ -260,7 +260,8 @@ void LLFloaterIMNearbyChat::loadHistory()
|
|||
|
||||
void LLFloaterIMNearbyChat::removeScreenChat()
|
||||
{
|
||||
LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
|
||||
LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(
|
||||
LLNotificationsUI::NEARBY_CHAT_CHANNEL_UUID);
|
||||
if(chat_channel)
|
||||
{
|
||||
chat_channel->removeToastsFromChannel();
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ LLFloaterIMNearbyChatHandler::LLFloaterIMNearbyChatHandler()
|
|||
{
|
||||
// Getting a Channel for our notifications
|
||||
LLFloaterIMNearbyChatScreenChannel::Params p;
|
||||
p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID"));
|
||||
p.id = NEARBY_CHAT_CHANNEL_UUID;
|
||||
LLFloaterIMNearbyChatScreenChannel* channel = new LLFloaterIMNearbyChatScreenChannel(p);
|
||||
|
||||
LLFloaterIMNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel;
|
||||
|
|
|
|||
|
|
@ -651,7 +651,7 @@ void LLFloaterIMSession::setDocked(bool docked, bool pop_on_undock)
|
|||
// update notification channel state
|
||||
LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
|
||||
(LLNotificationsUI::LLChannelManager::getInstance()->
|
||||
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
|
||||
findChannelByID(LLNotificationsUI::NOTIFICATION_CHANNEL_UUID));
|
||||
|
||||
if(!isChatMultiTab())
|
||||
{
|
||||
|
|
@ -687,7 +687,7 @@ void LLFloaterIMSession::setVisible(BOOL visible)
|
|||
{
|
||||
LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
|
||||
(LLNotificationsUI::LLChannelManager::getInstance()->
|
||||
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
|
||||
findChannelByID(LLNotificationsUI::NOTIFICATION_CHANNEL_UUID));
|
||||
|
||||
LLFloaterIMSessionTab::setVisible(visible);
|
||||
|
||||
|
|
@ -865,7 +865,7 @@ void LLFloaterIMSession::updateMessages()
|
|||
// remove embedded notification from channel
|
||||
LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
|
||||
(LLNotificationsUI::LLChannelManager::getInstance()->
|
||||
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
|
||||
findChannelByID(LLNotificationsUI::NOTIFICATION_CHANNEL_UUID));
|
||||
if (getVisible())
|
||||
{
|
||||
// toast will be automatically closed since it is not storable toast
|
||||
|
|
|
|||
|
|
@ -250,6 +250,13 @@ void LLFloaterJoystick::refresh()
|
|||
initFromSettings();
|
||||
}
|
||||
|
||||
bool LLFloaterJoystick::addDeviceCallback(std::string &name, LLSD& value, void* userdata)
|
||||
{
|
||||
LLFloaterJoystick * floater = (LLFloaterJoystick*)userdata;
|
||||
floater->mJoysticksCombo->add(name, value, ADD_BOTTOM, 1);
|
||||
return false; // keep searching
|
||||
}
|
||||
|
||||
void LLFloaterJoystick::addDevice(std::string &name, LLSD& value)
|
||||
{
|
||||
mJoysticksCombo->add(name, value, ADD_BOTTOM, 1);
|
||||
|
|
@ -264,19 +271,21 @@ void LLFloaterJoystick::refreshListOfDevices()
|
|||
|
||||
mHasDeviceList = false;
|
||||
|
||||
void* win_calback = nullptr;
|
||||
// di8_devices_callback callback is immediate and happens in scope of getInputDevices()
|
||||
#if LL_WINDOWS && !LL_MESA_HEADLESS
|
||||
// space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib
|
||||
U32 device_type = DI8DEVCLASS_GAMECTRL;
|
||||
void* callback = &di8_list_devices_callback;
|
||||
#else
|
||||
// MAC doesn't support device search yet
|
||||
// On MAC there is an ndof_idsearch and it is possible to specify product
|
||||
// and manufacturer in NDOF_Device for ndof_init_first to pick specific one
|
||||
win_calback = di8_list_devices_callback;
|
||||
#elif LL_DARWIN
|
||||
U32 device_type = 0;
|
||||
#else
|
||||
// On MAC it is possible to specify product
|
||||
// and manufacturer in NDOF_Device for
|
||||
// ndof_init_first to pick specific device
|
||||
U32 device_type = 0;
|
||||
void* callback = NULL;
|
||||
#endif
|
||||
if (gViewerWindow->getWindow()->getInputDevices(device_type, callback, this))
|
||||
if (gViewerWindow->getWindow()->getInputDevices(device_type, addDeviceCallback, win_calback, this))
|
||||
{
|
||||
mHasDeviceList = true;
|
||||
}
|
||||
|
|
@ -418,10 +427,11 @@ void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel)
|
|||
joystick->toggleFlycam();
|
||||
}
|
||||
}
|
||||
|
||||
std::string device_id = LLViewerJoystick::getInstance()->getDeviceUUIDString();
|
||||
gSavedSettings.setString("JoystickDeviceUUID", device_id);
|
||||
LL_DEBUGS("Joystick") << "Selected " << device_id << " as joystick." << LL_ENDL;
|
||||
|
||||
LLViewerJoystick::getInstance()->saveDeviceIdToSettings();
|
||||
|
||||
std::string device_string = LLViewerJoystick::getInstance()->getDeviceUUIDString();
|
||||
LL_DEBUGS("Joystick") << "Selected " << device_string << " as joystick." << LL_ENDL;
|
||||
|
||||
self->refreshListOfDevices();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public:
|
|||
virtual void draw();
|
||||
static void setSNDefaults();
|
||||
|
||||
static bool addDeviceCallback(std::string &name, LLSD& value, void* userdata);
|
||||
void addDevice(std::string &name, LLSD& value);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ LLPanel * LLFloaterNotificationsTabbed::findItemByID(const LLUUID& id, std::stri
|
|||
void LLFloaterNotificationsTabbed::initChannel()
|
||||
{
|
||||
LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(
|
||||
LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
|
||||
LLNotificationsUI::NOTIFICATION_CHANNEL_UUID);
|
||||
mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel);
|
||||
if(NULL == mChannel)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -329,9 +329,9 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
|
|||
|
||||
void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type )
|
||||
{
|
||||
if ( APT_PROPERTIES == type )
|
||||
if ( APT_PROPERTIES_LEGACY == type )
|
||||
{
|
||||
const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData );
|
||||
const LLAvatarLegacyData* pAvatarData = static_cast<const LLAvatarLegacyData*>( pData );
|
||||
if (pAvatarData && (gAgent.getID() == pAvatarData->avatar_id) && (pAvatarData->avatar_id != LLUUID::null))
|
||||
{
|
||||
mAllowPublish = (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH);
|
||||
|
|
@ -471,9 +471,7 @@ BOOL LLFloaterPreference::postBuild()
|
|||
|
||||
void LLFloaterPreference::updateDeleteTranscriptsButton()
|
||||
{
|
||||
std::vector<std::string> list_of_transcriptions_file_names;
|
||||
LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names);
|
||||
getChild<LLButton>("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0);
|
||||
getChild<LLButton>("delete_transcripts")->setEnabled(LLLogChat::transcriptFilesExist());
|
||||
}
|
||||
|
||||
void LLFloaterPreference::onDoNotDisturbResponseChanged()
|
||||
|
|
@ -638,7 +636,6 @@ void LLFloaterPreference::cancel()
|
|||
|
||||
void LLFloaterPreference::onOpen(const LLSD& key)
|
||||
{
|
||||
|
||||
// this variable and if that follows it are used to properly handle do not disturb mode response message
|
||||
static bool initialized = FALSE;
|
||||
// if user is logged in and we haven't initialized do not disturb mode response yet, do it
|
||||
|
|
@ -665,7 +662,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)
|
|||
(gAgent.isMature() || gAgent.isGodlike());
|
||||
|
||||
LLComboBox* maturity_combo = getChild<LLComboBox>("maturity_desired_combobox");
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest( gAgent.getID() );
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarLegacyPropertiesRequest( gAgent.getID() );
|
||||
if (can_choose_maturity)
|
||||
{
|
||||
// if they're not adult or a god, they shouldn't see the adult selection, so delete it
|
||||
|
|
|
|||
|
|
@ -48,12 +48,6 @@ public:
|
|||
LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { }
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch"))
|
||||
{
|
||||
LLNotificationsUtil::add("NoSearch", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
|
||||
return true;
|
||||
}
|
||||
|
||||
const size_t parts = tokens.size();
|
||||
|
||||
// get the (optional) category for the search
|
||||
|
|
|
|||
|
|
@ -129,12 +129,6 @@ public:
|
|||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap"))
|
||||
{
|
||||
LLNotificationsUtil::add("NoWorldMap", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (params.size() == 0)
|
||||
{
|
||||
// support the secondlife:///app/worldmap SLapp
|
||||
|
|
@ -170,12 +164,6 @@ public:
|
|||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap"))
|
||||
{
|
||||
LLNotificationsUtil::add("NoWorldMap", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
|
||||
return true;
|
||||
}
|
||||
|
||||
//Make sure we have some parameters
|
||||
if (params.size() == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@
|
|||
|
||||
// Longest time, in seconds, to wait for all animations to stop playing
|
||||
const F32 MAX_WAIT_ANIM_SECS = 30.f;
|
||||
// Longest time, in seconds, to wait for a key release.
|
||||
// This should be relatively long, but not too long. 10 minutes is enough
|
||||
const F32 MAX_WAIT_KEY_SECS = 60.f * 10.f;
|
||||
|
||||
// Lightweight constructor.
|
||||
// init() does the heavy lifting.
|
||||
|
|
@ -528,12 +531,13 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset
|
|||
LLGestureMgr::instance().replaceGesture(base_item_id, gesture, new_asset_id);
|
||||
}
|
||||
|
||||
void LLGestureMgr::playGesture(LLMultiGesture* gesture)
|
||||
void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool fromKeyPress)
|
||||
{
|
||||
if (!gesture) return;
|
||||
|
||||
// Reset gesture to first step
|
||||
gesture->mCurrentStep = 0;
|
||||
gesture->mTriggeredByKey = fromKeyPress;
|
||||
|
||||
// Add to list of playing
|
||||
gesture->mPlaying = TRUE;
|
||||
|
|
@ -731,7 +735,8 @@ BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask)
|
|||
if (!gesture) continue;
|
||||
|
||||
if (gesture->mKey == key
|
||||
&& gesture->mMask == mask)
|
||||
&& gesture->mMask == mask
|
||||
&& gesture->mWaitingKeyRelease == FALSE)
|
||||
{
|
||||
matching.push_back(gesture);
|
||||
}
|
||||
|
|
@ -744,13 +749,38 @@ BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask)
|
|||
|
||||
LLMultiGesture* gesture = matching[random];
|
||||
|
||||
playGesture(gesture);
|
||||
playGesture(gesture, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLGestureMgr::triggerGestureRelease(KEY key, MASK mask)
|
||||
{
|
||||
std::vector <LLMultiGesture *> matching;
|
||||
item_map_t::iterator it;
|
||||
|
||||
// collect matching gestures
|
||||
for (it = mActive.begin(); it != mActive.end(); ++it)
|
||||
{
|
||||
LLMultiGesture* gesture = (*it).second;
|
||||
|
||||
// asset data might not have arrived yet
|
||||
if (!gesture) continue;
|
||||
|
||||
if (gesture->mKey == key
|
||||
&& gesture->mMask == mask)
|
||||
{
|
||||
gesture->mKeyReleased = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//If we found one, block. Otherwise tell them it's free to go.
|
||||
return matching.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
S32 LLGestureMgr::getPlayingCount() const
|
||||
{
|
||||
return mPlaying.size();
|
||||
|
|
@ -899,6 +929,32 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture)
|
|||
continue;
|
||||
}
|
||||
|
||||
// If we're waiting a fixed amount of time, check for timer
|
||||
// expiration.
|
||||
if (gesture->mWaitingKeyRelease)
|
||||
{
|
||||
// We're waiting for a certain amount of time to pass
|
||||
if (gesture->mKeyReleased)
|
||||
{
|
||||
// wait is done, continue execution
|
||||
gesture->mWaitingKeyRelease = FALSE;
|
||||
gesture->mCurrentStep++;
|
||||
}
|
||||
else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_KEY_SECS)
|
||||
{
|
||||
LL_INFOS("GestureMgr") << "Waited too long for key release, continuing gesture."
|
||||
<< LL_ENDL;
|
||||
gesture->mWaitingKeyRelease = FALSE;
|
||||
gesture->mCurrentStep++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're waiting, so execution is done for now
|
||||
waiting = TRUE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we're waiting on our animations to stop, poll for
|
||||
// completion.
|
||||
if (gesture->mWaitingAnimations)
|
||||
|
|
@ -1015,7 +1071,17 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)
|
|||
case STEP_WAIT:
|
||||
{
|
||||
LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
|
||||
if (wait_step->mFlags & WAIT_FLAG_TIME)
|
||||
if (gesture->mTriggeredByKey // Only wait here IF we were triggered by a key!
|
||||
&& gesture->mWaitingKeyRelease == FALSE // We can only do this once! Prevent gestures infinitely running
|
||||
&& wait_step->mFlags & WAIT_FLAG_KEY_RELEASE)
|
||||
{
|
||||
// Lets wait for the key release first so we don't hold up re-presses
|
||||
gesture->mWaitingKeyRelease = TRUE;
|
||||
gesture->mKeyReleased = FALSE;
|
||||
// Use the wait timer as a deadlock breaker for key release waits.
|
||||
gesture->mWaitTimer.reset();
|
||||
}
|
||||
else if (wait_step->mFlags & WAIT_FLAG_TIME)
|
||||
{
|
||||
gesture->mWaitingTimer = TRUE;
|
||||
gesture->mWaitTimer.reset();
|
||||
|
|
@ -1023,8 +1089,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)
|
|||
else if (wait_step->mFlags & WAIT_FLAG_ALL_ANIM)
|
||||
{
|
||||
gesture->mWaitingAnimations = TRUE;
|
||||
// Use the wait timer as a deadlock breaker for animation
|
||||
// waits.
|
||||
// Use the wait timer as a deadlock breaker for animation waits.
|
||||
gesture->mWaitTimer.reset();
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -102,7 +102,10 @@ public:
|
|||
const item_map_t& getActiveGestures() const { return mActive; }
|
||||
// Force a gesture to be played, for example, if it is being
|
||||
// previewed.
|
||||
void playGesture(LLMultiGesture* gesture);
|
||||
void playGesture(LLMultiGesture* gesture, bool fromKeyPress);
|
||||
void playGesture(LLMultiGesture* gesture) {
|
||||
playGesture(gesture, FALSE);
|
||||
}
|
||||
void playGesture(const LLUUID& item_id);
|
||||
|
||||
// Stop all requested or playing anims for this gesture
|
||||
|
|
@ -118,10 +121,14 @@ public:
|
|||
{
|
||||
mCallbackMap[inv_item_id] = cb;
|
||||
}
|
||||
// Trigger the first gesture that matches this key.
|
||||
// Trigger a random gesture that matches this key.
|
||||
// Returns TRUE if it finds a gesture bound to that key.
|
||||
BOOL triggerGesture(KEY key, MASK mask);
|
||||
|
||||
// Trigger release wait on all gestures that matches this key.
|
||||
// Returns TRUE if it finds a gesture bound to that key.
|
||||
BOOL triggerGestureRelease(KEY key, MASK mask);
|
||||
|
||||
// Trigger all gestures referenced as substrings in this string
|
||||
BOOL triggerAndReviseString(const std::string &str, std::string *revised_string = NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -88,12 +88,6 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableGroupInfo"))
|
||||
{
|
||||
LLNotificationsUtil::add("NoGroupInfo", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tokens.size() < 1)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -372,7 +366,16 @@ void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id)
|
|||
args["GROUP"] = gdatap->mName;
|
||||
LLSD payload;
|
||||
payload["group_id"] = group_id;
|
||||
LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
|
||||
if (gdatap->mMembershipFee > 0)
|
||||
{
|
||||
args["COST"] = gdatap->mMembershipFee;
|
||||
LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("GroupLeaveConfirmMemberNoFee", args, payload, onLeaveGroup);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -404,7 +407,7 @@ void LLGroupActions::inspect(const LLUUID& group_id)
|
|||
}
|
||||
|
||||
// static
|
||||
void LLGroupActions::show(const LLUUID& group_id)
|
||||
void LLGroupActions::show(const LLUUID &group_id, bool expand_notices_tab)
|
||||
{
|
||||
if (group_id.isNull())
|
||||
return;
|
||||
|
|
@ -412,6 +415,10 @@ void LLGroupActions::show(const LLUUID& group_id)
|
|||
LLSD params;
|
||||
params["group_id"] = group_id;
|
||||
params["open_tab_name"] = "panel_group_info_sidetray";
|
||||
if (expand_notices_tab)
|
||||
{
|
||||
params["action"] = "show_notices";
|
||||
}
|
||||
|
||||
LLFloaterSidePanelContainer::showPanel("people", "panel_group_info_sidetray", params);
|
||||
LLFloater *floater = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>("people");
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
/**
|
||||
* Show group information panel.
|
||||
*/
|
||||
static void show(const LLUUID& group_id);
|
||||
static void show(const LLUUID& group_id, bool expand_notices_tab = false);
|
||||
|
||||
/**
|
||||
* Show group inspector floater.
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL
|
|||
|
||||
item->getChildView("info_btn")->setVisible( false);
|
||||
item->getChildView("profile_btn")->setVisible( false);
|
||||
item->getChildView("notices_btn")->setVisible(false);
|
||||
item->setGroupIconVisible(mShowIcons);
|
||||
if (!mShowIcons)
|
||||
{
|
||||
|
|
@ -403,6 +404,7 @@ mGroupIcon(NULL),
|
|||
mGroupNameBox(NULL),
|
||||
mInfoBtn(NULL),
|
||||
mProfileBtn(NULL),
|
||||
mNoticesBtn(NULL),
|
||||
mVisibilityHideBtn(NULL),
|
||||
mVisibilityShowBtn(NULL),
|
||||
mGroupID(LLUUID::null),
|
||||
|
|
@ -435,6 +437,9 @@ BOOL LLGroupListItem::postBuild()
|
|||
mProfileBtn = getChild<LLButton>("profile_btn");
|
||||
mProfileBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onProfileBtnClick(); });
|
||||
|
||||
mNoticesBtn = getChild<LLButton>("notices_btn");
|
||||
mNoticesBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onNoticesBtnClick(); });
|
||||
|
||||
mVisibilityHideBtn = findChild<LLButton>("visibility_hide_btn");
|
||||
if (mVisibilityHideBtn)
|
||||
{
|
||||
|
|
@ -470,13 +475,17 @@ void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask)
|
|||
{
|
||||
mInfoBtn->setVisible(true);
|
||||
mProfileBtn->setVisible(true);
|
||||
if (mForAgent && mVisibilityHideBtn)
|
||||
if (mForAgent)
|
||||
{
|
||||
LLGroupData agent_gdatap;
|
||||
if (gAgent.getGroupData(mGroupID, agent_gdatap))
|
||||
{
|
||||
mVisibilityHideBtn->setVisible(agent_gdatap.mListInProfile);
|
||||
mVisibilityShowBtn->setVisible(!agent_gdatap.mListInProfile);
|
||||
if (mVisibilityHideBtn)
|
||||
{
|
||||
mVisibilityHideBtn->setVisible(agent_gdatap.mListInProfile);
|
||||
mVisibilityShowBtn->setVisible(!agent_gdatap.mListInProfile);
|
||||
}
|
||||
mNoticesBtn->setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -489,6 +498,7 @@ void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask)
|
|||
getChildView("hovered_icon")->setVisible( false);
|
||||
mInfoBtn->setVisible(false);
|
||||
mProfileBtn->setVisible(false);
|
||||
mNoticesBtn->setVisible(false);
|
||||
if (mVisibilityHideBtn)
|
||||
{
|
||||
mVisibilityHideBtn->setVisible(false);
|
||||
|
|
@ -583,6 +593,11 @@ void LLGroupListItem::onProfileBtnClick()
|
|||
LLGroupActions::show(mGroupID);
|
||||
}
|
||||
|
||||
void LLGroupListItem::onNoticesBtnClick()
|
||||
{
|
||||
LLGroupActions::show(mGroupID, true);
|
||||
}
|
||||
|
||||
void LLGroupListItem::onVisibilityBtnClick(bool new_visibility)
|
||||
{
|
||||
LLGroupData agent_gdatap;
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ private:
|
|||
void setBold(bool bold);
|
||||
void onInfoBtnClick();
|
||||
void onProfileBtnClick();
|
||||
void onNoticesBtnClick();
|
||||
void onVisibilityBtnClick(bool new_visibility);
|
||||
|
||||
LLTextBox* mGroupNameBox;
|
||||
|
|
@ -130,6 +131,7 @@ private:
|
|||
LLGroupIconCtrl* mGroupIcon;
|
||||
LLButton* mInfoBtn;
|
||||
LLButton* mProfileBtn;
|
||||
LLButton* mNoticesBtn;
|
||||
LLButton* mVisibilityHideBtn;
|
||||
LLButton* mVisibilityShowBtn;
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,8 @@ LLIMHandler::~LLIMHandler()
|
|||
//--------------------------------------------------------------------------
|
||||
void LLIMHandler::initChannel()
|
||||
{
|
||||
S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
|
||||
S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
|
||||
mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound);
|
||||
S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
|
||||
mChannel.get()->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -581,6 +581,12 @@ void chatterBoxHistoryCoro(std::string url, LLUUID sessionId, std::string from,
|
|||
return;
|
||||
}
|
||||
|
||||
if (LLApp::isExiting() || gDisconnected)
|
||||
{
|
||||
LL_DEBUGS("ChatHistory") << "Ignoring chat history response, shutting down" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Add history to IM session
|
||||
LLSD history = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT];
|
||||
|
||||
|
|
@ -3915,6 +3921,12 @@ public:
|
|||
const LLSD& context,
|
||||
const LLSD& input) const
|
||||
{
|
||||
if (LLApp::isExiting() || gDisconnected)
|
||||
{
|
||||
LL_DEBUGS("ChatHistory") << "Ignoring ChatterBox session, Shutting down" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD body;
|
||||
LLUUID temp_session_id;
|
||||
LLUUID session_id;
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ LLInspect::~LLInspect()
|
|||
// virtual
|
||||
void LLInspect::draw()
|
||||
{
|
||||
static LLCachedControl<F32> FADE_TIME(*LLUI::getInstance()->mSettingGroups["config"], "InspectorFadeTime", 1.f);
|
||||
static LLCachedControl<F32> STAY_TIME(*LLUI::getInstance()->mSettingGroups["config"], "InspectorShowTime", 1.f);
|
||||
const F32 FADE_TIME = 0.5f;
|
||||
const F32 STAY_TIME = 3.f;
|
||||
if (mOpenTimer.getStarted())
|
||||
{
|
||||
LLFloater::draw();
|
||||
|
|
@ -59,7 +59,7 @@ void LLInspect::draw()
|
|||
}
|
||||
else if (mCloseTimer.getStarted())
|
||||
{
|
||||
F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_TIME(), 1.f, 0.f);
|
||||
F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_TIME, 1.f, 0.f);
|
||||
LLViewDrawContext context(alpha);
|
||||
LLFloater::draw();
|
||||
if (mCloseTimer.getElapsedTimeF32() > FADE_TIME)
|
||||
|
|
|
|||
|
|
@ -261,12 +261,15 @@ void LLInspectAvatar::requestUpdate()
|
|||
void LLInspectAvatar::processAvatarData(LLAvatarData* data)
|
||||
{
|
||||
LLStringUtil::format_map_t args;
|
||||
{
|
||||
std::string birth_date = LLTrans::getString("AvatarBirthDateFormat");
|
||||
LLStringUtil::format(birth_date, LLSD().with("datetime", (S32) data->born_on.secondsSinceEpoch()));
|
||||
args["[BORN_ON]"] = birth_date;
|
||||
}
|
||||
args["[AGE]"] = LLDateUtil::ageFromDate(data->born_on, LLDate::now());
|
||||
|
||||
std::string birth_date = LLTrans::getString(data->hide_age ?
|
||||
"AvatarBirthDateFormatShort" :
|
||||
"AvatarBirthDateFormatFull");
|
||||
LLStringUtil::format(birth_date, LLSD().with("datetime", (S32)data->born_on.secondsSinceEpoch()));
|
||||
args["[BORN_ON]"] = birth_date;
|
||||
args["[AGE]"] = data->hide_age ?
|
||||
LLStringUtilBase<char>::null :
|
||||
LLDateUtil::ageFromDate(data->born_on, LLDate::now());
|
||||
args["[SL_PROFILE]"] = data->about_text;
|
||||
args["[RW_PROFILE"] = data->fl_about_text;
|
||||
args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(data);
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ private:
|
|||
LLInspectToast::LLInspectToast(const LLSD& notification_id) :
|
||||
LLInspect(LLSD()), mPanel(NULL)
|
||||
{
|
||||
LLScreenChannelBase* channel = LLChannelManager::getInstance()->findChannelByID(
|
||||
LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
|
||||
LLScreenChannelBase* channel = LLChannelManager::getInstance()->findChannelByID(
|
||||
LLNotificationsUI::NOTIFICATION_CHANNEL_UUID);
|
||||
mScreenChannel = dynamic_cast<LLScreenChannel*>(channel);
|
||||
if(NULL == mScreenChannel)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@
|
|||
void copy_slurl_to_clipboard_callback_inv(const std::string& slurl);
|
||||
|
||||
const F32 SOUND_GAIN = 1.0f;
|
||||
const F32 FOLDER_LOADING_MESSAGE_DELAY = 0.5f; // Seconds to wait before showing the LOADING... text in folder views
|
||||
|
||||
using namespace LLOldEvents;
|
||||
|
||||
|
|
@ -308,9 +309,9 @@ void LLInvFVBridge::setCreationDate(time_t creation_date_utc)
|
|||
|
||||
|
||||
// Can be destroyed (or moved to trash)
|
||||
BOOL LLInvFVBridge::isItemRemovable() const
|
||||
BOOL LLInvFVBridge::isItemRemovable(bool check_worn) const
|
||||
{
|
||||
return get_is_item_removable(getInventoryModel(), mUUID);
|
||||
return get_is_item_removable(getInventoryModel(), mUUID, check_worn);
|
||||
}
|
||||
|
||||
// Can be moved to another folder
|
||||
|
|
@ -772,9 +773,6 @@ void hide_context_entries(LLMenuGL& menu,
|
|||
|
||||
bool found = false;
|
||||
|
||||
std::string myinput;
|
||||
std::vector<std::string> mylist{ "a", "b", "c" };
|
||||
|
||||
menuentry_vec_t::const_iterator itor2 = std::find(entries_to_show.begin(), entries_to_show.end(), name);
|
||||
if (itor2 != entries_to_show.end())
|
||||
{
|
||||
|
|
@ -874,7 +872,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
|
|||
}
|
||||
|
||||
items.push_back(std::string("Cut"));
|
||||
if (!isItemMovable() || !isItemRemovable())
|
||||
if (!isItemMovable() || !canMenuCut())
|
||||
{
|
||||
disabled_items.push_back(std::string("Cut"));
|
||||
}
|
||||
|
|
@ -923,7 +921,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
|
|||
if(!single_folder_root)
|
||||
{
|
||||
items.push_back(std::string("Cut"));
|
||||
if (!isItemMovable() || !isItemRemovable())
|
||||
if (!isItemMovable() || !canMenuCut())
|
||||
{
|
||||
disabled_items.push_back(std::string("Cut"));
|
||||
}
|
||||
|
|
@ -1068,7 +1066,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,
|
|||
|
||||
items.push_back(std::string("Delete"));
|
||||
|
||||
if (!isItemRemovable() || isPanelActive("Favorite Items"))
|
||||
if (isPanelActive("Favorite Items") || !canMenuDelete())
|
||||
{
|
||||
disabled_items.push_back(std::string("Delete"));
|
||||
}
|
||||
|
|
@ -1224,6 +1222,16 @@ void LLInvFVBridge::addLinkReplaceMenuOption(menuentry_vec_t& items, menuentry_v
|
|||
}
|
||||
}
|
||||
|
||||
bool LLInvFVBridge::canMenuDelete()
|
||||
{
|
||||
return isItemRemovable(false);
|
||||
}
|
||||
|
||||
bool LLInvFVBridge::canMenuCut()
|
||||
{
|
||||
return isItemRemovable(true);
|
||||
}
|
||||
|
||||
// *TODO: remove this
|
||||
BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
|
||||
{
|
||||
|
|
@ -1778,7 +1786,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
|
|||
}
|
||||
else if ("show_in_main_panel" == action)
|
||||
{
|
||||
LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, mUUID, TRUE);
|
||||
LLInventoryPanel::openInventoryPanelAndSetSelection(true, mUUID, true);
|
||||
return;
|
||||
}
|
||||
else if ("cut" == action)
|
||||
|
|
@ -2412,48 +2420,19 @@ void LLFolderBridge::update()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Iterate through a folder's children to determine if
|
||||
// all the children are removable.
|
||||
class LLIsItemRemovable : public LLFolderViewFunctor
|
||||
{
|
||||
public:
|
||||
LLIsItemRemovable() : mPassed(TRUE) {}
|
||||
virtual void doFolder(LLFolderViewFolder* folder)
|
||||
{
|
||||
mPassed &= folder->getViewModelItem()->isItemRemovable();
|
||||
}
|
||||
virtual void doItem(LLFolderViewItem* item)
|
||||
{
|
||||
mPassed &= item->getViewModelItem()->isItemRemovable();
|
||||
}
|
||||
BOOL mPassed;
|
||||
};
|
||||
|
||||
// Can be destroyed (or moved to trash)
|
||||
BOOL LLFolderBridge::isItemRemovable() const
|
||||
BOOL LLFolderBridge::isItemRemovable(bool check_worn) const
|
||||
{
|
||||
if (!get_is_category_removable(getInventoryModel(), mUUID))
|
||||
if (!get_is_category_and_children_removable(getInventoryModel(), mUUID, check_worn))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LLInventoryPanel* panel = mInventoryPanel.get();
|
||||
LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getItemByID(mUUID) : NULL);
|
||||
if (folderp)
|
||||
{
|
||||
LLIsItemRemovable folder_test;
|
||||
folderp->applyFunctorToChildren(folder_test);
|
||||
if (!folder_test.mPassed)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMarketplaceListingsFolder() && (!LLMarketplaceData::instance().isSLMDataFetched() || LLMarketplaceData::instance().getActivationState(mUUID)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (isMarketplaceListingsFolder()
|
||||
&& (!LLMarketplaceData::instance().isSLMDataFetched() || LLMarketplaceData::instance().getActivationState(mUUID)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -3409,7 +3388,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
|
|||
}
|
||||
else if ("show_in_main_panel" == action)
|
||||
{
|
||||
LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, mUUID, TRUE);
|
||||
LLInventoryPanel::openInventoryPanelAndSetSelection(true, mUUID, true);
|
||||
return;
|
||||
}
|
||||
else if ("cut" == action)
|
||||
|
|
@ -4382,6 +4361,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
disabled_items.push_back("New Settings");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
items.push_back(std::string("New Listing Folder"));
|
||||
}
|
||||
if (menu_items_added)
|
||||
{
|
||||
items.push_back(std::string("Create Separator"));
|
||||
|
|
@ -4523,7 +4506,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
|
|||
return;
|
||||
}
|
||||
|
||||
if (!isItemRemovable())
|
||||
if (!canMenuDelete())
|
||||
{
|
||||
disabled_items.push_back(std::string("Delete"));
|
||||
}
|
||||
|
|
@ -4894,6 +4877,192 @@ void LLFolderBridge::modifyOutfit(BOOL append)
|
|||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFolderBridge::onCanDeleteIdle(void* user_data)
|
||||
{
|
||||
LLFolderBridge* self = (LLFolderBridge*)user_data;
|
||||
|
||||
// we really need proper onidle mechanics that returns available time
|
||||
const F32 EXPIRY_SECONDS = 0.008f;
|
||||
LLTimer timer;
|
||||
timer.setTimerExpirySec(EXPIRY_SECONDS);
|
||||
|
||||
LLInventoryModel* model = self->getInventoryModel();
|
||||
if (model)
|
||||
{
|
||||
switch (self->mCanDeleteFolderState)
|
||||
{
|
||||
case CDS_INIT_FOLDER_CHECK:
|
||||
// Can still be expensive, split it further?
|
||||
model->collectDescendents(
|
||||
self->mUUID,
|
||||
self->mFoldersToCheck,
|
||||
self->mItemsToCheck,
|
||||
LLInventoryModel::EXCLUDE_TRASH);
|
||||
self->mCanDeleteFolderState = CDS_PROCESSING_ITEMS;
|
||||
break;
|
||||
|
||||
case CDS_PROCESSING_ITEMS:
|
||||
while (!timer.hasExpired() && !self->mItemsToCheck.empty())
|
||||
{
|
||||
LLViewerInventoryItem* item = self->mItemsToCheck.back().get();
|
||||
if (item)
|
||||
{
|
||||
if (LLAppearanceMgr::instance().getIsProtectedCOFItem(item))
|
||||
{
|
||||
if (get_is_item_worn(item))
|
||||
{
|
||||
// At the moment we disable 'cut' if category has worn items (do we need to?)
|
||||
// but allow 'delete' to happen since it will prompt user to detach
|
||||
self->mCanCut = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!item->getIsLinkType() && get_is_item_worn(item))
|
||||
{
|
||||
self->mCanCut = false;
|
||||
}
|
||||
}
|
||||
self->mItemsToCheck.pop_back();
|
||||
}
|
||||
self->mCanDeleteFolderState = CDS_PROCESSING_FOLDERS;
|
||||
break;
|
||||
case CDS_PROCESSING_FOLDERS:
|
||||
{
|
||||
const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
|
||||
LLViewerInventoryCategory* outfit_linked_category = base_outfit_link ? base_outfit_link->getLinkedCategory() : nullptr;
|
||||
|
||||
while (!timer.hasExpired() && !self->mFoldersToCheck.empty())
|
||||
{
|
||||
LLViewerInventoryCategory* cat = self->mFoldersToCheck.back().get();
|
||||
if (cat)
|
||||
{
|
||||
const LLFolderType::EType folder_type = cat->getPreferredType();
|
||||
if (LLFolderType::lookupIsProtectedType(folder_type))
|
||||
{
|
||||
self->mCanCut = false;
|
||||
self->mCanDelete = false;
|
||||
self->completeDeleteProcessing();
|
||||
break;
|
||||
}
|
||||
|
||||
// Can't delete the outfit that is currently being worn.
|
||||
if (folder_type == LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
if (cat == outfit_linked_category)
|
||||
{
|
||||
self->mCanCut = false;
|
||||
self->mCanDelete = false;
|
||||
self->completeDeleteProcessing();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
self->mFoldersToCheck.pop_back();
|
||||
}
|
||||
}
|
||||
self->mCanDeleteFolderState = CDS_DONE;
|
||||
break;
|
||||
case CDS_DONE:
|
||||
self->completeDeleteProcessing();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFolderBridge::canMenuDelete()
|
||||
{
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if (!model) return false;
|
||||
LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
|
||||
if (!category)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
S32 version = category->getVersion();
|
||||
if (mLastCheckedVersion == version)
|
||||
{
|
||||
return mCanDelete;
|
||||
}
|
||||
|
||||
initCanDeleteProcessing(model, version);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLFolderBridge::canMenuCut()
|
||||
{
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if (!model) return false;
|
||||
LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
|
||||
if (!category)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
S32 version = category->getVersion();
|
||||
if (mLastCheckedVersion == version)
|
||||
{
|
||||
return mCanCut;
|
||||
}
|
||||
|
||||
initCanDeleteProcessing(model, version);
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFolderBridge::initCanDeleteProcessing(LLInventoryModel* model, S32 version)
|
||||
{
|
||||
if (mCanDeleteFolderState == CDS_DONE
|
||||
|| mInProgressVersion != version)
|
||||
{
|
||||
if (get_is_category_removable(model, mUUID))
|
||||
{
|
||||
// init recursive check of content
|
||||
mInProgressVersion = version;
|
||||
mCanCut = true;
|
||||
mCanDelete = true;
|
||||
mCanDeleteFolderState = CDS_INIT_FOLDER_CHECK;
|
||||
mFoldersToCheck.clear();
|
||||
mItemsToCheck.clear();
|
||||
gIdleCallbacks.addFunction(onCanDeleteIdle, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no check needed
|
||||
mCanDelete = false;
|
||||
mCanCut = false;
|
||||
mLastCheckedVersion = version;
|
||||
mCanDeleteFolderState = CDS_DONE;
|
||||
mFoldersToCheck.clear();
|
||||
mItemsToCheck.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFolderBridge::completeDeleteProcessing()
|
||||
{
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
LLViewerInventoryCategory* category = model ? (LLViewerInventoryCategory*)model->getCategory(mUUID) : nullptr;
|
||||
if (model && category && category->getVersion() == mInProgressVersion)
|
||||
{
|
||||
mLastCheckedVersion = mInProgressVersion;
|
||||
mCanDeleteFolderState = CDS_DONE;
|
||||
gIdleCallbacks.deleteFunction(onCanDeleteIdle, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCanDelete = false;
|
||||
mCanCut = false;
|
||||
mLastCheckedVersion = LLViewerInventoryCategory::VERSION_UNKNOWN;
|
||||
mCanDeleteFolderState = CDS_DONE;
|
||||
}
|
||||
|
||||
if (mRoot)
|
||||
{
|
||||
mRoot->updateMenu();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// +=================================================+
|
||||
// | LLMarketplaceFolderBridge |
|
||||
|
|
@ -4937,9 +5106,7 @@ LLUIImagePtr LLMarketplaceFolderBridge::getMarketplaceFolderIcon(BOOL is_open) c
|
|||
|
||||
std::string LLMarketplaceFolderBridge::getLabelSuffix() const
|
||||
{
|
||||
static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f);
|
||||
|
||||
if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay())
|
||||
if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= FOLDER_LOADING_MESSAGE_DELAY)
|
||||
{
|
||||
return llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str());
|
||||
}
|
||||
|
|
@ -5057,6 +5224,27 @@ void drop_to_favorites_cb(const LLUUID& id, LLPointer<LLInventoryCallback> cb1,
|
|||
cb2->fire(id);
|
||||
}
|
||||
|
||||
LLFolderBridge::LLFolderBridge(LLInventoryPanel* inventory,
|
||||
LLFolderView* root,
|
||||
const LLUUID& uuid)
|
||||
: LLInvFVBridge(inventory, root, uuid)
|
||||
, mCallingCards(FALSE)
|
||||
, mWearables(FALSE)
|
||||
, mIsLoading(false)
|
||||
, mShowDescendantsCount(false)
|
||||
, mCanDeleteFolderState(CDS_DONE)
|
||||
, mLastCheckedVersion(S32_MIN)
|
||||
, mInProgressVersion(S32_MIN)
|
||||
, mCanDelete(false)
|
||||
, mCanCut(false)
|
||||
{
|
||||
}
|
||||
|
||||
LLFolderBridge::~LLFolderBridge()
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(onCanDeleteIdle, this);
|
||||
}
|
||||
|
||||
void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item, LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
// use callback to rearrange favorite landmarks after adding
|
||||
|
|
@ -6649,6 +6837,26 @@ LLInventoryObject* LLObjectBridge::getObject() const
|
|||
return object;
|
||||
}
|
||||
|
||||
LLViewerInventoryItem* LLObjectBridge::getItem() const
|
||||
{
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if (model)
|
||||
{
|
||||
return model->getItem(mUUID);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory* LLObjectBridge::getCategory() const
|
||||
{
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if (model)
|
||||
{
|
||||
return model->getCategory(mUUID);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ public:
|
|||
virtual BOOL isItemRenameable() const { return TRUE; }
|
||||
virtual BOOL isMultiPreviewAllowed() { return TRUE; }
|
||||
//virtual BOOL renameItem(const std::string& new_name) {}
|
||||
virtual BOOL isItemRemovable() const;
|
||||
virtual BOOL isItemRemovable(bool check_worn = true) const;
|
||||
virtual BOOL isItemMovable() const;
|
||||
virtual BOOL isItemInTrash() const;
|
||||
virtual bool isItemInOutfits() const;
|
||||
|
|
@ -162,6 +162,9 @@ protected:
|
|||
virtual void addLinkReplaceMenuOption(menuentry_vec_t& items,
|
||||
menuentry_vec_t& disabled_items);
|
||||
|
||||
virtual bool canMenuDelete();
|
||||
virtual bool canMenuCut();
|
||||
|
||||
protected:
|
||||
LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid);
|
||||
|
||||
|
|
@ -272,14 +275,10 @@ class LLFolderBridge : public LLInvFVBridge
|
|||
public:
|
||||
LLFolderBridge(LLInventoryPanel* inventory,
|
||||
LLFolderView* root,
|
||||
const LLUUID& uuid)
|
||||
: LLInvFVBridge(inventory, root, uuid),
|
||||
mCallingCards(FALSE),
|
||||
mWearables(FALSE),
|
||||
mIsLoading(false),
|
||||
mShowDescendantsCount(false)
|
||||
{}
|
||||
|
||||
const LLUUID& uuid);
|
||||
|
||||
~LLFolderBridge();
|
||||
|
||||
BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL is_link = FALSE, BOOL user_confirm = TRUE, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item);
|
||||
|
|
@ -321,7 +320,7 @@ public:
|
|||
void* cargo_data,
|
||||
std::string& tooltip_msg);
|
||||
|
||||
virtual BOOL isItemRemovable() const;
|
||||
virtual BOOL isItemRemovable(bool check_worn = true) const;
|
||||
virtual BOOL isItemMovable() const ;
|
||||
virtual BOOL isUpToDate() const;
|
||||
virtual bool isItemCopyable(bool can_copy_as_link = true) const;
|
||||
|
|
@ -392,6 +391,31 @@ protected:
|
|||
LLTimer mTimeSinceRequestStart;
|
||||
std::string mMessage;
|
||||
LLRootHandle<LLFolderBridge> mHandle;
|
||||
|
||||
private:
|
||||
// checking if folder is cutable or deletable is expensive,
|
||||
// cache values and split check over frames
|
||||
static void onCanDeleteIdle(void* user_data);
|
||||
void initCanDeleteProcessing(LLInventoryModel* model, S32 version);
|
||||
void completeDeleteProcessing();
|
||||
bool canMenuDelete();
|
||||
bool canMenuCut();
|
||||
|
||||
enum ECanDeleteState
|
||||
{
|
||||
CDS_INIT_FOLDER_CHECK,
|
||||
CDS_PROCESSING_ITEMS,
|
||||
CDS_PROCESSING_FOLDERS,
|
||||
CDS_DONE,
|
||||
};
|
||||
|
||||
ECanDeleteState mCanDeleteFolderState;
|
||||
LLInventoryModel::cat_array_t mFoldersToCheck;
|
||||
LLInventoryModel::item_array_t mItemsToCheck;
|
||||
S32 mLastCheckedVersion;
|
||||
S32 mInProgressVersion;
|
||||
bool mCanDelete;
|
||||
bool mCanCut;
|
||||
};
|
||||
|
||||
class LLTextureBridge : public LLItemBridge
|
||||
|
|
@ -524,6 +548,8 @@ public:
|
|||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
virtual BOOL renameItem(const std::string& new_name);
|
||||
LLInventoryObject* getObject() const;
|
||||
LLViewerInventoryItem* getItem() const;
|
||||
LLViewerInventoryCategory* getCategory() const;
|
||||
protected:
|
||||
static LLUUID sContextMenuItemID; // Only valid while the context menu is open.
|
||||
U32 mAttachPt;
|
||||
|
|
|
|||
|
|
@ -579,9 +579,8 @@ BOOL get_is_parent_to_worn_item(const LLUUID& id)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL get_is_item_worn(const LLUUID& id)
|
||||
BOOL get_is_item_worn(const LLUUID& id, const LLViewerInventoryItem* item)
|
||||
{
|
||||
const LLViewerInventoryItem* item = gInventory.getItem(id);
|
||||
if (!item)
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -619,6 +618,21 @@ BOOL get_is_item_worn(const LLUUID& id)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL get_is_item_worn(const LLUUID& id)
|
||||
{
|
||||
const LLViewerInventoryItem* item = gInventory.getItem(id);
|
||||
return get_is_item_worn(id, item);
|
||||
}
|
||||
|
||||
BOOL get_is_item_worn(const LLViewerInventoryItem* item)
|
||||
{
|
||||
if (!item)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return get_is_item_worn(item->getUUID(), item);
|
||||
}
|
||||
|
||||
BOOL get_can_item_be_worn(const LLUUID& id)
|
||||
{
|
||||
const LLViewerInventoryItem* item = gInventory.getItem(id);
|
||||
|
|
@ -682,39 +696,39 @@ BOOL get_can_item_be_worn(const LLUUID& id)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
|
||||
bool get_is_item_removable(const LLInventoryModel* model, const LLUUID& id, bool check_worn)
|
||||
{
|
||||
if (!model)
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't delete an item that's in the library.
|
||||
if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable delete from COF folder; have users explicitly choose "detach/take off",
|
||||
// unless the item is not worn but in the COF (i.e. is bugged).
|
||||
if (LLAppearanceMgr::instance().getIsProtectedCOFItem(id))
|
||||
const LLViewerInventoryItem* obj = model->getItem(id);
|
||||
if (LLAppearanceMgr::instance().getIsProtectedCOFItem(obj))
|
||||
{
|
||||
if (get_is_item_worn(id))
|
||||
if (get_is_item_worn(id, obj))
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const LLInventoryObject *obj = model->getItem(id);
|
||||
if (obj && obj->getIsLinkType())
|
||||
{
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
if (get_is_item_worn(id))
|
||||
if (check_worn && get_is_item_worn(id, obj))
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_is_item_editable(const LLUUID& inv_item_id)
|
||||
|
|
@ -805,6 +819,74 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUID& folder_id, bool check_worn)
|
||||
{
|
||||
if (!get_is_category_removable(model, folder_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
model->collectDescendents(
|
||||
folder_id,
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH);
|
||||
|
||||
if (check_worn)
|
||||
{
|
||||
for (LLInventoryModel::item_array_t::value_type& item : item_array)
|
||||
{
|
||||
// Disable delete/cut from COF folder; have users explicitly choose "detach/take off",
|
||||
// unless the item is not worn but in the COF (i.e. is bugged).
|
||||
if (item)
|
||||
{
|
||||
if (LLAppearanceMgr::instance().getIsProtectedCOFItem(item))
|
||||
{
|
||||
if (get_is_item_worn(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!item->getIsLinkType() && get_is_item_worn(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
|
||||
LLViewerInventoryCategory* outfit_linked_category = base_outfit_link ? base_outfit_link->getLinkedCategory() : nullptr;
|
||||
for (LLInventoryModel::cat_array_t::value_type& cat : cat_array)
|
||||
{
|
||||
const LLFolderType::EType folder_type = cat->getPreferredType();
|
||||
if (LLFolderType::lookupIsProtectedType(folder_type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't delete the outfit that is currently being worn.
|
||||
if (folder_type == LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
if (cat == outfit_linked_category)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
|
||||
{
|
||||
if (!model)
|
||||
|
|
@ -2759,7 +2841,7 @@ bool LLFindNonRemovableObjects::operator()(LLInventoryCategory* cat, LLInventory
|
|||
{
|
||||
if (item)
|
||||
{
|
||||
return !get_is_item_removable(&gInventory, item->getUUID());
|
||||
return !get_is_item_removable(&gInventory, item->getUUID(), true);
|
||||
}
|
||||
if (cat)
|
||||
{
|
||||
|
|
@ -3024,6 +3106,8 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
|
|||
{
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
bool marketplacelistings_item = false;
|
||||
bool has_worn = false;
|
||||
bool needs_replacement = false;
|
||||
LLAllDescendentsPassedFilter f;
|
||||
for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it)
|
||||
{
|
||||
|
|
@ -3032,14 +3116,69 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
|
|||
folder->applyFunctorRecursively(f);
|
||||
}
|
||||
LLFolderViewModelItemInventory * viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*it)->getViewModelItem());
|
||||
if (viewModel && gInventory.isObjectDescendentOf(viewModel->getUUID(), marketplacelistings_id))
|
||||
LLUUID obj_id = viewModel->getUUID();
|
||||
if (viewModel && gInventory.isObjectDescendentOf(obj_id, marketplacelistings_id))
|
||||
{
|
||||
marketplacelistings_item = true;
|
||||
break;
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(obj_id);
|
||||
if (cat)
|
||||
{
|
||||
LLInventoryModel::cat_array_t categories;
|
||||
LLInventoryModel::item_array_t items;
|
||||
|
||||
gInventory.collectDescendents(obj_id, categories, items, FALSE);
|
||||
|
||||
for (LLInventoryModel::item_array_t::value_type& item : items)
|
||||
{
|
||||
if (get_is_item_worn(item))
|
||||
{
|
||||
has_worn = true;
|
||||
LLWearableType::EType type = item->getWearableType();
|
||||
if (type == LLWearableType::WT_SHAPE
|
||||
|| type == LLWearableType::WT_SKIN
|
||||
|| type == LLWearableType::WT_HAIR
|
||||
|| type == LLWearableType::WT_EYES)
|
||||
{
|
||||
needs_replacement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needs_replacement)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
LLViewerInventoryItem* item = gInventory.getItem(obj_id);
|
||||
if (item && get_is_item_worn(item))
|
||||
{
|
||||
has_worn = true;
|
||||
LLWearableType::EType type = item->getWearableType();
|
||||
if (type == LLWearableType::WT_SHAPE
|
||||
|| type == LLWearableType::WT_SKIN
|
||||
|| type == LLWearableType::WT_HAIR
|
||||
|| type == LLWearableType::WT_EYES)
|
||||
{
|
||||
needs_replacement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fall through to the generic confirmation if the user choose to ignore the specialized one
|
||||
if ( (!f.allDescendentsPassedFilter()) && !marketplacelistings_item && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) )
|
||||
if (needs_replacement)
|
||||
{
|
||||
LLNotificationsUtil::add("CantDeleteRequiredClothing");
|
||||
}
|
||||
else if (has_worn)
|
||||
{
|
||||
LLSD payload;
|
||||
payload["has_worn"] = true;
|
||||
LLNotificationsUtil::add("DeleteWornItems", LLSD(), payload, boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
|
||||
}
|
||||
else if ( (!f.allDescendentsPassedFilter()) && !marketplacelistings_item && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) )
|
||||
{
|
||||
LLNotificationsUtil::add("DeleteFilteredItems", LLSD(), LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
|
||||
}
|
||||
|
|
@ -3362,11 +3501,81 @@ void LLInventoryAction::onItemsRemovalConfirmation(const LLSD& notification, con
|
|||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
if (option == 0 && !root.isDead() && !root.get()->isDead())
|
||||
{
|
||||
bool has_worn = notification["payload"]["has_worn"].asBoolean();
|
||||
LLFolderView* folder_root = root.get();
|
||||
//Need to remove item from DND before item is removed from root folder view
|
||||
//because once removed from root folder view the item is no longer a selected item
|
||||
removeItemFromDND(folder_root);
|
||||
folder_root->removeSelectedItems();
|
||||
|
||||
// removeSelectedItems will change selection, collect worn items beforehand
|
||||
uuid_vec_t worn;
|
||||
uuid_vec_t item_deletion_list;
|
||||
uuid_vec_t cat_deletion_list;
|
||||
if (has_worn)
|
||||
{
|
||||
//Get selected items
|
||||
LLFolderView::selected_items_t selectedItems = folder_root->getSelectedItems();
|
||||
|
||||
//If user is in DND and deletes item, make sure the notification is not displayed by removing the notification
|
||||
//from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification.
|
||||
for (LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
|
||||
{
|
||||
LLFolderViewModelItemInventory* viewModel = dynamic_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem());
|
||||
|
||||
LLUUID obj_id = viewModel->getUUID();
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(obj_id);
|
||||
bool cat_has_worn = false;
|
||||
if (cat)
|
||||
{
|
||||
LLInventoryModel::cat_array_t categories;
|
||||
LLInventoryModel::item_array_t items;
|
||||
|
||||
gInventory.collectDescendents(obj_id, categories, items, FALSE);
|
||||
|
||||
for (LLInventoryModel::item_array_t::value_type& item : items)
|
||||
{
|
||||
if (get_is_item_worn(item))
|
||||
{
|
||||
worn.push_back(item->getUUID());
|
||||
cat_has_worn = true;
|
||||
}
|
||||
}
|
||||
if (cat_has_worn)
|
||||
{
|
||||
cat_deletion_list.push_back(obj_id);
|
||||
}
|
||||
}
|
||||
LLViewerInventoryItem* item = gInventory.getItem(obj_id);
|
||||
if (item && get_is_item_worn(item))
|
||||
{
|
||||
worn.push_back(obj_id);
|
||||
item_deletion_list.push_back(obj_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// removeSelectedItems will check if items are worn before deletion,
|
||||
// don't 'unwear' yet to prevent race conditions from unwearing
|
||||
// and removing simultaneously
|
||||
folder_root->removeSelectedItems();
|
||||
|
||||
// unwear then delete the rest
|
||||
if (!worn.empty())
|
||||
{
|
||||
// should fire once after every item gets detached
|
||||
LLAppearanceMgr::instance().removeItemsFromAvatar(worn,
|
||||
[item_deletion_list, cat_deletion_list]()
|
||||
{
|
||||
for (const LLUUID& id : item_deletion_list)
|
||||
{
|
||||
remove_inventory_item(id, NULL);
|
||||
}
|
||||
for (const LLUUID& id : cat_deletion_list)
|
||||
{
|
||||
remove_inventory_category(id, NULL);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update the marketplace listings that have been affected by the operation
|
||||
updateMarketplaceFolders();
|
||||
|
|
|
|||
|
|
@ -47,17 +47,19 @@ BOOL get_is_parent_to_worn_item(const LLUUID& id);
|
|||
|
||||
// Is this item or its baseitem is worn, attached, etc...
|
||||
BOOL get_is_item_worn(const LLUUID& id);
|
||||
BOOL get_is_item_worn(const LLViewerInventoryItem* item);
|
||||
|
||||
// Could this item be worn (correct type + not already being worn)
|
||||
BOOL get_can_item_be_worn(const LLUUID& id);
|
||||
|
||||
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id);
|
||||
bool get_is_item_removable(const LLInventoryModel* model, const LLUUID& id, bool check_worn);
|
||||
|
||||
// Performs the appropiate edit action (if one exists) for this item
|
||||
bool get_is_item_editable(const LLUUID& inv_item_id);
|
||||
void handle_item_edit(const LLUUID& inv_item_id);
|
||||
|
||||
BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id);
|
||||
bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUID& folder_id, bool check_worn);
|
||||
|
||||
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id);
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
static LLPanelInjector<LLInventoryGallery> t_inventory_gallery("inventory_gallery");
|
||||
|
||||
const S32 GALLERY_ITEMS_PER_ROW_MIN = 2;
|
||||
const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value immediately
|
||||
|
||||
// Helper dnd functions
|
||||
BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, BOOL drop, std::string& tooltip_msg, BOOL is_link);
|
||||
|
|
@ -106,6 +107,7 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p)
|
|||
mGalleryWidthFactor(p.gallery_width_factor),
|
||||
mIsInitialized(false),
|
||||
mRootDirty(false),
|
||||
mLoadThumbnailsImmediately(true),
|
||||
mNeedsArrange(false),
|
||||
mSearchType(LLInventoryFilter::SEARCHTYPE_NAME),
|
||||
mSortOrder(LLInventoryFilter::SO_DATE)
|
||||
|
|
@ -540,6 +542,12 @@ void LLInventoryGallery::addToGallery(LLInventoryGalleryItem* item)
|
|||
int n_prev = n - 1;
|
||||
int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1;
|
||||
|
||||
// Avoid loading too many items.
|
||||
// Intent is for small folders to display all content fast
|
||||
// and for large folders to load content mostly as needed
|
||||
// Todo: ideally needs to unload images outside visible area
|
||||
mLoadThumbnailsImmediately = mItemsAddedCount < FAST_LOAD_THUMBNAIL_TRSHOLD;
|
||||
|
||||
bool add_row = row_count != row_count_prev;
|
||||
int pos = 0;
|
||||
if (add_row)
|
||||
|
|
@ -573,6 +581,8 @@ void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item, boo
|
|||
mItemsAddedCount--;
|
||||
mIndexToItemMap.erase(mItemsAddedCount);
|
||||
|
||||
mLoadThumbnailsImmediately = mItemsAddedCount < FAST_LOAD_THUMBNAIL_TRSHOLD;
|
||||
|
||||
bool remove_row = row_count != row_count_prev;
|
||||
removeFromLastRow(mItems[mItemsAddedCount]);
|
||||
mItems.pop_back();
|
||||
|
|
@ -636,6 +646,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L
|
|||
gitem->setUUID(item_id);
|
||||
gitem->setGallery(this);
|
||||
gitem->setType(type, inventory_type, flags, is_link);
|
||||
gitem->setLoadImmediately(mLoadThumbnailsImmediately);
|
||||
gitem->setThumbnail(thumbnail_id);
|
||||
gitem->setWorn(is_worn);
|
||||
gitem->setCreatorName(get_searchable_creator_name(&gInventory, item_id));
|
||||
|
|
@ -997,6 +1008,7 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id)
|
|||
|
||||
if (mItemMap[item_id])
|
||||
{
|
||||
mItemMap[item_id]->setLoadImmediately(mLoadThumbnailsImmediately);
|
||||
mItemMap[item_id]->setThumbnail(thumbnail_id);
|
||||
|
||||
bool passes_filter = checkAgainstFilters(mItemMap[item_id], mFilterSubString);
|
||||
|
|
@ -1423,7 +1435,7 @@ void LLInventoryGallery::onFocusReceived()
|
|||
LLInventoryGalleryItem* focus_item = NULL;
|
||||
for (const LLUUID& id : mSelectedItemIDs)
|
||||
{
|
||||
if (mItemMap[id])
|
||||
if (mItemMap[id] && !mItemMap[id]->isHidden())
|
||||
{
|
||||
focus_item = mItemMap[id];
|
||||
focus_item->setSelected(true);
|
||||
|
|
@ -1656,6 +1668,45 @@ void LLInventoryGallery::cut()
|
|||
mFilterSubString.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool is_category_removable(const LLUUID& folder_id, bool check_worn)
|
||||
{
|
||||
if (!get_is_category_removable(&gInventory, folder_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// check children
|
||||
LLInventoryModel::cat_array_t* cat_array;
|
||||
LLInventoryModel::item_array_t* item_array;
|
||||
gInventory.getDirectDescendentsOf(folder_id, cat_array, item_array);
|
||||
|
||||
for (LLInventoryModel::item_array_t::value_type& item : *item_array)
|
||||
{
|
||||
if (!get_is_item_removable(&gInventory, item->getUUID(), check_worn))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (LLInventoryModel::cat_array_t::value_type& cat : *cat_array)
|
||||
{
|
||||
if (!is_category_removable(cat->getUUID(), check_worn))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLInventoryGallery::canCut() const
|
||||
{
|
||||
if (!getVisible() || !getEnabled() || mSelectedItemIDs.empty())
|
||||
|
|
@ -1668,12 +1719,12 @@ BOOL LLInventoryGallery::canCut() const
|
|||
LLViewerInventoryCategory* cat = gInventory.getCategory(id);
|
||||
if (cat)
|
||||
{
|
||||
if (!get_is_category_removable(&gInventory, id))
|
||||
if (!get_is_category_and_children_removable(&gInventory, id, true))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (!get_is_item_removable(&gInventory, id))
|
||||
else if (!get_is_item_removable(&gInventory, id, true))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -1852,42 +1903,149 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response
|
|||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
if (option == 0)
|
||||
{
|
||||
for (const LLUUID& id : selected_ids)
|
||||
bool has_worn = notification["payload"]["has_worn"].asBoolean();
|
||||
uuid_vec_t worn;
|
||||
uuid_vec_t item_deletion_list;
|
||||
uuid_vec_t cat_deletion_list;
|
||||
for (const LLUUID& obj_id : selected_ids)
|
||||
{
|
||||
LLInventoryObject* obj = gInventory.getObject(id);
|
||||
if (!obj)
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(obj_id);
|
||||
if (cat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (obj->getType() == LLAssetType::AT_CATEGORY)
|
||||
{
|
||||
if (get_is_category_removable(&gInventory, id))
|
||||
bool cat_has_worn = false;
|
||||
if (has_worn)
|
||||
{
|
||||
gInventory.removeCategory(id);
|
||||
LLInventoryModel::cat_array_t categories;
|
||||
LLInventoryModel::item_array_t items;
|
||||
|
||||
gInventory.collectDescendents(obj_id, categories, items, FALSE);
|
||||
|
||||
for (LLInventoryModel::item_array_t::value_type& item : items)
|
||||
{
|
||||
if (get_is_item_worn(item))
|
||||
{
|
||||
worn.push_back(item->getUUID());
|
||||
cat_has_worn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cat_has_worn)
|
||||
{
|
||||
cat_deletion_list.push_back(obj_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
gInventory.removeCategory(obj_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
LLViewerInventoryItem* item = gInventory.getItem(obj_id);
|
||||
if (item)
|
||||
{
|
||||
if (get_is_item_removable(&gInventory, id))
|
||||
if (has_worn && get_is_item_worn(item))
|
||||
{
|
||||
gInventory.removeItem(id);
|
||||
worn.push_back(item->getUUID());
|
||||
item_deletion_list.push_back(item->getUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
gInventory.removeItem(obj_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!worn.empty())
|
||||
{
|
||||
// should fire once after every item gets detached
|
||||
LLAppearanceMgr::instance().removeItemsFromAvatar(worn,
|
||||
[item_deletion_list, cat_deletion_list]()
|
||||
{
|
||||
for (const LLUUID& id : item_deletion_list)
|
||||
{
|
||||
remove_inventory_item(id, NULL);
|
||||
}
|
||||
for (const LLUUID& id : cat_deletion_list)
|
||||
{
|
||||
remove_inventory_category(id, NULL);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryGallery::deleteSelection()
|
||||
{
|
||||
if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session
|
||||
bool has_worn = false;
|
||||
bool needs_replacement = false;
|
||||
for (const LLUUID& id : mSelectedItemIDs)
|
||||
{
|
||||
LLNotifications::instance().setIgnored("DeleteItems", false);
|
||||
LLInventoryAction::sDeleteConfirmationDisplayed = true;
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(id);
|
||||
if (cat)
|
||||
{
|
||||
LLInventoryModel::cat_array_t categories;
|
||||
LLInventoryModel::item_array_t items;
|
||||
|
||||
gInventory.collectDescendents(id, categories, items, FALSE);
|
||||
|
||||
for (LLInventoryModel::item_array_t::value_type& item : items)
|
||||
{
|
||||
if (get_is_item_worn(item))
|
||||
{
|
||||
has_worn = true;
|
||||
LLWearableType::EType type = item->getWearableType();
|
||||
if (type == LLWearableType::WT_SHAPE
|
||||
|| type == LLWearableType::WT_SKIN
|
||||
|| type == LLWearableType::WT_HAIR
|
||||
|| type == LLWearableType::WT_EYES)
|
||||
{
|
||||
needs_replacement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needs_replacement)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerInventoryItem* item = gInventory.getItem(id);
|
||||
if (item && get_is_item_worn(item))
|
||||
{
|
||||
has_worn = true;
|
||||
LLWearableType::EType type = item->getWearableType();
|
||||
if (type == LLWearableType::WT_SHAPE
|
||||
|| type == LLWearableType::WT_SKIN
|
||||
|| type == LLWearableType::WT_HAIR
|
||||
|| type == LLWearableType::WT_EYES)
|
||||
{
|
||||
needs_replacement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLSD args;
|
||||
args["QUESTION"] = LLTrans::getString("DeleteItem");
|
||||
LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs));
|
||||
if (needs_replacement)
|
||||
{
|
||||
LLNotificationsUtil::add("CantDeleteRequiredClothing");
|
||||
}
|
||||
else if (has_worn)
|
||||
{
|
||||
LLSD payload;
|
||||
payload["has_worn"] = true;
|
||||
LLNotificationsUtil::add("DeleteWornItems", LLSD(), payload, boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session
|
||||
{
|
||||
LLNotifications::instance().setIgnored("DeleteItems", false);
|
||||
LLInventoryAction::sDeleteConfirmationDisplayed = true;
|
||||
}
|
||||
|
||||
LLSD args;
|
||||
args["QUESTION"] = LLTrans::getString("DeleteItem");
|
||||
LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs));
|
||||
}
|
||||
}
|
||||
|
||||
bool LLInventoryGallery::canDeleteSelection()
|
||||
|
|
@ -1913,7 +2071,7 @@ bool LLInventoryGallery::canDeleteSelection()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else if (!get_is_item_removable(&gInventory, id))
|
||||
else if (!get_is_item_removable(&gInventory, id, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2557,6 +2715,7 @@ BOOL LLInventoryGalleryItem::postBuild()
|
|||
{
|
||||
mNameText = getChild<LLTextBox>("item_name");
|
||||
mTextBgPanel = getChild<LLPanel>("text_bg_panel");
|
||||
mThumbnailCtrl = getChild<LLThumbnailCtrl>("preview_thumbnail");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -2632,14 +2791,19 @@ void LLInventoryGalleryItem::setThumbnail(LLUUID id)
|
|||
mDefaultImage = id.isNull();
|
||||
if(mDefaultImage)
|
||||
{
|
||||
getChild<LLThumbnailCtrl>("preview_thumbnail")->clearTexture();
|
||||
mThumbnailCtrl->clearTexture();
|
||||
}
|
||||
else
|
||||
{
|
||||
getChild<LLThumbnailCtrl>("preview_thumbnail")->setValue(id);
|
||||
mThumbnailCtrl->setValue(id);
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryGalleryItem::setLoadImmediately(bool val)
|
||||
{
|
||||
mThumbnailCtrl->setInitImmediately(val);
|
||||
}
|
||||
|
||||
void LLInventoryGalleryItem::draw()
|
||||
{
|
||||
if (isFadeItem())
|
||||
|
|
@ -2654,7 +2818,7 @@ void LLInventoryGalleryItem::draw()
|
|||
|
||||
// Draw border
|
||||
LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white);
|
||||
LLRect border = getChildView("preview_thumbnail")->getRect();
|
||||
LLRect border = mThumbnailCtrl->getRect();
|
||||
border.mRight = border.mRight + 1;
|
||||
border.mTop = border.mTop + 1;
|
||||
gl_rect_2d(border, border_color.get(), FALSE);
|
||||
|
|
@ -2876,7 +3040,7 @@ void LLInventoryGalleryItem::updateNameText()
|
|||
mNameText->setFont(getTextFont());
|
||||
mNameText->setText(mItemName + mPermSuffix + mWornSuffix);
|
||||
mNameText->setToolTip(mItemName + mPermSuffix + mWornSuffix);
|
||||
getChild<LLThumbnailCtrl>("preview_thumbnail")->setToolTip(mItemName + mPermSuffix + mWornSuffix);
|
||||
mThumbnailCtrl->setToolTip(mItemName + mPermSuffix + mWornSuffix);
|
||||
}
|
||||
|
||||
bool LLInventoryGalleryItem::isFadeItem()
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class LLInventoryGalleryItem;
|
|||
class LLScrollContainer;
|
||||
class LLTextBox;
|
||||
class LLThumbnailsObserver;
|
||||
class LLThumbnailCtrl;
|
||||
class LLGalleryGestureObserver;
|
||||
|
||||
class LLInventoryGalleryContextMenu;
|
||||
|
|
@ -246,6 +247,7 @@ private:
|
|||
int mRowCount;
|
||||
int mItemsAddedCount;
|
||||
bool mGalleryCreated;
|
||||
bool mLoadThumbnailsImmediately;
|
||||
bool mNeedsArrange;
|
||||
|
||||
/* Params */
|
||||
|
|
@ -342,6 +344,7 @@ public:
|
|||
LLAssetType::EType getAssetType() { return mType; }
|
||||
void setThumbnail(LLUUID id);
|
||||
void setGallery(LLInventoryGallery* gallery) { mGallery = gallery; }
|
||||
void setLoadImmediately(bool val);
|
||||
bool isFolder() { return mIsFolder; }
|
||||
bool isLink() { return mIsLink; }
|
||||
EInventorySortGroup getSortGroup() { return mSortGroup; }
|
||||
|
|
@ -354,6 +357,7 @@ private:
|
|||
LLUUID mUUID;
|
||||
LLTextBox* mNameText;
|
||||
LLPanel* mTextBgPanel;
|
||||
LLThumbnailCtrl* mThumbnailCtrl;
|
||||
bool mSelected;
|
||||
bool mWorn;
|
||||
bool mDefaultImage;
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
}
|
||||
}
|
||||
items.push_back(std::string("Purge Item"));
|
||||
if (is_folder && !get_is_category_removable(&gInventory, selected_id))
|
||||
if (is_folder && !get_is_category_and_children_removable(&gInventory, selected_id, true))
|
||||
{
|
||||
disabled_items.push_back(std::string("Purge Item"));
|
||||
}
|
||||
|
|
@ -542,11 +542,16 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
}
|
||||
items.push_back(std::string("Cut"));
|
||||
items.push_back(std::string("Delete"));
|
||||
if(!get_is_category_removable(&gInventory, selected_id))
|
||||
|
||||
if(!get_is_category_and_children_removable(&gInventory, selected_id, false))
|
||||
{
|
||||
disabled_items.push_back(std::string("Delete"));
|
||||
disabled_items.push_back(std::string("Cut"));
|
||||
}
|
||||
else if (!get_is_category_and_children_removable(&gInventory, selected_id, true))
|
||||
{
|
||||
disabled_items.push_back(std::string("Cut"));
|
||||
}
|
||||
|
||||
if(!is_inbox)
|
||||
{
|
||||
|
|
@ -577,11 +582,15 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
{
|
||||
items.push_back(std::string("Delete"));
|
||||
}
|
||||
if(!get_is_item_removable(&gInventory, selected_id))
|
||||
if (!get_is_item_removable(&gInventory, selected_id, false))
|
||||
{
|
||||
disabled_items.push_back(std::string("Delete"));
|
||||
disabled_items.push_back(std::string("Cut"));
|
||||
}
|
||||
else if(!get_is_item_removable(&gInventory, selected_id, true))
|
||||
{
|
||||
disabled_items.push_back(std::string("Cut"));
|
||||
}
|
||||
|
||||
if (selected_item && (selected_item->getInventoryType() != LLInventoryType::IT_CALLINGCARD) && !is_inbox && selected_item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ void LLInventoryItemsList::refresh()
|
|||
case REFRESH_LIST_SORT:
|
||||
{
|
||||
// Filter, sort, rearrange and notify parent about shape changes
|
||||
filterItems();
|
||||
filterItems(true, true);
|
||||
|
||||
if (mAddedItems.size() == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,20 +51,20 @@ public:
|
|||
/**
|
||||
* Let list know items need to be refreshed in next doIdle()
|
||||
*/
|
||||
void setNeedsRefresh(bool needs_refresh){ mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; }
|
||||
void setNeedsRefresh(bool needs_refresh) { mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; }
|
||||
|
||||
U32 getNeedsRefresh(){ return mRefreshState; }
|
||||
U32 getNeedsRefresh() { return mRefreshState; }
|
||||
|
||||
/**
|
||||
* Sets the flag indicating that the list needs to be refreshed even if it is
|
||||
* not currently visible.
|
||||
*/
|
||||
void setForceRefresh(bool force_refresh){ mForceRefresh = force_refresh; }
|
||||
void setForceRefresh(bool force_refresh) { mForceRefresh = force_refresh; }
|
||||
|
||||
/**
|
||||
* If refreshes when invisible.
|
||||
*/
|
||||
bool getForceRefresh(){ return mForceRefresh; }
|
||||
bool getForceRefresh() { return mForceRefresh; }
|
||||
|
||||
virtual bool selectItemByValue(const LLSD& value, bool select = true);
|
||||
|
||||
|
|
|
|||
|
|
@ -1887,46 +1887,52 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
|
|||
}
|
||||
|
||||
//static
|
||||
void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const LLUUID& obj_id, BOOL use_main_panel, BOOL take_keyboard_focus, BOOL reset_filter)
|
||||
void LLInventoryPanel::openInventoryPanelAndSetSelection(bool auto_open, const LLUUID& obj_id,
|
||||
bool use_main_panel, bool take_keyboard_focus, bool reset_filter)
|
||||
{
|
||||
LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
|
||||
sidepanel_inventory->showInventoryPanel();
|
||||
|
||||
bool in_inbox = (gInventory.isObjectDescendentOf(obj_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX)));
|
||||
|
||||
if (!in_inbox && (use_main_panel || !sidepanel_inventory->getMainInventoryPanel()->isRecentItemsPanelSelected()))
|
||||
LLUUID cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX);
|
||||
bool in_inbox = gInventory.isObjectDescendentOf(obj_id, cat_id);
|
||||
if (!in_inbox && use_main_panel)
|
||||
{
|
||||
sidepanel_inventory->selectAllItemsPanel();
|
||||
}
|
||||
|
||||
LLFloater* inventory_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater();
|
||||
if(!auto_open && inventory_floater && inventory_floater->getVisible())
|
||||
if (!auto_open)
|
||||
{
|
||||
LLSidepanelInventory *inventory_panel = inventory_floater->findChild<LLSidepanelInventory>("main_panel");
|
||||
LLPanelMainInventory* main_panel = inventory_panel->getMainInventoryPanel();
|
||||
if(main_panel->isSingleFolderMode() && main_panel->isGalleryViewMode())
|
||||
LLFloater* inventory_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater();
|
||||
if (inventory_floater && inventory_floater->getVisible())
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Opening gallery panel for item" << obj_id << LL_ENDL;
|
||||
main_panel->setGallerySelection(obj_id);
|
||||
return;
|
||||
LLSidepanelInventory *inventory_panel = inventory_floater->findChild<LLSidepanelInventory>("main_panel");
|
||||
LLPanelMainInventory* main_panel = inventory_panel->getMainInventoryPanel();
|
||||
if (main_panel->isSingleFolderMode() && main_panel->isGalleryViewMode())
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Opening gallery panel for item" << obj_id << LL_ENDL;
|
||||
main_panel->setGallerySelection(obj_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
|
||||
if (main_inventory && main_inventory->isSingleFolderMode()
|
||||
&& use_main_panel)
|
||||
if (use_main_panel)
|
||||
{
|
||||
const LLInventoryObject *obj = gInventory.getObject(obj_id);
|
||||
if (obj)
|
||||
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
|
||||
if (main_inventory && main_inventory->isSingleFolderMode())
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Opening main inventory panel for item" << obj_id << LL_ENDL;
|
||||
main_inventory->setSingleFolderViewRoot(obj->getParentUUID(), false);
|
||||
main_inventory->setGallerySelection(obj_id);
|
||||
return;
|
||||
const LLInventoryObject *obj = gInventory.getObject(obj_id);
|
||||
if (obj)
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Opening main inventory panel for item" << obj_id << LL_ENDL;
|
||||
main_inventory->setSingleFolderViewRoot(obj->getParentUUID(), false);
|
||||
main_inventory->setGallerySelection(obj_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open);
|
||||
|
||||
if (active_panel)
|
||||
{
|
||||
LL_DEBUGS("Messaging", "Inventory") << "Highlighting" << obj_id << LL_ENDL;
|
||||
|
|
@ -1938,11 +1944,8 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
|
|||
|
||||
if (in_inbox)
|
||||
{
|
||||
|
||||
LLInventoryPanel * inventory_panel = NULL;
|
||||
sidepanel_inventory->openInbox();
|
||||
inventory_panel = sidepanel_inventory->getInboxPanel();
|
||||
|
||||
LLInventoryPanel* inventory_panel = sidepanel_inventory->getInboxPanel();
|
||||
if (inventory_panel)
|
||||
{
|
||||
inventory_panel->setSelection(obj_id, take_keyboard_focus);
|
||||
|
|
@ -1967,7 +1970,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
|
|||
|
||||
void LLInventoryPanel::setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id)
|
||||
{
|
||||
|
||||
LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
|
||||
for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
|
||||
{
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue