Merge from q/viewer-release to dessie/viewer-release for 2.1.1 beta 1

master
Kent Quirk 2010-07-30 10:11:55 -04:00
commit 19c0d6d4ea
174 changed files with 2099 additions and 833 deletions

View File

@ -293,7 +293,7 @@ BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp)
dp.unpackU32(mFlags, "flags");
return TRUE;
}
// *TODO: Translate
// *NOTE: result is translated in LLPreviewGesture::getLabel()
std::vector<std::string> LLGestureStepAnimation::getLabel() const
{
std::vector<std::string> strings;
@ -367,7 +367,7 @@ BOOL LLGestureStepSound::deserialize(LLDataPacker& dp)
dp.unpackU32(mFlags, "flags");
return TRUE;
}
// *TODO: Translate
// *NOTE: result is translated in LLPreviewGesture::getLabel()
std::vector<std::string> LLGestureStepSound::getLabel() const
{
std::vector<std::string> strings;
@ -425,7 +425,7 @@ BOOL LLGestureStepChat::deserialize(LLDataPacker& dp)
dp.unpackU32(mFlags, "flags");
return TRUE;
}
// *TODO: Translate
// *NOTE: result is translated in LLPreviewGesture::getLabel()
std::vector<std::string> LLGestureStepChat::getLabel() const
{
std::vector<std::string> strings;
@ -479,7 +479,7 @@ BOOL LLGestureStepWait::deserialize(LLDataPacker& dp)
dp.unpackU32(mFlags, "flags");
return TRUE;
}
// *TODO: Translate
// *NOTE: result is translated in LLPreviewGesture::getLabel()
std::vector<std::string> LLGestureStepWait::getLabel() const
{
std::vector<std::string> strings;

View File

@ -37,16 +37,40 @@
#include <cstdarg>
std::string llformat(const char *fmt, ...)
// common used function with va_list argument
// wrapper for vsnprintf to be called from llformatXXX functions.
static void va_format(std::string& out, const char *fmt, va_list va)
{
char tstr[1024]; /* Flawfinder: ignore */
va_list va;
va_start(va, fmt);
#if LL_WINDOWS
_vsnprintf(tstr, 1024, fmt, va);
#else
vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */
#endif
va_end(va);
return std::string(tstr);
out.assign(tstr);
}
std::string llformat(const char *fmt, ...)
{
std::string res;
va_list va;
va_start(va, fmt);
va_format(res, fmt, va);
va_end(va);
return res;
}
std::string llformat_to_utf8(const char *fmt, ...)
{
std::string res;
va_list va;
va_start(va, fmt);
va_format(res, fmt, va);
va_end(va);
#if LL_WINDOWS
// made converting to utf8. See EXT-8318.
res = ll_convert_string_to_utf8_string(res);
#endif
return res;
}

View File

@ -42,4 +42,8 @@
std::string LL_COMMON_API llformat(const char *fmt, ...);
// the same version as above but ensures that returned string is in utf8 on windows
// to enable correct converting utf8_to_wstring.
std::string LL_COMMON_API llformat_to_utf8(const char *fmt, ...);
#endif // LL_LLFORMAT_H

View File

@ -171,11 +171,6 @@ void LLMD5::update(FILE* file){
}
// MD5 update for istreams.
// Like update for files; see above.
@ -192,9 +187,10 @@ void LLMD5::update(std::istream& stream){
}
void LLMD5::update(const std::string& s)
{
update((unsigned char *)s.c_str(),s.length());
}
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
@ -277,7 +273,7 @@ LLMD5::LLMD5(const unsigned char *s)
finalize();
}
void LLMD5::raw_digest(unsigned char *s)
void LLMD5::raw_digest(unsigned char *s) const
{
if (!finalized)
{
@ -293,7 +289,7 @@ void LLMD5::raw_digest(unsigned char *s)
void LLMD5::hex_digest(char *s)
void LLMD5::hex_digest(char *s) const
{
int i;
@ -319,6 +315,7 @@ void LLMD5::hex_digest(char *s)
std::ostream& operator<<(std::ostream &stream, LLMD5 context)
{
char s[33]; /* Flawfinder: ignore */
@ -327,13 +324,25 @@ std::ostream& operator<<(std::ostream &stream, LLMD5 context)
return stream;
}
bool operator==(const LLMD5& a, const LLMD5& b)
{
unsigned char a_guts[16];
unsigned char b_guts[16];
a.raw_digest(a_guts);
b.raw_digest(b_guts);
if (memcmp(a_guts,b_guts,16)==0)
return true;
else
return false;
}
bool operator!=(const LLMD5& a, const LLMD5& b)
{
return !(a==b);
}
// PRIVATE METHODS:
void LLMD5::init(){
finalized=0; // we just started!
@ -531,3 +540,5 @@ void LLMD5::decode (uint4 *output, const uint1 *input, const uint4 len){
output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
(((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
}

View File

@ -95,6 +95,7 @@ public:
void update (const uint1 *input, const uint4 input_length);
void update (std::istream& stream);
void update (FILE *file);
void update (const std::string& str);
void finalize ();
// constructors for special circumstances. All these constructors finalize
@ -105,12 +106,11 @@ public:
LLMD5 (const unsigned char *string, const unsigned int number);
// methods to acquire finalized result
void raw_digest(unsigned char *array); // provide 16-byte array for binary data
void hex_digest(char *string); // provide 33-byte array for ascii-hex string
void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data
void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string
friend std::ostream& operator<< (std::ostream&, LLMD5 context);
private:
@ -131,4 +131,7 @@ private:
};
LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b);
LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b);
#endif // LL_LLMD5_H

View File

@ -633,14 +633,14 @@ namespace snprintf_hack
}
}
std::string ll_convert_wide_to_string(const wchar_t* in)
std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page)
{
std::string out;
if(in)
{
int len_in = wcslen(in);
int len_out = WideCharToMultiByte(
CP_ACP,
code_page,
0,
in,
len_in,
@ -655,7 +655,7 @@ std::string ll_convert_wide_to_string(const wchar_t* in)
if(pout)
{
WideCharToMultiByte(
CP_ACP,
code_page,
0,
in,
len_in,
@ -669,6 +669,38 @@ std::string ll_convert_wide_to_string(const wchar_t* in)
}
return out;
}
wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page)
{
// From review:
// We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input,
// plus one for a null terminator, and be guaranteed to not overflow.
// Normally, I'd call that sort of thing premature optimization,
// but we *are* seeing string operations taking a bunch of time, especially when constructing widgets.
// int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0);
// reserve place to NULL terminator
int output_str_len = in.length();
wchar_t* w_out = new wchar_t[output_str_len + 1];
memset(w_out, 0, output_str_len + 1);
int real_output_str_len = MultiByteToWideChar (code_page, 0, in.c_str(), in.length(), w_out, output_str_len);
//looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858.
w_out[real_output_str_len] = 0;
return w_out;
}
std::string ll_convert_string_to_utf8_string(const std::string& in)
{
wchar_t* w_mesg = ll_convert_string_to_wide(in, CP_ACP);
std::string out_utf8(ll_convert_wide_to_string(w_mesg, CP_UTF8));
delete[] w_mesg;
return out_utf8;
}
#endif // LL_WINDOWS
long LLStringOps::sPacificTimeOffset = 0;

View File

@ -564,7 +564,20 @@ using snprintf_hack::snprintf;
*
* This replaces the unsafe W2A macro from ATL.
*/
LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in);
LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page);
/**
* Converts a string to wide string.
*
* It will allocate memory for result string with "new []". Don't forget to release it with "delete []".
*/
LL_COMMON_API wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page);
/**
* Converts incoming string into urf8 string
*
*/
LL_COMMON_API std::string ll_convert_string_to_utf8_string(const std::string& in);
//@}
#endif // LL_WINDOWS

View File

@ -364,13 +364,6 @@ U32 LLCurl::Easy::report(CURLcode code)
responseCode = 499;
responseReason = strerror(code) + " : " + mErrorBuffer;
}
if(responseCode >= 300 && responseCode < 400) //redirect
{
char new_url[512] ;
curl_easy_getinfo(mCurlEasyHandle, CURLINFO_REDIRECT_URL, new_url);
responseReason = new_url ; //get the new URL.
}
if (mResponder)
{
@ -469,6 +462,13 @@ void LLCurl::Easy::prepRequest(const std::string& url,
setopt(CURLOPT_HEADERFUNCTION, (void*)&curlHeaderCallback);
setopt(CURLOPT_HEADERDATA, (void*)this);
// Allow up to five redirects
if(responder && responder->followRedir())
{
setopt(CURLOPT_FOLLOWLOCATION, 1);
setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS);
}
setErrorBuffer();
setCA();
@ -1061,3 +1061,4 @@ void LLCurl::cleanupClass()
curl_global_cleanup();
}
const unsigned int LLCurl::MAX_REDIRECTS = 5;

View File

@ -123,6 +123,11 @@ public:
// Used internally to set the url for debugging later.
void setURL(const std::string& url);
virtual bool followRedir()
{
return false;
}
public: /* but not really -- don't touch this */
U32 mReferenceCount;
@ -182,6 +187,7 @@ public:
private:
static std::string sCAPath;
static std::string sCAFile;
static const unsigned int MAX_REDIRECTS;
};
namespace boost

View File

@ -109,11 +109,20 @@ void LLImageGL::checkTexSize(bool forced) const
{
if ((forced || gDebugGL) && mTarget == GL_TEXTURE_2D)
{
{
//check viewport
GLint vp[4] ;
glGetIntegerv(GL_VIEWPORT, vp) ;
llcallstacks << "viewport: " << vp[0] << " : " << vp[1] << " : " << vp[2] << " : " << vp[3] << llcallstacksendl ;
}
GLint texname;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
BOOL error = FALSE;
if (texname != mTexName)
{
llinfos << "Bound: " << texname << " Should bind: " << mTexName << " Default: " << LLImageGL::sDefaultGLTexture->getTexName() << llendl;
error = TRUE;
if (gDebugSession)
{

View File

@ -768,6 +768,17 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
}
return 0;
}
else if(str_action == "deselect_current")
{
// Reset selection to the currently selected tab.
if (mSelectedTab)
{
mSelectedTab->setSelected(false);
mSelectedTab = NULL;
return 1;
}
return 0;
}
}
else if (info.has("scrollToShowRect"))
{
@ -814,6 +825,31 @@ void LLAccordionCtrl::reset ()
mScrollbar->setDocPos(0);
}
void LLAccordionCtrl::expandDefaultTab()
{
if (mAccordionTabs.size() > 0)
{
LLAccordionCtrlTab* tab = mAccordionTabs.front();
if (!tab->getDisplayChildren())
{
tab->setDisplayChildren(true);
}
for (size_t i = 1; i < mAccordionTabs.size(); ++i)
{
tab = mAccordionTabs[i];
if (tab->getDisplayChildren())
{
tab->setDisplayChildren(false);
}
}
arrange();
}
}
void LLAccordionCtrl::sort()
{
if (!mTabComparator)

View File

@ -122,6 +122,7 @@ public:
S32 notifyParent(const LLSD& info);
void reset ();
void expandDefaultTab();
void setComparator(const LLTabComparator* comp) { mTabComparator = comp; }
void sort();
@ -140,6 +141,8 @@ public:
const LLAccordionCtrlTab* getSelectedTab() const { return mSelectedTab; }
bool getFitParent() const {return mFitParent;}
private:
void initNoTabsWidget(const LLTextBox::Params& tb_params);
void updateNoTabsHelpTextVisibility();

View File

@ -33,6 +33,7 @@
#include "linden_common.h"
#include "llaccordionctrltab.h"
#include "llaccordionctrl.h"
#include "lllocalcliprect.h"
#include "llscrollbar.h"
@ -371,9 +372,11 @@ LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)
mHeader = LLUICtrlFactory::create<LLAccordionCtrlTabHeader>(headerParams);
addChild(mHeader, 1);
if (p.selection_enabled)
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this));
if (!p.selection_enabled)
{
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this));
LLFocusableElement::setFocusLostCallback(boost::bind(&LLAccordionCtrlTab::deselectOnFocusLost, this));
}
reshape(100, 200,FALSE);
@ -598,6 +601,15 @@ void LLAccordionCtrlTab::selectOnFocusReceived()
getParent()->notifyParent(LLSD().with("action", "select_current"));
}
void LLAccordionCtrlTab::deselectOnFocusLost()
{
if(getParent()) // A parent may not be set if tabs are added dynamically.
{
getParent()->notifyParent(LLSD().with("action", "deselect_current"));
}
}
S32 LLAccordionCtrlTab::getHeaderHeight()
{
return mHeaderVisible?HEADER_HEIGHT:0;
@ -698,7 +710,7 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
setRect(panel_rect);
}
//LLAccordionCtrl should rearrange accodion tab if one of accordion change its size
//LLAccordionCtrl should rearrange accordion tab if one of accordion change its size
if (getParent()) // A parent may not be set if tabs are added dynamically.
getParent()->notifyParent(info);
return 1;
@ -709,6 +721,27 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
return 1;
}
}
else if (info.has("scrollToShowRect"))
{
LLAccordionCtrl* parent = dynamic_cast<LLAccordionCtrl*>(getParent());
if (parent && parent->getFitParent())
{
// EXT-8285 ('No attachments worn' text appears at the bottom of blank 'Attachments' accordion)
// The problem was in passing message "scrollToShowRect" IN LLAccordionCtrlTab::notifyParent
// FROM child LLScrollContainer TO parent LLAccordionCtrl with "it_parent" set to true.
// It is wrong notification for parent accordion which leads to recursive call of adjustContainerPanel
// As the result of recursive call of adjustContainerPanel we got LLAccordionCtrlTab
// that reshaped and re-sized with different rectangles.
// LLAccordionCtrl has own scrollContainer and LLAccordionCtrlTab has own scrollContainer
// both should handle own scroll container's event.
// So, if parent accordion "fit_parent" accordion tab should handle its scroll container events itself.
return 1;
}
}
return LLUICtrl::notifyParent(info);
}

View File

@ -220,6 +220,7 @@ protected:
LLView* findContainerView ();
void selectOnFocusReceived();
void deselectOnFocusLost();
private:

View File

@ -81,17 +81,6 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
// must be big enough to hold all children
setUseBoundingRect(TRUE);
// Label (add a little space to make sure text actually renders)
const S32 FUDGE = 10;
S32 text_width = mFont->getWidth( p.label ) + FUDGE;
S32 text_height = llround(mFont->getLineHeight());
LLRect label_rect;
label_rect.setOriginAndSize(
llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing,
llcheckboxctrl_vpad + 1, // padding to get better alignment
text_width + llcheckboxctrl_hpad,
text_height );
// *HACK Get rid of this with SL-55508...
// this allows blank check boxes and radio boxes for now
std::string local_label = p.label;
@ -101,7 +90,6 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
}
LLTextBox::Params tbparams = p.label_text;
tbparams.rect(label_rect);
tbparams.initial_value(local_label);
if (p.font.isProvided())
{
@ -111,6 +99,17 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
mLabel = LLUICtrlFactory::create<LLTextBox> (tbparams);
addChild(mLabel);
S32 text_width = mLabel->getTextBoundingRect().getWidth();
S32 text_height = llround(mFont->getLineHeight());
LLRect label_rect;
label_rect.setOriginAndSize(
llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing,
llcheckboxctrl_vpad + 1, // padding to get better alignment
text_width + llcheckboxctrl_hpad,
text_height );
mLabel->setShape(label_rect);
// Button
// Note: button cover the label by extending all the way to the right.
LLRect btn_rect;
@ -190,8 +189,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
static LLUICachedControl<S32> llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0);
static LLUICachedControl<S32> llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0);
const S32 FUDGE = 10;
S32 text_width = mFont->getWidth( mLabel->getText() ) + FUDGE;
S32 text_width = mLabel->getTextBoundingRect().getWidth();
S32 text_height = llround(mFont->getLineHeight());
LLRect label_rect;
label_rect.setOriginAndSize(
@ -199,7 +197,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
llcheckboxctrl_vpad,
text_width,
text_height );
mLabel->setRect(label_rect);
mLabel->setShape(label_rect);
LLRect btn_rect;
btn_rect.setOriginAndSize(
@ -207,7 +205,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
llcheckboxctrl_vpad,
llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width,
llmax( text_height, llcheckboxctrl_btn_size() ) );
mButton->setRect( btn_rect );
mButton->setShape( btn_rect );
LLUICtrl::reshape(width, height, called_from_parent);
}

View File

@ -1048,26 +1048,7 @@ void LLFlatListView::setNoItemsCommentVisible(bool visible) const
{
if (mNoItemsCommentTextbox)
{
if (visible)
{
/*
// *NOTE: MA 2010-02-04
// Deprecated after params of the comment text box were moved into widget (flat_list_view.xml)
// can be removed later if nothing happened.
// We have to update child rect here because of issues with rect after reshaping while creating LLTextbox
// It is possible to have invalid LLRect if Flat List is in LLAccordionTab
LLRect comment_rect = getLocalRect();
// To see comment correctly (EXT - 3244) in mNoItemsCommentTextbox we must get border width
// of LLFlatListView (@see getBorderWidth()) and stretch mNoItemsCommentTextbox to this width
// But getBorderWidth() returns 0 if LLFlatListView not visible. So we have to get border width
// from 'scroll_border'
LLViewBorder* scroll_border = getChild<LLViewBorder>("scroll border");
comment_rect.stretch(-scroll_border->getBorderWidth());
mNoItemsCommentTextbox->setRect(comment_rect);
*/
}
mSelectedItemsBorder->setVisible(FALSE);
mSelectedItemsBorder->setVisible(!visible);
mNoItemsCommentTextbox->setVisible(visible);
}
}

View File

@ -451,6 +451,14 @@ void LLFloater::enableResizeCtrls(bool enable)
}
}
void LLFloater::destroy()
{
// LLFloaterReg should be synchronized with "dead" floater to avoid returning dead instance before
// it was deleted via LLMortician::updateClass(). See EXT-8458.
LLFloaterReg::removeInstance(mInstanceName, mKey);
die();
}
// virtual
LLFloater::~LLFloater()
{

View File

@ -308,7 +308,7 @@ protected:
BOOL getAutoFocus() const { return mAutoFocus; }
LLDragHandle* getDragHandle() const { return mDragHandle; }
void destroy() { die(); } // Don't call this directly. You probably want to call closeFloater()
void destroy(); // Don't call this directly. You probably want to call closeFloater()
virtual void onClickCloseBtn();

View File

@ -217,6 +217,12 @@ void LLMenuItemGL::setValue(const LLSD& value)
setLabel(value.asString());
}
//virtual
LLSD LLMenuItemGL::getValue() const
{
return getLabel();
}
//virtual
BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
{

View File

@ -95,6 +95,7 @@ public:
// LLUICtrl overrides
/*virtual*/ void setValue(const LLSD& value);
/*virtual*/ LLSD getValue() const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);

View File

@ -373,6 +373,7 @@ LLNotification::LLNotification(const LLSD& sd) :
LLSD LLNotification::asLLSD()
{
LLSD output;
output["id"] = mId;
output["name"] = mTemplatep->mName;
output["form"] = getForm()->asLLSD();
output["substitutions"] = mSubstitutions;

View File

@ -353,6 +353,8 @@ public:
}
};
LLNotificationResponderPtr getResponderPtr() { return mResponder; }
private:
LLUUID mId;

View File

@ -298,11 +298,11 @@ void LLResMgr::getIntegerString( std::string& output, S32 input ) const
{
if (fraction == remaining_count)
{
fraction_string = llformat("%d%c", fraction, getThousandsSeparator());
fraction_string = llformat_to_utf8("%d%c", fraction, getThousandsSeparator());
}
else
{
fraction_string = llformat("%3.3d%c", fraction, getThousandsSeparator());
fraction_string = llformat_to_utf8("%3.3d%c", fraction, getThousandsSeparator());
}
output = fraction_string + output;
}

View File

@ -2261,6 +2261,12 @@ void LLTextBase::updateRects()
? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
: mVisibleTextRect.getWidth();
if (!mScroller)
{
// push doc rect to top of text widget
doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop);
}
mDocumentView->setShape(doc_rect);
//update mVisibleTextRect *after* mDocumentView has been resized
@ -2756,9 +2762,9 @@ F32 LLLineBreakTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 se
}
LLImageTextSegment::LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor)
:LLTextSegment(pos,pos+1)
,mStyle( style )
,mEditor(editor)
: LLTextSegment(pos,pos+1),
mStyle( style ),
mEditor(editor)
{
}

View File

@ -585,7 +585,7 @@
<key>Value</key>
<integer>2</integer>
</map>
<key>AvatarBakedTextureTimeout</key>
<key>AvatarBakedTextureUploadTimeout</key>
<map>
<key>Comment</key>
<string>Specifes the maximum time in seconds to wait before sending your baked textures for avatar appearance. Set to 0 to disable and wait until all baked textures are at highest resolution.</string>
@ -594,8 +594,20 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>120</integer>
<integer>60</integer>
</map>
<key>AvatarBakedLocalTextureUpdateTimeout</key>
<map>
<key>Comment</key>
<string>Specifes the maximum time in seconds to wait before updating your appearance during appearance mode.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>10</integer>
</map>
<key>AvatarSex</key>
<map>
<key>Comment</key>

View File

@ -3075,7 +3075,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
return;
}
if (gAgentCamera.cameraCustomizeAvatar())
if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
{
// ignore baked textures when in customize mode
return;
@ -3541,7 +3541,7 @@ void LLAgent::sendAgentSetAppearance()
{
if (!isAgentAvatarValid()) return;
if (gAgentQueryManager.mNumPendingQueries > 0 && !gAgentCamera.cameraCustomizeAvatar())
if (gAgentQueryManager.mNumPendingQueries > 0 && (isAgentAvatarValid() && gAgentAvatarp->isUsingBakedTextures()))
{
return;
}

View File

@ -941,7 +941,7 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction)
*/
}
if( cameraCustomizeAvatar() )
if(cameraCustomizeAvatar())
{
new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
}

View File

@ -39,21 +39,35 @@
// library includes
#include "llui.h" // getLanguage()
LLAgentLanguage::LLAgentLanguage()
// static
void LLAgentLanguage::init()
{
gSavedSettings.getControl("Language")->getSignal()->connect(boost::bind(&update));
gSavedSettings.getControl("InstallLanguage")->getSignal()->connect(boost::bind(&update));
gSavedSettings.getControl("SystemLanguage")->getSignal()->connect(boost::bind(&update));
gSavedSettings.getControl("LanguageIsPublic")->getSignal()->connect(boost::bind(&update));
gSavedSettings.getControl("Language")->getSignal()->connect(boost::bind(&onChange));
gSavedSettings.getControl("InstallLanguage")->getSignal()->connect(boost::bind(&onChange));
gSavedSettings.getControl("SystemLanguage")->getSignal()->connect(boost::bind(&onChange));
gSavedSettings.getControl("LanguageIsPublic")->getSignal()->connect(boost::bind(&onChange));
}
// static
void LLAgentLanguage::onChange()
{
// Clear inventory cache so that default names of inventory items
// appear retranslated (EXT-8308).
gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE);
}
// send language settings to the sim
// static
bool LLAgentLanguage::update()
{
LLSD body;
std::string url = gAgent.getRegion()->getCapability("UpdateAgentLanguage");
std::string url;
if (gAgent.getRegion())
{
url = gAgent.getRegion()->getCapability("UpdateAgentLanguage");
}
if (!url.empty())
{
std::string language = LLUI::getLanguage();

View File

@ -33,14 +33,14 @@
#ifndef LL_LLAGENTLANGUAGE_H
#define LL_LLAGENTLANGUAGE_H
#include "llsingleton.h" // LLSingleton<>
#include "llevent.h"
class LLAgentLanguage: public LLSingleton<LLAgentLanguage>, public LLOldEvents::LLSimpleListener
class LLAgentLanguage
{
public:
LLAgentLanguage();
static void init();
static bool update();
private:
static void onChange();
};
#endif // LL_LLAGENTLANGUAGE_H

View File

@ -384,7 +384,8 @@ void LLAgentWearables::sendAgentWearablesUpdate()
gAgent.sendReliableMessage();
}
void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update)
void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update,
const std::string new_name)
{
LLWearable* old_wearable = getWearable(type, index);
if (old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion()))
@ -402,6 +403,14 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
LLInventoryItem* item = gInventory.getItem(old_item_id);
if (item)
{
std::string item_name = item->getName();
bool name_changed = false;
if (!new_name.empty() && (new_name != item->getName()))
{
llinfos << "saveWearable changing name from " << item->getName() << " to " << new_name << llendl;
item_name = new_name;
name_changed = true;
}
// Update existing inventory item
LLPointer<LLViewerInventoryItem> template_item =
new LLViewerInventoryItem(item->getUUID(),
@ -410,7 +419,7 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
new_wearable->getAssetID(),
new_wearable->getAssetType(),
item->getInventoryType(),
item->getName(),
item_name,
item->getDescription(),
item->getSaleInfo(),
item->getFlags(),
@ -418,6 +427,10 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
template_item->setTransactionID(new_wearable->getTransactionID());
template_item->updateServer(FALSE);
gInventory.updateItem(template_item);
if (name_changed)
{
gInventory.notifyObservers();
}
}
else
{

View File

@ -206,7 +206,8 @@ private:
//--------------------------------------------------------------------
public:
void saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, BOOL save_in_lost_and_found);
void saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update = TRUE);
void saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update = TRUE,
const std::string new_name = "");
void saveAllWearables();
void revertWearable(const LLWearableType::EType type, const U32 index);

View File

@ -983,6 +983,10 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
LLNotificationsUtil::add("CannotWearTrash");
return false;
}
else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), LLAppearanceMgr::instance().getCOF())) // EXT-84911
{
return false;
}
switch (item_to_wear->getType())
{
@ -1801,9 +1805,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
llinfos << "wearInventoryCategory( " << category->getName()
<< " )" << llendl;
callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
&LLAppearanceMgr::instance(),
category->getUUID(), copy, append));
callAfterCategoryFetch(category->getUUID(), boost::bind(&LLAppearanceMgr::wearCategoryFinal,
&LLAppearanceMgr::instance(),
category->getUUID(), copy, append));
}
void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
@ -2217,6 +2221,7 @@ void LLAppearanceMgr::updateIsDirty()
LLViewerInventoryItem *item2 = outfit_items.get(i);
if (item1->getLinkedUUID() != item2->getLinkedUUID() ||
item1->getName() != item2->getName() ||
item1->LLInventoryItem::getDescription() != item2->LLInventoryItem::getDescription())
{
mOutfitIsDirty = true;
@ -2706,6 +2711,21 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
return gInventory.isObjectDescendentOf(obj_id, getCOF());
}
// static
bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id)
{
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id));
gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
find_links);
return !items.empty();
}
BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
{
if (!getIsInCOF(obj_id)) return FALSE;
@ -2733,3 +2753,192 @@ BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
return FALSE;
*/
}
// Shim class to allow arbitrary boost::bind
// expressions to be run as one-time idle callbacks.
//
// TODO: rework idle function spec to take a boost::function in the first place.
class OnIdleCallbackOneTime
{
public:
OnIdleCallbackOneTime(nullary_func_t callable):
mCallable(callable)
{
}
static void onIdle(void *data)
{
gIdleCallbacks.deleteFunction(onIdle, data);
OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
self->call();
delete self;
}
void call()
{
mCallable();
}
private:
nullary_func_t mCallable;
};
void doOnIdleOneTime(nullary_func_t callable)
{
OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
}
// Shim class to allow generic boost functions to be run as
// recurring idle callbacks. Callable should return true when done,
// false to continue getting called.
//
// TODO: rework idle function spec to take a boost::function in the first place.
class OnIdleCallbackRepeating
{
public:
OnIdleCallbackRepeating(bool_func_t callable):
mCallable(callable)
{
}
// Will keep getting called until the callable returns true.
static void onIdle(void *data)
{
OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
bool done = self->call();
if (done)
{
gIdleCallbacks.deleteFunction(onIdle, data);
delete self;
}
}
bool call()
{
return mCallable();
}
private:
bool_func_t mCallable;
};
void doOnIdleRepeating(bool_func_t callable)
{
OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
}
class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver
{
public:
CallAfterCategoryFetchStage2(const uuid_vec_t& ids,
nullary_func_t callable) :
LLInventoryFetchItemsObserver(ids),
mCallable(callable)
{
}
~CallAfterCategoryFetchStage2()
{
}
virtual void done()
{
llinfos << this << " done with incomplete " << mIncomplete.size()
<< " complete " << mComplete.size() << " calling callable" << llendl;
gInventory.removeObserver(this);
doOnIdleOneTime(mCallable);
delete this;
}
protected:
nullary_func_t mCallable;
};
class CallAfterCategoryFetchStage1: public LLInventoryFetchDescendentsObserver
{
public:
CallAfterCategoryFetchStage1(const LLUUID& cat_id, nullary_func_t callable) :
LLInventoryFetchDescendentsObserver(cat_id),
mCallable(callable)
{
}
~CallAfterCategoryFetchStage1()
{
}
virtual void done()
{
// What we do here is get the complete information on the items in
// the library, and set up an observer that will wait for that to
// happen.
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(mComplete.front(),
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH);
S32 count = item_array.count();
if(!count)
{
llwarns << "Nothing fetched in category " << mComplete.front()
<< llendl;
//dec_busy_count();
gInventory.removeObserver(this);
// lets notify observers that loading is finished.
gAgentWearables.notifyLoadingFinished();
delete this;
return;
}
llinfos << "stage1 got " << item_array.count() << " items, passing to stage2 " << llendl;
uuid_vec_t ids;
for(S32 i = 0; i < count; ++i)
{
ids.push_back(item_array.get(i)->getUUID());
}
gInventory.removeObserver(this);
// do the fetch
CallAfterCategoryFetchStage2 *stage2 = new CallAfterCategoryFetchStage2(ids, mCallable);
stage2->startFetch();
if(stage2->isFinished())
{
// everything is already here - call done.
stage2->done();
}
else
{
// it's all on it's way - add an observer, and the inventory
// will call done for us when everything is here.
gInventory.addObserver(stage2);
}
delete this;
}
protected:
nullary_func_t mCallable;
};
void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb)
{
CallAfterCategoryFetchStage1 *stage1 = new CallAfterCategoryFetchStage1(cat_id, cb);
stage1->startFetch();
if (stage1->isFinished())
{
stage1->done();
}
else
{
gInventory.addObserver(stage1);
}
}
void wear_multiple(const uuid_vec_t& ids, bool replace)
{
LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
bool first = true;
uuid_vec_t::const_iterator it;
for (it = ids.begin(); it != ids.end(); ++it)
{
// if replace is requested, the first item worn will replace the current top
// item, and others will be added.
LLAppearanceMgr::instance().wearItemOnAvatar(*it,false,first && replace,cb);
first = false;
}
}

View File

@ -223,6 +223,11 @@ public:
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;
/**
* Checks if COF contains link to specified object.
*/
static bool isLinkInCOF(const LLUUID& obj_id);
};
class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
@ -242,180 +247,19 @@ private:
LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);
// Shim class and template function to allow arbitrary boost::bind
// expressions to be run as one-time idle callbacks.
template <typename T>
class OnIdleCallbackOneTime
{
public:
OnIdleCallbackOneTime(T callable):
mCallable(callable)
{
}
static void onIdle(void *data)
{
gIdleCallbacks.deleteFunction(onIdle, data);
OnIdleCallbackOneTime<T>* self = reinterpret_cast<OnIdleCallbackOneTime<T>*>(data);
self->call();
delete self;
}
void call()
{
mCallable();
}
private:
T mCallable;
};
typedef boost::function<void ()> nullary_func_t;
typedef boost::function<bool ()> bool_func_t;
template <typename T>
void doOnIdleOneTime(T callable)
{
OnIdleCallbackOneTime<T>* cb_functor = new OnIdleCallbackOneTime<T>(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackOneTime<T>::onIdle,cb_functor);
}
// Call a given callable once in idle loop.
void doOnIdleOneTime(nullary_func_t callable);
// Shim class and template function to allow arbitrary boost::bind
// expressions to be run as recurring idle callbacks.
// Callable should return true when done, false to continue getting called.
template <typename T>
class OnIdleCallbackRepeating
{
public:
OnIdleCallbackRepeating(T callable):
mCallable(callable)
{
}
// Will keep getting called until the callable returns true.
static void onIdle(void *data)
{
OnIdleCallbackRepeating<T>* self = reinterpret_cast<OnIdleCallbackRepeating<T>*>(data);
bool done = self->call();
if (done)
{
gIdleCallbacks.deleteFunction(onIdle, data);
delete self;
}
}
bool call()
{
return mCallable();
}
private:
T mCallable;
};
// Repeatedly call a callable in idle loop until it returns true.
void doOnIdleRepeating(bool_func_t callable);
template <typename T>
void doOnIdleRepeating(T callable)
{
OnIdleCallbackRepeating<T>* cb_functor = new OnIdleCallbackRepeating<T>(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackRepeating<T>::onIdle,cb_functor);
}
// Invoke a given callable after category contents are fully fetched.
void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb);
template <class T>
class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver
{
public:
CallAfterCategoryFetchStage2(const uuid_vec_t& ids,
T callable) :
LLInventoryFetchItemsObserver(ids),
mCallable(callable)
{
}
~CallAfterCategoryFetchStage2()
{
}
virtual void done()
{
llinfos << this << " done with incomplete " << mIncomplete.size()
<< " complete " << mComplete.size() << " calling callable" << llendl;
gInventory.removeObserver(this);
doOnIdleOneTime(mCallable);
delete this;
}
protected:
T mCallable;
};
template <class T>
class CallAfterCategoryFetchStage1: public LLInventoryFetchDescendentsObserver
{
public:
CallAfterCategoryFetchStage1(const LLUUID& cat_id, T callable) :
LLInventoryFetchDescendentsObserver(cat_id),
mCallable(callable)
{
}
~CallAfterCategoryFetchStage1()
{
}
virtual void done()
{
// What we do here is get the complete information on the items in
// the library, and set up an observer that will wait for that to
// happen.
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(mComplete.front(),
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH);
S32 count = item_array.count();
if(!count)
{
llwarns << "Nothing fetched in category " << mComplete.front()
<< llendl;
//dec_busy_count();
gInventory.removeObserver(this);
// lets notify observers that loading is finished.
gAgentWearables.notifyLoadingFinished();
delete this;
return;
}
llinfos << "stage1 got " << item_array.count() << " items, passing to stage2 " << llendl;
uuid_vec_t ids;
for(S32 i = 0; i < count; ++i)
{
ids.push_back(item_array.get(i)->getUUID());
}
gInventory.removeObserver(this);
// do the fetch
CallAfterCategoryFetchStage2<T> *stage2 = new CallAfterCategoryFetchStage2<T>(ids, mCallable);
stage2->startFetch();
if(stage2->isFinished())
{
// everything is already here - call done.
stage2->done();
}
else
{
// it's all on it's way - add an observer, and the inventory
// will call done for us when everything is here.
gInventory.addObserver(stage2);
}
delete this;
}
protected:
T mCallable;
};
template <class T>
void callAfterCategoryFetch(const LLUUID& cat_id, T callable)
{
CallAfterCategoryFetchStage1<T> *stage1 = new CallAfterCategoryFetchStage1<T>(cat_id, callable);
stage1->startFetch();
if (stage1->isFinished())
{
stage1->done();
}
else
{
gInventory.addObserver(stage1);
}
}
// Wear all items in a uuid vector.
void wear_multiple(const uuid_vec_t& ids, bool replace);
#endif

View File

@ -45,6 +45,7 @@
#include "llgroupmgr.h"
#include "llagent.h"
#include "llagentcamera.h"
#include "llagentlanguage.h"
#include "llagentwearables.h"
#include "llwindow.h"
#include "llviewerstats.h"
@ -356,7 +357,7 @@ static void ui_audio_callback(const LLUUID& uuid)
bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
{
if(!match || !base)
if(!match || !base || base->getPlainText())
return false;
LLUUID match_id = match->getID();
@ -385,7 +386,7 @@ bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
params.view = icon;
params.left_pad = 4;
params.right_pad = 4;
params.top_pad = 2;
params.top_pad = -2;
params.bottom_pad = 2;
base->appendWidget(params," ",false);
@ -946,6 +947,8 @@ bool LLAppViewer::init()
LLStringOps::sPM = LLTrans::getString("dateTimePM");
}
LLAgentLanguage::init();
return true;
}

View File

@ -550,9 +550,10 @@ namespace action_give_inventory
}
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
if (NULL == active_panel)
if (!active_panel)
{
return;
active_panel = get_outfit_editor_inventory_panel();
if (!active_panel) return;
}
const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();

View File

@ -111,6 +111,12 @@ public:
return pInstance;
}
~LLChatHistoryHeader()
{
// Detach the info button so that it doesn't get destroyed (EXT-8463).
hideInfoCtrl();
}
BOOL handleMouseUp(S32 x, S32 y, MASK mask)
{
return LLPanel::handleMouseUp(x,y,mask);
@ -382,8 +388,18 @@ protected:
if (!sInfoCtrl)
{
// *TODO: Delete the button at exit.
sInfoCtrl = LLUICtrlFactory::createFromFile<LLUICtrl>("inspector_info_ctrl.xml", NULL, LLPanel::child_registry_t::instance());
sInfoCtrl->setCommitCallback(boost::bind(&LLChatHistoryHeader::onClickInfoCtrl, sInfoCtrl));
if (sInfoCtrl)
{
sInfoCtrl->setCommitCallback(boost::bind(&LLChatHistoryHeader::onClickInfoCtrl, sInfoCtrl));
}
}
if (!sInfoCtrl)
{
llassert(sInfoCtrl != NULL);
return;
}
LLTextBase* name = getChild<LLTextBase>("user_name");

View File

@ -283,7 +283,8 @@ LLCOFWearables::LLCOFWearables() : LLPanel(),
mClothingTab(NULL),
mAttachmentsTab(NULL),
mBodyPartsTab(NULL),
mLastSelectedTab(NULL)
mLastSelectedTab(NULL),
mAccordionCtrl(NULL)
{
mClothingMenu = new CofClothingContextMenu(this);
mAttachmentMenu = new CofAttachmentContextMenu(this);
@ -335,6 +336,8 @@ BOOL LLCOFWearables::postBuild()
mTab2AssetType[mAttachmentsTab] = LLAssetType::AT_OBJECT;
mTab2AssetType[mBodyPartsTab] = LLAssetType::AT_BODYPART;
mAccordionCtrl = getChild<LLAccordionCtrl>("cof_wearables_accordion");
return LLPanel::postBuild();
}
@ -633,18 +636,35 @@ LLAssetType::EType LLCOFWearables::getExpandedAccordionAssetType()
typedef std::map<std::string, LLAssetType::EType> type_map_t;
static type_map_t type_map;
static LLAccordionCtrl* accordion_ctrl = getChild<LLAccordionCtrl>("cof_wearables_accordion");
const LLAccordionCtrlTab* expanded_tab = accordion_ctrl->getExpandedTab();
return get_if_there(mTab2AssetType, expanded_tab, LLAssetType::AT_NONE);
if (mAccordionCtrl != NULL)
{
const LLAccordionCtrlTab* expanded_tab = mAccordionCtrl->getExpandedTab();
return get_if_there(mTab2AssetType, expanded_tab, LLAssetType::AT_NONE);
}
return LLAssetType::AT_NONE;
}
LLAssetType::EType LLCOFWearables::getSelectedAccordionAssetType()
{
static LLAccordionCtrl* accordion_ctrl = getChild<LLAccordionCtrl>("cof_wearables_accordion");
const LLAccordionCtrlTab* selected_tab = accordion_ctrl->getSelectedTab();
if (mAccordionCtrl != NULL)
{
const LLAccordionCtrlTab* selected_tab = mAccordionCtrl->getSelectedTab();
return get_if_there(mTab2AssetType, selected_tab, LLAssetType::AT_NONE);
return get_if_there(mTab2AssetType, selected_tab, LLAssetType::AT_NONE);
}
return LLAssetType::AT_NONE;
}
void LLCOFWearables::expandDefaultAccordionTab()
{
if (mAccordionCtrl != NULL)
{
mAccordionCtrl->expandDefaultTab();
}
}
void LLCOFWearables::onListRightClick(LLUICtrl* ctrl, S32 x, S32 y, LLListContextMenu* menu)

View File

@ -40,6 +40,7 @@
#include "llappearancemgr.h"
#include "llinventorymodel.h"
class LLAccordionCtrl;
class LLAccordionCtrlTab;
class LLListContextMenu;
class LLPanelClothingListItem;
@ -86,6 +87,7 @@ public:
LLAssetType::EType getExpandedAccordionAssetType();
LLAssetType::EType getSelectedAccordionAssetType();
void expandDefaultAccordionTab();
LLCOFCallbacks& getCOFCallbacks() { return mCOFCallbacks; }
@ -123,6 +125,8 @@ protected:
LLListContextMenu* mClothingMenu;
LLListContextMenu* mAttachmentMenu;
LLListContextMenu* mBodyPartMenu;
LLAccordionCtrl* mAccordionCtrl;
};

View File

@ -35,6 +35,8 @@
#include "lluictrlfactory.h"
#include "lltextbox.h"
#include "lllineeditor.h"
#include "llresmgr.h" // for LLLocale
#include "lltrans.h"
#include "llviewercontrol.h"
#include "llversioninfo.h"
@ -323,7 +325,12 @@ std::string LLCurrencyUIManager::Impl::getLocalEstimate() const
if (mUSDCurrencyEstimated)
{
// we have the old-style USD-specific value
return "US$ " + llformat("%#.2f", mUSDCurrencyEstimatedCost / 100.0);
LLStringUtil::format_map_t args;
{
LLLocale locale_override(LLStringUtil::getLocale());
args["[AMOUNT]"] = llformat("%#.2f", mUSDCurrencyEstimatedCost / 100.0);
}
return LLTrans::getString("LocalEstimateUSD", args);
}
return "";
}

View File

@ -149,7 +149,7 @@ void LLStandardBumpmap::restoreGL()
0,
0);
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL, NULL );
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL );
LLStandardBumpmap::sStandardBumpmapCount++;
}
@ -923,7 +923,7 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
// Note: this may create an LLImageGL immediately
src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL, NULL );
src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
// bump_total++;

View File

@ -167,6 +167,10 @@ void LLViewerDynamicTexture::postRender(BOOL success)
{
generateGLTexture() ;
}
if(!mGLTexturep->getHasGLTexture())
{
generateGLTexture() ;
}
llcallstacks << "class type: " << (S32)getType() << llcallstacksendl ;
success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);

View File

@ -1364,7 +1364,7 @@ F32 LLFace::getTextureVirtualSize()
F32 cos_angle_to_view_dir;
BOOL in_frustum = calcPixelArea(cos_angle_to_view_dir, radius);
if (mPixelArea < 0.0001f || !in_frustum)
if (mPixelArea < F_ALMOST_ZERO || !in_frustum)
{
setVirtualSize(0.f) ;
return 0.f;

View File

@ -47,6 +47,7 @@
#include "llbutton.h"
#include "llgroupactions.h"
#include "llscrolllistctrl.h"
#include "llselectmgr.h"
#include "lltextbox.h"
#include "lluictrlfactory.h"
#include "lltrans.h"
@ -89,6 +90,7 @@ BOOL LLFloaterGroupPicker::postBuild()
list_ctrl->setContextMenu(LLScrollListCtrl::MENU_GROUP);
}
LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterGroupPicker::onBtnCancel, this));
childSetAction("OK", onBtnOK, this);

View File

@ -2088,7 +2088,8 @@ void LLPanelLandOptions::refresh()
LLStyle::Params style;
style.image(LLUI::getUIImage(gFloaterView->getParentFloater(this)->getString("maturity_icon_moderate")));
LLCheckBoxWithTBAcess* fullaccess_mature_ctrl = (LLCheckBoxWithTBAcess*)mMatureCtrl;
fullaccess_mature_ctrl->getTextBox()->setText(std::string("icon"),style);
fullaccess_mature_ctrl->getTextBox()->setText(LLStringExplicit(""));
fullaccess_mature_ctrl->getTextBox()->appendImageSegment(style);
fullaccess_mature_ctrl->getTextBox()->appendText(getString("mature_check_mature"), false);
fullaccess_mature_ctrl->setToolTip(getString("mature_check_mature_tooltip"));
fullaccess_mature_ctrl->reshape(fullaccess_mature_ctrl->getRect().getWidth(), fullaccess_mature_ctrl->getRect().getHeight(), FALSE);

View File

@ -227,7 +227,23 @@ void LLPanelVoiceDeviceSettings::refresh()
iter != LLVoiceClient::getInstance()->getCaptureDevices().end();
iter++)
{
mCtrlInputDevices->add( *iter, ADD_BOTTOM );
// Lets try to localize some system device names. EXT-8375
std::string device_name = *iter;
LLStringUtil::toLower(device_name); //compare in low case
if ("default system device" == device_name)
{
device_name = getString(device_name);
}
else if ("no device" == device_name)
{
device_name = getString(device_name);
}
else
{
// restore original value
device_name = *iter;
}
mCtrlInputDevices->add(device_name, ADD_BOTTOM );
}
if(!mCtrlInputDevices->setSimple(mInputDevice))
@ -244,7 +260,23 @@ void LLPanelVoiceDeviceSettings::refresh()
for(iter= LLVoiceClient::getInstance()->getRenderDevices().begin();
iter != LLVoiceClient::getInstance()->getRenderDevices().end(); iter++)
{
mCtrlOutputDevices->add( *iter, ADD_BOTTOM );
// Lets try to localize some system device names. EXT-8375
std::string device_name = *iter;
LLStringUtil::toLower(device_name); //compare in low case
if ("default system device" == device_name)
{
device_name = getString(device_name);
}
else if ("no device" == device_name)
{
device_name = getString(device_name);
}
else
{
// restore original value
device_name = *iter;
}
mCtrlOutputDevices->add(device_name, ADD_BOTTOM );
}
if(!mCtrlOutputDevices->setSimple(mOutputDevice))

View File

@ -206,6 +206,7 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key)
mFactoryMap["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL);
//Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", FALSE);
mCommitCallbackRegistrar.add("WMap.Coordinates", boost::bind(&LLFloaterWorldMap::onCoordinatesCommit, this));
mCommitCallbackRegistrar.add("WMap.Location", boost::bind(&LLFloaterWorldMap::onLocationCommit, this));
mCommitCallbackRegistrar.add("WMap.AvatarCombo", boost::bind(&LLFloaterWorldMap::onAvatarComboCommit, this));
mCommitCallbackRegistrar.add("WMap.Landmark", boost::bind(&LLFloaterWorldMap::onLandmarkComboCommit, this));
@ -336,8 +337,6 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)
}
}
// static
void LLFloaterWorldMap::reloadIcons(void*)
{
@ -582,6 +581,10 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
S32 world_y = S32(pos_global.mdV[1] / 256);
LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
setDefaultBtn("");
// clicked on a non-region - turn off coord display
enableTeleportCoordsDisplay( false );
return;
}
if (sim_info->isDown())
@ -592,6 +595,10 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
LLWorldMap::getInstance()->setTrackingInvalid();
LLTracker::stopTracking(NULL);
setDefaultBtn("");
// clicked on a down region - turn off coord display
enableTeleportCoordsDisplay( false );
return;
}
@ -609,9 +616,40 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
LLTracker::trackLocation(pos_global, full_name, tooltip);
LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking
LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal();
updateTeleportCoordsDisplay( coord_pos );
// we have a valid region - turn on coord display
enableTeleportCoordsDisplay( true );
setDefaultBtn("Teleport");
}
// enable/disable teleport destination coordinates
void LLFloaterWorldMap::enableTeleportCoordsDisplay( bool enabled )
{
childSetEnabled("teleport_coordinate_x", enabled );
childSetEnabled("teleport_coordinate_y", enabled );
childSetEnabled("teleport_coordinate_z", enabled );
}
// update display of teleport destination coordinates - pos is in global coordinates
void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos )
{
// if we're going to update their value, we should also enable them
enableTeleportCoordsDisplay( true );
// convert global specified position to a local one
F32 region_local_x = (F32)fmod( pos.mdV[VX], (F64)REGION_WIDTH_METERS );
F32 region_local_y = (F32)fmod( pos.mdV[VY], (F64)REGION_WIDTH_METERS );
F32 region_local_z = (F32)fmod( pos.mdV[VZ], (F64)REGION_WIDTH_METERS );
// write in the values
childSetValue("teleport_coordinate_x", region_local_x );
childSetValue("teleport_coordinate_y", region_local_y );
childSetValue("teleport_coordinate_z", region_local_z );
}
void LLFloaterWorldMap::updateLocation()
{
bool gotSimName;
@ -638,6 +676,9 @@ void LLFloaterWorldMap::updateLocation()
// Fill out the location field
childSetValue("location", agent_sim_name);
// update the coordinate display with location of avatar in region
updateTeleportCoordsDisplay( agentPos );
// Figure out where user is
// Set the current SLURL
mSLURL = LLSLURL(agent_sim_name, gAgent.getPositionGlobal());
@ -668,6 +709,10 @@ void LLFloaterWorldMap::updateLocation()
childSetValue("location", sim_name);
// refresh coordinate display to reflect where user clicked.
LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal();
updateTeleportCoordsDisplay( coord_pos );
// simNameFromPosGlobal can fail, so don't give the user an invalid SLURL
if ( gotSimName )
{
@ -1139,6 +1184,22 @@ void LLFloaterWorldMap::onLocationCommit()
}
}
void LLFloaterWorldMap::onCoordinatesCommit()
{
if( mIsClosing )
{
return;
}
S32 x_coord = (S32)childGetValue("teleport_coordinate_x").asReal();
S32 y_coord = (S32)childGetValue("teleport_coordinate_y").asReal();
S32 z_coord = (S32)childGetValue("teleport_coordinate_z").asReal();
const std::string region_name = childGetValue("location").asString();
trackURL( region_name, x_coord, y_coord, z_coord );
}
void LLFloaterWorldMap::onClearBtn()
{
mTrackedStatus = LLTracker::TRACKING_NOTHING;
@ -1199,6 +1260,9 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate)
else if(LLWorldMap::getInstance()->isTracking())
{
pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal();;
}
else
{

View File

@ -149,6 +149,7 @@ protected:
void updateSearchEnabled();
void onLocationFocusChanged( LLFocusableElement* ctrl );
void onLocationCommit();
void onCoordinatesCommit();
void onCommitSearchResult();
void cacheLandmarkPosition();
@ -160,6 +161,12 @@ private:
F32 mCurZoomVal;
LLFrameTimer mZoomTimer;
// update display of teleport destination coordinates - pos is in global coordinates
void updateTeleportCoordsDisplay( const LLVector3d& pos );
// enable/disable teleport destination coordinates
void enableTeleportCoordsDisplay( bool enabled );
LLDynamicArray<LLUUID> mLandmarkAssetIDList;
LLDynamicArray<LLUUID> mLandmarkItemIDList;

View File

@ -1195,7 +1195,7 @@ void LLFolderView::propertiesSelectedItems( void )
void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type)
{
LLFolderBridge *folder_bridge = LLFolderBridge::sSelf;
LLFolderBridge *folder_bridge = LLFolderBridge::sSelf.get();
if (!folder_bridge) return;
LLViewerInventoryCategory *cat = folder_bridge->getCategory();
@ -1874,13 +1874,18 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
}
// Successively filter out invalid options
selected_items_t::iterator item_itor;
U32 flags = FIRST_SELECTED_ITEM;
for (item_itor = mSelectedItems.begin(); item_itor != mSelectedItems.end(); ++item_itor)
for (selected_items_t::iterator item_itor = mSelectedItems.begin();
item_itor != mSelectedItems.end();
++item_itor)
{
(*item_itor)->buildContextMenu(*menu, flags);
LLFolderViewItem* selected_item = (*item_itor);
selected_item->buildContextMenu(*menu, flags);
flags = 0x0;
}
addNoOptions(menu);
menu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, menu, x, y);
@ -1889,7 +1894,7 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
}
else
{
if(menu && menu->getVisible())
if (menu && menu->getVisible())
{
menu->setVisible(FALSE);
}
@ -1898,6 +1903,37 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
return handled;
}
// Add "--no options--" if the menu is completely blank.
BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const
{
const std::string nooptions_str = "--no options--";
LLView *nooptions_item = NULL;
const LLView::child_list_t *list = menu->getChildList();
for (LLView::child_list_t::const_iterator itor = list->begin();
itor != list->end();
++itor)
{
LLView *menu_item = (*itor);
if (menu_item->getVisible())
{
return FALSE;
}
std::string name = menu_item->getName();
if (menu_item->getName() == nooptions_str)
{
nooptions_item = menu_item;
}
}
if (nooptions_item)
{
nooptions_item->setVisible(TRUE);
nooptions_item->setEnabled(FALSE);
return TRUE;
}
return FALSE;
}
BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask )
{
return LLView::handleHover( x, y, mask );

View File

@ -262,6 +262,7 @@ public:
BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; }
BOOL needsAutoRename() { return mNeedsAutoRename; }
void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; }
void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; }
void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }
@ -290,6 +291,8 @@ protected:
bool selectFirstItem();
bool selectLastItem();
BOOL addNoOptions(LLMenuGL* menu) const;
protected:
LLHandle<LLView> mPopupMenuHandle;

View File

@ -903,7 +903,15 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
if (member_id.notNull())
{
formatDateString(online_status); // reformat for sorting, e.g. 12/25/2008 -> 2008/12/25
if (online_status == "Online")
{
static std::string localized_online(LLTrans::getString("group_member_status_online"));
online_status = localized_online;
}
else
{
formatDateString(online_status); // reformat for sorting, e.g. 12/25/2008 -> 2008/12/25
}
//llinfos << "Member " << member_id << " has powers " << std::hex << agent_powers << std::dec << llendl;
LLGroupMemberData* newdata = new LLGroupMemberData(member_id,

View File

@ -952,6 +952,8 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
BOOL LLInvFVBridge::canShare() const
{
if (!isAgentInventory()) return FALSE;
const LLInventoryModel* model = getInventoryModel();
if (!model) return FALSE;
@ -963,9 +965,10 @@ BOOL LLInvFVBridge::canShare() const
return (BOOL)LLGiveInventory::isInventoryGiveAcceptable(item);
}
// All categories can be given.
const LLViewerInventoryCategory* cat = model->getCategory(mUUID);
return (cat != NULL);
// Categories can be given.
if (model->getCategory(mUUID)) return TRUE;
return FALSE;
}
// +=================================================+
@ -1444,7 +1447,7 @@ bool LLItemBridge::isRemoveAction(std::string action) const
// | LLFolderBridge |
// +=================================================+
LLFolderBridge* LLFolderBridge::sSelf=NULL;
LLHandle<LLFolderBridge> LLFolderBridge::sSelf;
// Can be moved to another folder
BOOL LLFolderBridge::isItemMovable() const
@ -2388,8 +2391,11 @@ void LLFolderBridge::pasteLinkFromClipboard()
void LLFolderBridge::staticFolderOptionsMenu()
{
if (!sSelf) return;
sSelf->folderOptionsMenu();
LLFolderBridge* selfp = sSelf.get();
if (selfp)
{
selfp->folderOptionsMenu();
}
}
void LLFolderBridge::folderOptionsMenu()
@ -2466,11 +2472,15 @@ void LLFolderBridge::folderOptionsMenu()
}
mItems.push_back(std::string("Outfit Separator"));
}
hide_context_entries(*mMenu, mItems, disabled_items, TRUE);
LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
if (menup)
{
hide_context_entries(*menup, mItems, disabled_items, TRUE);
// Reposition the menu, in case we're adding items to an existing menu.
mMenu->needsArrange();
mMenu->arrangeAndClear();
// Reposition the menu, in case we're adding items to an existing menu.
menup->needsArrange();
menup->arrangeAndClear();
}
}
BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
@ -2512,6 +2522,10 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
mDisabledItems.push_back(std::string("New Body Parts"));
}
// clear out old menu and folder pointers
mMenu.markDead();
sSelf.markDead();
if(trash_id == mUUID)
{
// This is the trash.
@ -2587,9 +2601,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
mWearables=TRUE;
}
mMenu = &menu;
sSelf = this;
}
// Preemptively disable system folder removal if more than one item selected.
@ -2604,12 +2615,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
mDisabledItems.push_back(std::string("Share"));
}
if (mItems.empty())
{
mItems.push_back(std::string("--no options--"));
mDisabledItems.push_back(std::string("--no options--"));
}
hide_context_entries(menu, mItems, mDisabledItems);
// Add menu items that are dependent on the contents of the folder.
@ -2619,6 +2624,9 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
folders.push_back(category->getUUID());
}
mMenu = menu.getHandle();
sSelf = getHandle();
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE);
fetch->startFetch();
inc_busy_count();
@ -4134,7 +4142,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
LLSD cbparams;
cbparams["index"] = curiter->first;
cbparams["label"] = attachment->getName();
cbparams["label"] = p.name;
p.on_click.function_name = "Inventory.AttachObject";
p.on_click.parameter = LLSD(attachment->getName());
p.on_enable.function_name = "Attachment.Label";

View File

@ -230,8 +230,8 @@ public:
const LLUUID& uuid) :
LLInvFVBridge(inventory, root, uuid),
mCallingCards(FALSE),
mWearables(FALSE),
mMenu(NULL) {}
mWearables(FALSE)
{}
BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop);
BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop);
@ -272,6 +272,7 @@ public:
static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);
LLViewerInventoryCategory* getCategory() const;
LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; }
protected:
//--------------------------------------------------------------------
@ -305,16 +306,17 @@ protected:
// Messy hacks for handling folder options
//--------------------------------------------------------------------
public:
static LLFolderBridge* sSelf;
static LLHandle<LLFolderBridge> sSelf;
static void staticFolderOptionsMenu();
void folderOptionsMenu();
private:
BOOL mCallingCards;
BOOL mWearables;
LLMenuGL* mMenu;
menuentry_vec_t mItems;
menuentry_vec_t mDisabledItems;
BOOL mCallingCards;
BOOL mWearables;
LLHandle<LLView> mMenu;
menuentry_vec_t mItems;
menuentry_vec_t mDisabledItems;
LLRootHandle<LLFolderBridge> mHandle;
};
class LLTextureBridge : public LLItemBridge

View File

@ -250,6 +250,18 @@ BOOL get_can_item_be_worn(const LLUUID& id)
const LLViewerInventoryItem* item = gInventory.getItem(id);
if (!item)
return FALSE;
if (LLAppearanceMgr::isLinkInCOF(item->getLinkedUUID()))
{
// an item having links in COF (i.e. a worn item)
return FALSE;
}
if (gInventory.isObjectDescendentOf(id, LLAppearanceMgr::instance().getCOF()))
{
// a non-link object in COF (should not normally happen)
return FALSE;
}
switch(item->getType())
{

View File

@ -117,6 +117,7 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type,
if (item_is_multi)
{
idx = ICONNAME_OBJECT_MULTI;
return getIconName(idx);
}
switch(asset_type)

View File

@ -294,6 +294,30 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id,
items = get_ptr_in_map(mParentChildItemTree, cat_id);
}
LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const
{
LLInventoryModel::cat_array_t* cat_array;
LLInventoryModel::item_array_t* item_array;
getDirectDescendentsOf(cat_id,cat_array,item_array);
LLMD5 item_name_hash;
if (!item_array)
{
item_name_hash.finalize();
return item_name_hash;
}
for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin();
iter != item_array->end();
iter++)
{
const LLViewerInventoryItem *item = (*iter);
if (!item)
continue;
item_name_hash.update(item->getName());
}
item_name_hash.finalize();
return item_name_hash;
}
// SJB: Added version to lock the arrays to catch potential logic bugs
void LLInventoryModel::lockDirectDescendentArrays(const LLUUID& cat_id,
cat_array_t*& categories,
@ -1254,6 +1278,9 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category)
//llinfos << "LLInventoryModel::addCategory()" << llendl;
if(category)
{
// try to localize default names first. See EXT-8319, EXT-7051.
category->localizeName();
// Insert category uniquely into the map
mCategoryMap[category->getUUID()] = category; // LLPointer will deref and delete the old one
//mInventory[category->getUUID()] = category;

View File

@ -41,6 +41,7 @@
#include "lluuid.h"
#include "llpermissionsflags.h"
#include "llstring.h"
#include "llmd5.h"
#include <map>
#include <set>
#include <string>
@ -194,6 +195,9 @@ public:
void getDirectDescendentsOf(const LLUUID& cat_id,
cat_array_t*& categories,
item_array_t*& items) const;
// Compute a hash of direct descendent names (for detecting child name changes)
LLMD5 hashDirectDescendentNames(const LLUUID& cat_id) const;
// Starting with the object specified, add its descendents to the
// array provided, but do not add the inventory object specified

View File

@ -676,7 +676,9 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
iter != mCategoryMap.end();
++iter)
{
LLViewerInventoryCategory* category = gInventory.getCategory((*iter).first);
const LLUUID& cat_id = (*iter).first;
LLViewerInventoryCategory* category = gInventory.getCategory(cat_id);
if (!category)
continue;
@ -691,7 +693,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
// Check number of known descendents to find out whether it has changed.
LLInventoryModel::cat_array_t* cats;
LLInventoryModel::item_array_t* items;
gInventory.getDirectDescendentsOf((*iter).first, cats, items);
gInventory.getDirectDescendentsOf(cat_id, cats, items);
if (!cats || !items)
{
llwarns << "Category '" << category->getName() << "' descendents corrupted, fetch failed." << llendl;
@ -703,20 +705,33 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
continue;
}
const S32 current_num_known_descendents = cats->count() + items->count();
LLCategoryData cat_data = (*iter).second;
bool cat_changed = false;
// If category version or descendents count has changed
// update category data in mCategoryMap and fire a callback.
// update category data in mCategoryMap
if (version != cat_data.mVersion || current_num_known_descendents != cat_data.mDescendentsCount)
{
cat_data.mVersion = version;
cat_data.mDescendentsCount = current_num_known_descendents;
cat_data.mCallback();
cat_changed = true;
}
// If any item names have changed, update the name hash
LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
if (cat_data.mItemNameHash != item_name_hash)
{
cat_data.mItemNameHash = item_name_hash;
cat_changed = true;
}
// If anything has changed above, fire the callback.
if (cat_changed)
cat_data.mCallback();
}
}

View File

@ -34,6 +34,7 @@
#define LL_LLINVENTORYOBSERVERS_H
#include "lluuid.h"
#include "llmd5.h"
#include <string>
#include <vector>
@ -298,11 +299,14 @@ protected:
: mCallback(cb)
, mVersion(version)
, mDescendentsCount(num_descendents)
{}
{
mItemNameHash.finalize();
}
callback_t mCallback;
S32 mVersion;
S32 mDescendentsCount;
LLMD5 mItemNameHash;
};
typedef std::map<LLUUID, LLCategoryData> category_map_t;

View File

@ -790,7 +790,7 @@ void LLInventoryPanel::doToSelected(const LLSD& userdata)
void LLInventoryPanel::doCreate(const LLSD& userdata)
{
menu_create_inventory_item(mFolderRoot, LLFolderBridge::sSelf, userdata);
menu_create_inventory_item(mFolderRoot, LLFolderBridge::sSelf.get(), userdata);
}
bool LLInventoryPanel::beginIMSession()

View File

@ -58,6 +58,7 @@
#endif
#include "llsecapi.h"
#include "llstartup.h"
#include "llmachineid.h"
static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback";
static const char * const TOS_LISTENER_NAME = "lllogininstance_tos";
@ -165,22 +166,24 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
// (re)initialize the request params with creds.
LLSD request_params = user_credential->getLoginParams();
char hashed_mac_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
LLMD5 hashed_mac;
unsigned char MACAddress[MAC_ADDRESS_BYTES];
if(LLUUID::getNodeID(MACAddress) == 0) {
llerrs << "Failed to get node id; cannot uniquely identify this machine." << llendl;
char hashed_unique_id_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
LLMD5 hashed_unique_id;
unsigned char unique_id[MAC_ADDRESS_BYTES];
if(LLUUID::getNodeID(unique_id) == 0) {
if(LLMachineID::getUniqueID(unique_id, sizeof(unique_id)) == 0) {
llerrs << "Failed to get an id; cannot uniquely identify this machine." << llendl;
}
}
hashed_mac.update( MACAddress, MAC_ADDRESS_BYTES );
hashed_mac.finalize();
hashed_mac.hex_digest(hashed_mac_string);
hashed_unique_id.update(unique_id, MAC_ADDRESS_BYTES);
hashed_unique_id.finalize();
hashed_unique_id.hex_digest(hashed_unique_id_string);
request_params["start"] = construct_start_string();
request_params["skipoptional"] = mSkipOptionalUpdate;
request_params["agree_to_tos"] = false; // Always false here. Set true in
request_params["read_critical"] = false; // handleTOSResponse
request_params["last_exec_event"] = mLastExecEvent;
request_params["mac"] = hashed_mac_string;
request_params["mac"] = hashed_unique_id_string;
request_params["version"] = gCurrentVersion; // Includes channel name
request_params["channel"] = gSavedSettings.getString("VersionChannelName");
request_params["id0"] = mSerialNumber;

View File

@ -83,6 +83,16 @@ LLFloaterMove::LLFloaterMove(const LLSD& key)
{
}
LLFloaterMove::~LLFloaterMove()
{
// Ensure LLPanelStandStopFlying panel is not among floater's children. See EXT-8458.
setVisible(FALSE);
// Otherwise it can be destroyed and static pointer in LLPanelStandStopFlying::getInstance() will become invalid.
// Such situation was possible when LLFloaterReg returns "dead" instance of floater.
// Should not happen after LLFloater::destroy was modified to remove "dead" instances from LLFloaterReg.
}
// virtual
BOOL LLFloaterMove::postBuild()
{

View File

@ -51,7 +51,7 @@ class LLFloaterMove
private:
LLFloaterMove(const LLSD& key);
~LLFloaterMove() {}
~LLFloaterMove();
public:
/*virtual*/ BOOL postBuild();

View File

@ -317,9 +317,19 @@ void LLGestureComboList::refreshGestures()
if (gestures)
{
S32 index = gestures->getSelectedValue().asInteger();
if(index > 0)
gesture = mGestures.at(index);
S32 sel_index = gestures->getFirstSelectedIndex();
if (sel_index != 0)
{
S32 index = gestures->getSelectedValue().asInteger();
if (index<0 || index >= (S32)mGestures.size())
{
llwarns << "out of range gesture access" << llendl;
}
else
{
gesture = mGestures.at(index);
}
}
}
if(gesture && LLGestureMgr::instance().isGesturePlaying(gesture))
@ -335,13 +345,13 @@ void LLGestureComboList::onCommitGesture()
LLCtrlListInterface* gestures = getListInterface();
if (gestures)
{
S32 index = gestures->getFirstSelectedIndex();
if (index == 0)
S32 sel_index = gestures->getFirstSelectedIndex();
if (sel_index == 0)
{
return;
}
index = gestures->getSelectedValue().asInteger();
S32 index = gestures->getSelectedValue().asInteger();
if (mViewAllItemIndex == index)
{
@ -357,13 +367,20 @@ void LLGestureComboList::onCommitGesture()
return;
}
LLMultiGesture* gesture = mGestures.at(index);
if(gesture)
if (index<0 || index >= (S32)mGestures.size())
{
LLGestureMgr::instance().playGesture(gesture);
if(!gesture->mReplaceText.empty())
llwarns << "out of range gesture index" << llendl;
}
else
{
LLMultiGesture* gesture = mGestures.at(index);
if(gesture)
{
LLNearbyChatBar::sendChatFromViewer(gesture->mReplaceText, CHAT_TYPE_NORMAL, FALSE);
LLGestureMgr::instance().playGesture(gesture);
if(!gesture->mReplaceText.empty())
{
LLNearbyChatBar::sendChatFromViewer(gesture->mReplaceText, CHAT_TYPE_NORMAL, FALSE);
}
}
}
}
@ -374,6 +391,13 @@ LLGestureComboList::~LLGestureComboList()
LLGestureMgr::instance().removeObserver(this);
}
LLCtrlListInterface* LLGestureComboList::getListInterface()
{
LLCtrlListInterface *result = mList;
llassert((LLCtrlListInterface*)mList==result);
return mList;
};
LLNearbyChatBar::LLNearbyChatBar()
: LLPanel()
, mChatBox(NULL)

View File

@ -68,7 +68,7 @@ public:
~LLGestureComboList();
LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)mList; };
LLCtrlListInterface* getListInterface();
virtual void showList();
virtual void hideList();
virtual BOOL handleKeyHere(KEY key, MASK mask);

View File

@ -40,6 +40,7 @@
LLOutfitObserver::LLOutfitObserver() :
mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN)
{
mItemNameHash.finalize();
gInventory.addObserver(this);
}
@ -87,13 +88,24 @@ bool LLOutfitObserver::checkCOF()
if (cof.isNull())
return false;
bool cof_changed = false;
LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cof);
if (item_name_hash != mItemNameHash)
{
cof_changed = true;
mItemNameHash = item_name_hash;
}
S32 cof_version = getCategoryVersion(cof);
if (cof_version != mCOFLastVersion)
{
cof_changed = true;
mCOFLastVersion = cof_version;
}
if (cof_version == mCOFLastVersion)
if (!cof_changed)
return false;
mCOFLastVersion = cof_version;
// dirtiness state should be updated before sending signal
LLAppearanceMgr::getInstance()->updateIsDirty();
mCOFChanged();

View File

@ -34,6 +34,7 @@
#define LL_OUTFITOBSERVER_H
#include "llsingleton.h"
#include "llmd5.h"
/**
* Outfit observer facade that provides simple possibility to subscribe on
@ -84,6 +85,8 @@ protected:
bool mLastOutfitDirtiness;
LLMD5 mItemNameHash;
private:
signal_t mBOFReplaced;
signal_t mBOFChanged;

View File

@ -665,7 +665,18 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata)
}
if (command_name == "wear")
{
return !gAgentWearables.isCOFChangeInProgress();
if (gAgentWearables.isCOFChangeInProgress())
{
return false;
}
if (hasItemSelected())
{
return canWearSelected();
}
// outfit selected
return LLAppearanceMgr::getCanAddToCOF(mSelectedOutfitUUID);
}
if (command_name == "take_off")
{
@ -677,6 +688,7 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata)
if (command_name == "wear_add")
{
// *TODO: do we ever get here?
if (gAgentWearables.isCOFChangeInProgress())
{
return false;
@ -984,6 +996,26 @@ bool LLOutfitsList::canTakeOffSelected()
return false;
}
bool LLOutfitsList::canWearSelected()
{
uuid_vec_t selected_items;
getSelectedItemsUUIDs(selected_items);
for (uuid_vec_t::const_iterator it = selected_items.begin(); it != selected_items.end(); ++it)
{
const LLUUID& id = *it;
// Check whether the item is worn.
if (!get_can_item_be_worn(id))
{
return false;
}
}
// All selected items can be worn.
return true;
}
void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
{
LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);

View File

@ -183,6 +183,11 @@ private:
*/
bool canTakeOffSelected();
/**
* Returns true if all selected items can be worn.
*/
bool canWearSelected();
void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
void onCOFChanged();

View File

@ -47,6 +47,7 @@
#include "llvoavatarself.h"
#include "lltexteditor.h"
#include "lltextbox.h"
#include "llaccordionctrl.h"
#include "llaccordionctrltab.h"
#include "llagentwearables.h"
#include "llscrollingpanelparam.h"
@ -666,6 +667,35 @@ void LLPanelEditWearable::updateAvatarHeightLabel()
mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param);
}
void LLPanelEditWearable::onWearablePanelVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl)
{
if (in_visible_chain.asBoolean() && accordion_ctrl != NULL)
{
accordion_ctrl->expandDefaultTab();
}
}
void LLPanelEditWearable::setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel)
{
if (bodypart_panel != NULL)
{
LLAccordionCtrl* accordion_ctrl = bodypart_panel->getChild<LLAccordionCtrl>("wearable_accordion");
if (accordion_ctrl != NULL)
{
bodypart_panel->setVisibleCallback(
boost::bind(&LLPanelEditWearable::onWearablePanelVisibilityChange, this, _2, accordion_ctrl));
}
else
{
llwarns << "accordion_ctrl is NULL" << llendl;
}
}
else
{
llwarns << "bodypart_panel is NULL" << llendl;
}
}
// virtual
BOOL LLPanelEditWearable::postBuild()
@ -695,6 +725,14 @@ BOOL LLPanelEditWearable::postBuild()
mPanelEyes = getChild<LLPanel>("edit_eyes_panel");
mPanelHair = getChild<LLPanel>("edit_hair_panel");
// Setting the visibility callback is applied only to the bodyparts panel
// because currently they are the only ones whose 'wearable_accordion' has
// multiple accordion tabs (see EXT-8164 for details).
setWearablePanelVisibilityChangeCallback(mPanelShape);
setWearablePanelVisibilityChangeCallback(mPanelSkin);
setWearablePanelVisibilityChangeCallback(mPanelEyes);
setWearablePanelVisibilityChangeCallback(mPanelHair);
//clothes
mPanelShirt = getChild<LLPanel>("edit_shirt_panel");
mPanelPants = getChild<LLPanel>("edit_pants_panel");
@ -786,7 +824,7 @@ BOOL LLPanelEditWearable::isDirty() const
if (mWearablePtr)
{
if (mWearablePtr->isDirty() ||
mWearablePtr->getName().compare(mNameEditor->getText()) != 0)
mWearableItem->getName().compare(mNameEditor->getText()) != 0)
{
isDirty = TRUE;
}
@ -839,7 +877,7 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r
if( !wearable_name.empty() )
{
mNameEditor->setText(wearable_name);
saveChanges();
saveChanges(true);
}
}
}
@ -896,7 +934,7 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
{
// Set the new version
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID());
if( image->getID().isNull() )
if( image->getID() == IMG_DEFAULT )
{
image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
}
@ -971,7 +1009,7 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type)
}
}
void LLPanelEditWearable::saveChanges()
void LLPanelEditWearable::saveChanges(bool force_save_as)
{
if (!mWearablePtr || !isDirty())
{
@ -980,16 +1018,18 @@ void LLPanelEditWearable::saveChanges()
}
U32 index = gAgentWearables.getWearableIndex(mWearablePtr);
if (mWearablePtr->getName().compare(mNameEditor->getText()) != 0)
std::string new_name = mNameEditor->getText();
if (force_save_as)
{
// the name of the wearable has changed, re-save wearable with new name
LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(),false);
gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, mNameEditor->getText(), FALSE);
gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, FALSE);
mNameEditor->setText(mWearableItem->getName());
}
else
{
gAgentWearables.saveWearable(mWearablePtr->getType(), index);
gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name);
}
}
@ -1002,7 +1042,7 @@ void LLPanelEditWearable::revertChanges()
}
mWearablePtr->revertValues();
mNameEditor->setText(mWearablePtr->getName());
mNameEditor->setText(mWearableItem->getName());
updatePanelPickerControls(mWearablePtr->getType());
updateTypeSpecificControls(mWearablePtr->getType());
gAgentAvatarp->wearableUpdated(mWearablePtr->getType(), FALSE);
@ -1048,7 +1088,7 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
mDescTitle->setText(description_title);
// set name
mNameEditor->setText(wearable->getName());
mNameEditor->setText(mWearableItem->getName());
updatePanelPickerControls(type);
updateTypeSpecificControls(type);

View File

@ -39,6 +39,7 @@
#include "llvoavatardefines.h"
#include "llwearabletype.h"
class LLAccordionCtrl;
class LLCheckBoxCtrl;
class LLWearable;
class LLTextBox;
@ -63,7 +64,7 @@ public:
LLWearable* getWearable() { return mWearablePtr; }
void setWearable(LLWearable *wearable);
void saveChanges();
void saveChanges(bool force_save_as = false);
void revertChanges();
void showDefaultSubpart();
@ -113,6 +114,10 @@ private:
// updates avatar height label
void updateAvatarHeightLabel();
void onWearablePanelVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl);
void setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel);
// the pointer to the wearable we're editing. NULL means we're not editing a wearable.
LLWearable *mWearablePtr;
LLViewerInventoryItem* mWearableItem;

View File

@ -182,6 +182,11 @@ BOOL LLPanelGroup::postBuild()
LLPanelGroupTab* panel_notices = findChild<LLPanelGroupTab>("group_notices_tab_panel");
LLPanelGroupTab* panel_land = findChild<LLPanelGroupTab>("group_land_tab_panel");
if (LLAccordionCtrl* accordion_ctrl = getChild<LLAccordionCtrl>("groups_accordion"))
{
setVisibleCallback(boost::bind(&LLPanelGroup::onVisibilityChange, this, _2, accordion_ctrl));
}
if(panel_general) mTabs.push_back(panel_general);
if(panel_roles) mTabs.push_back(panel_roles);
if(panel_notices) mTabs.push_back(panel_notices);
@ -305,6 +310,13 @@ void LLPanelGroup::onBtnCancel()
onBackBtnClick();
}
void LLPanelGroup::onVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl)
{
if (in_visible_chain.asBoolean() && accordion_ctrl != NULL)
{
accordion_ctrl->expandDefaultTab();
}
}
void LLPanelGroup::changed(LLGroupChange gc)
{

View File

@ -42,6 +42,7 @@ class LLOfferInfo;
const S32 UPDATE_MEMBERS_PER_FRAME = 500;
// Forward declares
class LLAccordionCtrl;
class LLPanelGroupTab;
class LLTabContainer;
class LLAgent;
@ -102,6 +103,7 @@ protected:
void onBackBtnClick();
void onBtnJoin();
void onBtnCancel();
void onVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl);
static void onBtnApply(void*);
static void onBtnRefresh(void*);
@ -126,7 +128,6 @@ protected:
LLButton* mButtonJoin;
LLUICtrl* mJoinText;
};
class LLPanelGroupTab : public LLPanel

View File

@ -1432,10 +1432,10 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg,
// text.append(llformat( "%-24s %6d %6d \n", LLTrans::getString("GroupMoneyDebits").c_str(), total_debits, (S32)floor((F32)total_debits/(F32)non_exempt_members)));
// text.append(llformat( "%-24s %6d %6d \n", LLTrans::getString("GroupMoneyTotal").c_str(), total_credits + total_debits, (S32)floor((F32)(total_credits + total_debits)/(F32)non_exempt_members)));
text.append( " Group\n");
text.append(llformat( "%-24s %6d\n", "Credits", total_credits));
text.append(llformat( "%-24s %6d\n", "Debits", total_debits));
text.append(llformat( "%-24s %6d\n", "Total", total_credits + total_debits));
text.append(llformat( "%s\n", LLTrans::getString("GroupColumn").c_str()));
text.append(llformat( "%-24s %6d\n", LLTrans::getString("GroupMoneyCredits").c_str(), total_credits));
text.append(llformat( "%-24s %6d\n", LLTrans::getString("GroupMoneyDebits").c_str(), total_debits));
text.append(llformat( "%-24s %6d\n", LLTrans::getString("GroupMoneyTotal").c_str(), total_credits + total_debits));
if ( mImplementationp->mTextEditorp )
{

View File

@ -51,6 +51,7 @@
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltexteditor.h"
#include "lltrans.h"
#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llfocusmgr.h"
@ -587,7 +588,7 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
row["columns"][1]["column"] = "action";
row["columns"][1]["type"] = "text";
row["columns"][1]["value"] = action_set->mActionSetData->mName;
row["columns"][1]["value"] = LLTrans::getString(action_set->mActionSetData->mName);
row["columns"][1]["font"]["name"] = "SANSSERIF_SMALL";
@ -1593,6 +1594,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
LLUIString donated = getString("donation_area");
S32 i = 0;
for( ; mMemberProgress != end && i<UPDATE_MEMBERS_PER_FRAME;
@ -1614,9 +1616,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
if (add_member)
{
// Build the donated tier string.
std::ostringstream donated;
donated << mMemberProgress->second->getContribution() << " sq. m.";
donated.setArg("[AREA]", llformat("%d", mMemberProgress->second->getContribution()));
LLSD row;
row["id"] = (*mMemberProgress).first;
@ -1625,7 +1625,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
// value is filled in by name list control
row["columns"][1]["column"] = "donated";
row["columns"][1]["value"] = donated.str();
row["columns"][1]["value"] = donated.getString();
row["columns"][2]["column"] = "online";
row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();

View File

@ -566,7 +566,8 @@ void LLPanelMainInventory::draw()
void LLPanelMainInventory::updateItemcountText()
{
LLLocale locale(LLLocale::USER_LOCALE);
// *TODO: Calling setlocale() on each frame may be inefficient.
LLLocale locale(LLStringUtil::getLocale());
std::string item_count_string;
LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());

View File

@ -750,8 +750,6 @@ void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
std::vector<std::string> items;
std::vector<std::string> disabled_items;
items.push_back(std::string("--no options--"));
disabled_items.push_back(std::string("--no options--"));
hide_context_entries(menu, items, disabled_items);
}

View File

@ -923,6 +923,18 @@ bool LLPanelOutfitEdit::switchPanels(LLPanel* switch_from_panel, LLPanel* switch
return false;
}
void LLPanelOutfitEdit::resetAccordionState()
{
if (mCOFWearables != NULL)
{
mCOFWearables->expandDefaultAccordionTab();
}
else
{
llwarns << "mCOFWearables is NULL" << llendl;
}
}
void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)
{
if(!mGearMenu)

View File

@ -182,6 +182,8 @@ public:
*/
bool switchPanels(LLPanel* switch_from_panel, LLPanel* switch_to_panel);
void resetAccordionState();
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,

View File

@ -337,7 +337,7 @@ bool LLPanelOutfitsInventory::isCOFPanelActive() const
void LLPanelOutfitsInventory::setWearablesLoading(bool val)
{
mListCommands->childSetEnabled("wear_btn", !val);
updateVerbs();
}
void LLPanelOutfitsInventory::onWearablesLoaded()

View File

@ -60,7 +60,8 @@ LLPanelPlaceInfo::LLPanelPlaceInfo()
mScrollingPanelWidth(0),
mInfoType(UNKNOWN),
mScrollingPanel(NULL),
mScrollContainer(NULL)
mScrollContainer(NULL),
mDescEditor(NULL)
{}
//virtual
@ -248,6 +249,16 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
// virtual
void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
{
// This if was added to force collapsing description textbox on Windows at the beginning of reshape
// (the only case when reshape is skipped here is when it's caused by this textbox, so called_from_parent is FALSE)
// This way it is consistent with Linux where topLost collapses textbox at the beginning of reshape.
// On windows it collapsed only after reshape which caused EXT-8342.
if(called_from_parent)
{
if(mDescEditor) mDescEditor->onTopLost();
}
LLPanel::reshape(width, height, called_from_parent);
if (!mScrollContainer || !mScrollingPanel)

View File

@ -79,7 +79,8 @@ LLPanelPlaceProfile::LLPanelPlaceProfile()
: LLPanelPlaceInfo(),
mForSalePanel(NULL),
mYouAreHerePanel(NULL),
mSelectedParcelID(-1)
mSelectedParcelID(-1),
mAccordionCtrl(NULL)
{}
// virtual
@ -139,6 +140,7 @@ BOOL LLPanelPlaceProfile::postBuild()
mSubdivideText = getChild<LLTextEditor>("subdivide");
mResaleText = getChild<LLTextEditor>("resale");
mSaleToText = getChild<LLTextBox>("sale_to");
mAccordionCtrl = getChild<LLAccordionCtrl>("advanced_info_accordion");
icon_pg = getString("icon_PG");
icon_m = getString("icon_M");
@ -278,6 +280,11 @@ void LLPanelPlaceProfile::handleVisibilityChange(BOOL new_visibility)
parcel_mgr->deselectUnused();
}
}
if (mAccordionCtrl != NULL)
{
mAccordionCtrl->expandDefaultTab();
}
}
void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,

View File

@ -35,6 +35,7 @@
#include "llpanelplaceinfo.h"
class LLAccordionCtrl;
class LLIconCtrl;
class LLTextEditor;
@ -118,6 +119,7 @@ private:
LLTextEditor* mSubdivideText;
LLTextEditor* mResaleText;
LLTextBox* mSaleToText;
LLAccordionCtrl* mAccordionCtrl;
};
#endif // LL_LLPANELPLACEPROFILE_H

View File

@ -718,8 +718,8 @@ void LLPanelPlaces::onOverflowButtonClicked()
bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
if ((is_agent_place_info_visible ||
mPlaceInfoType == "remote_place" ||
mPlaceInfoType == "teleport_history") && mPlaceMenu != NULL)
mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE) && mPlaceMenu != NULL)
{
menu = mPlaceMenu;
@ -1089,6 +1089,8 @@ void LLPanelPlaces::updateVerbs()
if (is_place_info_visible)
{
mShowOnMapBtn->setEnabled(have_3d_pos);
if (is_agent_place_info_visible)
{
// We don't need to teleport to the current location

View File

@ -115,7 +115,7 @@ void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601
// repeat parent functionality
sSelf = this; // necessary for "New Folder" functionality
sSelf = getHandle(); // necessary for "New Folder" functionality
hide_context_entries(menu, items, disabled_items);
}

View File

@ -1625,7 +1625,17 @@ std::string LLPreviewGesture::getLabel(std::vector<std::string> labels)
result=LLTrans::getString("AnimFlagStart");
}
result.append(v_labels[1]);
// lets localize action value
std::string action = v_labels[1];
if ("None" == action)
{
action = LLTrans::getString("GestureActionNone");
}
else if ("until animations are done" == action)
{
action = LLFloaterReg::getInstance("preview_gesture")->getChild<LLCheckBoxCtrl>("wait_anim_check")->getLabel();
}
result.append(action);
return result;
}

View File

@ -87,7 +87,7 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key)
LLPreviewTexture::~LLPreviewTexture()
{
LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList, this) ;
LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
if( mLoadingFullImage )
{
@ -280,7 +280,7 @@ void LLPreviewTexture::saveAs()
mLoadingFullImage = TRUE;
getWindow()->incBusyCount();
mImage->setLoadedCallback( LLPreviewTexture::onFileLoadedForSave,
0, TRUE, FALSE, new LLUUID( mItemUUID ), this, &mCallbackTextureList );
0, TRUE, FALSE, new LLUUID( mItemUUID ), &mCallbackTextureList );
}
// virtual

View File

@ -190,13 +190,16 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
{
if (new_visibility.asBoolean())
{
if ((mOutfitEdit && mOutfitEdit->getVisible()) || (mEditWearable && mEditWearable->getVisible()))
bool is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
bool is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
if (is_outfit_edit_visible || is_wearable_edit_visible)
{
if (!gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement"))
{
gAgentCamera.changeCameraToCustomizeAvatar();
}
if (mEditWearable && mEditWearable->getVisible())
if (is_wearable_edit_visible)
{
LLWearable *wearable_ptr = mEditWearable->getWearable();
if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
@ -205,6 +208,11 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
showOutfitEditPanel();
}
}
if (is_outfit_edit_visible)
{
mOutfitEdit->resetAccordionState();
}
}
}
else
@ -283,6 +291,15 @@ void LLSidepanelAppearance::showOutfitsInventoryPanel()
void LLSidepanelAppearance::showOutfitEditPanel()
{
// Accordion's state must be reset in all cases except the one when user
// is returning back to the mOutfitEdit panel from the mEditWearable panel.
// The simplest way to control this is to check the visibility state of the mEditWearable
// BEFORE it is changed by the call to the toggleWearableEditPanel(FALSE, NULL, TRUE).
if (mEditWearable != NULL && !mEditWearable->getVisible() && mOutfitEdit != NULL)
{
mOutfitEdit->resetAccordionState();
}
togglMyOutfitsPanel(FALSE);
toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode
toggleOutfitEditPanel(TRUE);

View File

@ -33,10 +33,13 @@
#include "llsidepanelinventory.h"
#include "llagent.h"
#include "llappearancemgr.h"
#include "llavataractions.h"
#include "llbutton.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorypanel.h"
#include "lloutfitobserver.h"
#include "llpanelmaininventory.h"
#include "llsidepaneliteminfo.h"
#include "llsidepaneltaskinfo.h"
@ -98,6 +101,8 @@ BOOL LLSidepanelInventory::postBuild()
my_inventory_panel->addHideFolderType(LLFolderType::FT_LANDMARK);
my_inventory_panel->addHideFolderType(LLFolderType::FT_FAVORITE);
*/
LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLSidepanelInventory::updateVerbs, this));
}
// UI elements from item panel
@ -283,7 +288,7 @@ void LLSidepanelInventory::updateVerbs()
case LLInventoryType::IT_OBJECT:
case LLInventoryType::IT_ATTACHMENT:
mWearBtn->setVisible(TRUE);
mWearBtn->setEnabled(TRUE);
mWearBtn->setEnabled(get_can_item_be_worn(item->getLinkedUUID()));
mShopBtn->setVisible(FALSE);
break;
case LLInventoryType::IT_SOUND:

View File

@ -121,7 +121,7 @@ private:
protected:
LLViewerObject* getObject();
private:
LLViewerObject* mObject;
LLPointer<LLViewerObject> mObject;
LLObjectSelectionHandle mObjectSelection;
static LLSidepanelTaskInfo* sActivePanel;
};

View File

@ -158,6 +158,7 @@ void LLSurface::initClasses()
void LLSurface::setRegion(LLViewerRegion *regionp)
{
mRegionp = regionp;
mWaterObjp = NULL; // depends on regionp, needs recreating
}
// Assumes that arguments are powers of 2, and that
@ -958,6 +959,7 @@ LLSurfacePatch *LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const
LLSurfacePatch *LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const
{
llassert(mRegionp);
LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(pos_global);
return resolvePatchRegion(pos_region);
}

View File

@ -119,14 +119,16 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner,
S32 width, S32 height) :
// ORDER_LAST => must render these after the hints are created.
LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ),
mNeedsUpdate(TRUE),
mNeedsUpload(FALSE),
mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates
mNeedsUpload(FALSE),
mNumLowresUploads(0),
mNeedsUpdate(TRUE),
mNumLowresUpdates(0),
mTexLayerSet(owner)
{
LLTexLayerSetBuffer::sGLByteCount += getSize();
mNeedsUploadTimer.start();
mNeedsUpdateTimer.start();
}
LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
@ -165,8 +167,9 @@ void LLTexLayerSetBuffer::dumpTotalByteCount()
void LLTexLayerSetBuffer::requestUpdate()
{
conditionalRestartUploadTimer();
restartUpdateTimer();
mNeedsUpdate = TRUE;
mNumLowresUpdates = 0;
// If we're in the middle of uploading a baked texture, we don't care about it any more.
// When it's downloaded, ignore it.
mUploadID.setNull();
@ -196,6 +199,12 @@ void LLTexLayerSetBuffer::conditionalRestartUploadTimer()
}
}
void LLTexLayerSetBuffer::restartUpdateTimer()
{
mNeedsUpdateTimer.reset();
mNeedsUpdateTimer.start();
}
void LLTexLayerSetBuffer::cancelUpload()
{
mNeedsUpload = FALSE;
@ -229,25 +238,31 @@ BOOL LLTexLayerSetBuffer::needsRender()
llassert(mTexLayerSet->getAvatar() == gAgentAvatarp);
if (!isAgentAvatarValid()) return FALSE;
const BOOL upload_now = isReadyToUpload();
BOOL needs_update = (mNeedsUpdate || upload_now) && !gAgentAvatarp->mAppearanceAnimating;
if (needs_update)
const BOOL upload_now = mNeedsUpload && isReadyToUpload();
const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
// Don't render if we don't want to (or aren't ready to) upload or update.
if (!(update_now || upload_now))
{
BOOL invalid_skirt = gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT);
if (invalid_skirt)
{
// we were trying to create a skirt texture
// but we're no longer wearing a skirt...
needs_update = FALSE;
cancelUpload();
}
else
{
needs_update &= mTexLayerSet->isLocalTextureDataAvailable();
}
return FALSE;
}
return needs_update;
// Don't render if we're animating our appearance.
if (gAgentAvatarp->getIsAppearanceAnimating())
{
return FALSE;
}
// Don't render if we are trying to create a shirt texture but aren't wearing a skirt.
if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED &&
!gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT))
{
cancelUpload();
return FALSE;
}
// Render if we have at least minimal level of detail for each local texture.
return mTexLayerSet->isLocalTextureDataAvailable();
}
void LLTexLayerSetBuffer::preRender(BOOL clear_depth)
@ -272,11 +287,12 @@ BOOL LLTexLayerSetBuffer::render()
gGL.setColorMask(true, true);
// do we need to upload, and do we have sufficient data to create an uploadable composite?
// When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
const BOOL upload_now = isReadyToUpload();
// TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
const BOOL upload_now = mNeedsUpload && isReadyToUpload();
const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
BOOL success = TRUE;
// Composite the color data
LLGLSUIDefault gls_ui;
success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight );
@ -294,7 +310,7 @@ BOOL LLTexLayerSetBuffer::render()
if (mTexLayerSet->isVisible())
{
mTexLayerSet->getAvatar()->debugBakedTextureUpload(mTexLayerSet->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish.
readBackAndUpload();
doUpload();
}
else
{
@ -305,6 +321,11 @@ BOOL LLTexLayerSetBuffer::render()
}
}
}
if (update_now)
{
doUpdate();
}
// reset GL state
gGL.setColorMask(true, true);
@ -312,7 +333,6 @@ BOOL LLTexLayerSetBuffer::render()
// we have valid texture data now
mGLTexturep->setGLTextureCreated(true);
mNeedsUpdate = FALSE;
return success;
}
@ -339,16 +359,16 @@ BOOL LLTexLayerSetBuffer::uploadInProgress() const
BOOL LLTexLayerSetBuffer::isReadyToUpload() const
{
if (!mNeedsUpload) return FALSE; // Don't need to upload if we haven't requested one.
if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries.
if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites.
// If we requested an upload and have the final LOD ready, then upload.
const BOOL can_highest_lod = mTexLayerSet->isLocalTextureDataFinal();
if (can_highest_lod) return TRUE;
if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE;
const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureTimeout");
if (texture_timeout)
// Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure
// we aren't doing uploads too frequently.
const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
if (texture_timeout != 0)
{
// The timeout period increases exponentially between every lowres upload in order to prevent
// spamming the server with frequent uploads.
@ -359,10 +379,33 @@ BOOL LLTexLayerSetBuffer::isReadyToUpload() const
const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable();
if (has_lower_lod && is_upload_textures_timeout) return TRUE;
}
return FALSE;
}
BOOL LLTexLayerSetBuffer::updateImmediate()
BOOL LLTexLayerSetBuffer::isReadyToUpdate() const
{
// If we requested an update and have the final LOD ready, then update.
if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE;
// If we haven't done an update yet, then just do one now regardless of state of textures.
if (mNumLowresUpdates == 0) return TRUE;
// Update if we've hit a timeout. Unlike for uploads, we can make this timeout fairly small
// since render unnecessarily doesn't cost much.
const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedLocalTextureUpdateTimeout");
if (texture_timeout != 0)
{
// If we hit our timeout and have textures available at even lower resolution, then update.
const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout;
const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable();
if (has_lower_lod && is_update_textures_timeout) return TRUE;
}
return FALSE;
}
BOOL LLTexLayerSetBuffer::requestUpdateImmediate()
{
mNeedsUpdate = TRUE;
BOOL result = FALSE;
@ -377,7 +420,9 @@ BOOL LLTexLayerSetBuffer::updateImmediate()
return result;
}
void LLTexLayerSetBuffer::readBackAndUpload()
// Create the baked texture, send it out to the server, then wait for it to come
// back so we can switch to using it.
void LLTexLayerSetBuffer::doUpload()
{
llinfos << "Uploading baked " << mTexLayerSet->getBodyRegionName() << llendl;
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES);
@ -447,6 +492,7 @@ void LLTexLayerSetBuffer::readBackAndUpload()
LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp,
this->mTexLayerSet,
asset_id);
// upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.
mUploadID = asset_id;
// Upload the image
@ -490,12 +536,13 @@ void LLTexLayerSetBuffer::readBackAndUpload()
// Print out notification that we uploaded this texture.
if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
{
std::string lod_str = highest_lod ? "HighRes" : "LowRes";
const std::string lod_str = highest_lod ? "HighRes" : "LowRes";
LLSD args;
args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32());
args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32());
args["BODYREGION"] = mTexLayerSet->getBodyRegionName();
args["RESOLUTION"] = lod_str;
args["ACTION"] = "uploaded";
LLNotificationsUtil::add("AvatarRezSelfBakeNotification",args);
llinfos << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << llendl;
}
@ -520,6 +567,37 @@ void LLTexLayerSetBuffer::readBackAndUpload()
delete [] baked_color_data;
}
// Mostly bookkeeping; don't need to actually "do" anything since
// render() will actually do the update.
void LLTexLayerSetBuffer::doUpdate()
{
const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal();
if (highest_lod)
{
mNeedsUpdate = FALSE;
}
else
{
mNumLowresUpdates++;
}
restartUpdateTimer();
// Print out notification that we uploaded this texture.
if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
{
const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal();
const std::string lod_str = highest_lod ? "HighRes" : "LowRes";
LLSD args;
args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32());
args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32());
args["BODYREGION"] = mTexLayerSet->getBodyRegionName();
args["RESOLUTION"] = lod_str;
args["ACTION"] = "locally updated";
LLNotificationsUtil::add("AvatarRezSelfBakeNotification",args);
llinfos << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << llendl;
}
}
// static
void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
@ -931,7 +1009,7 @@ void LLTexLayerSet::setUpdatesEnabled( BOOL b )
void LLTexLayerSet::updateComposite()
{
createComposite();
mComposite->updateImmediate();
mComposite->requestUpdateImmediate();
}
LLTexLayerSetBuffer* LLTexLayerSet::getComposite()

View File

@ -270,47 +270,69 @@ class LLTexLayerSetBuffer : public LLViewerDynamicTexture
public:
LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);
virtual ~LLTexLayerSetBuffer();
public:
/*virtual*/ S8 getType() const;
virtual void preRender(BOOL clear_depth);
virtual void postRender(BOOL success);
virtual BOOL render();
BOOL updateImmediate();
BOOL isInitialized(void) const;
BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point
BOOL uploadNeeded() const; // We need to upload a new texture
BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result
/*virtual*/ BOOL needsRender();
void requestUpdate();
void requestUpload();
void cancelUpload();
BOOL render(S32 x, S32 y, S32 width, S32 height);
void readBackAndUpload();
static void onTextureUploadComplete(const LLUUID& uuid,
void* userdata,
S32 result, LLExtStat ext_status);
static void dumpTotalByteCount();
const std::string dumpTextureInfo() const;
virtual void restoreGLTexture();
virtual void destroyGLTexture();
protected:
void pushProjection() const;
void popProjection() const;
BOOL isReadyToUpload() const;
void conditionalRestartUploadTimer();
private:
LLTexLayerSet* const mTexLayerSet;
BOOL mNeedsUpdate; // whether we need to update our baked textures
BOOL mNeedsUpload; // whether we need to send our baked textures to the server
U32 mNumLowresUploads; // number of times we've sent a lowres version of our baked textures to the server
BOOL mUploadPending; // whether we have received back the new baked textures
LLUUID mUploadID; // the current upload process (null if none). Used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.
static S32 sGLByteCount;
LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested
//--------------------------------------------------------------------
// Render
//--------------------------------------------------------------------
public:
/*virtual*/ BOOL needsRender();
protected:
BOOL render(S32 x, S32 y, S32 width, S32 height);
virtual void preRender(BOOL clear_depth);
virtual void postRender(BOOL success);
virtual BOOL render();
//--------------------------------------------------------------------
// Uploads
//--------------------------------------------------------------------
public:
void requestUpload();
void cancelUpload();
BOOL uploadNeeded() const; // We need to upload a new texture
BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result
BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point
static void onTextureUploadComplete(const LLUUID& uuid,
void* userdata,
S32 result, LLExtStat ext_status);
protected:
BOOL isReadyToUpload() const;
void doUpload(); // Does a read back and upload.
void conditionalRestartUploadTimer();
private:
BOOL mNeedsUpload; // Whether we need to send our baked textures to the server
U32 mNumLowresUploads; // Number of times we've sent a lowres version of our baked textures to the server
BOOL mUploadPending; // Whether we have received back the new baked textures
LLUUID mUploadID; // The current upload process (null if none).
LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested and performed.
//--------------------------------------------------------------------
// Updates
//--------------------------------------------------------------------
public:
void requestUpdate();
BOOL requestUpdateImmediate();
protected:
BOOL isReadyToUpdate() const;
void doUpdate();
void restartUpdateTimer();
private:
BOOL mNeedsUpdate; // Whether we need to locally update our baked textures
U32 mNumLowresUpdates; // Number of times we've locally updated with lowres version of our baked textures
LLFrameTimer mNeedsUpdateTimer; // Tracks time since update was requested and performed.
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -180,7 +180,7 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
{
if (gAgentCamera.cameraCustomizeAvatar())
if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
{
upload_bake = FALSE;
}

View File

@ -391,6 +391,7 @@ bool LLTextureCacheRemoteWorker::doRead()
}
else
{
//llinfos << "texture " << mID.asString() << " found in local_assets" << llendl;
mImageSize = local_size;
mImageLocal = TRUE;
}

View File

@ -175,6 +175,8 @@ protected:
BOOL mNoCopyTextureSelected;
F32 mContextConeOpacity;
LLSaveFolderState mSavedFolderState;
BOOL mSelectedItemPinned;
};
LLFloaterTexturePicker::LLFloaterTexturePicker(
@ -197,7 +199,8 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
mFilterEdit(NULL),
mImmediateFilterPermMask(immediate_filter_perm_mask),
mNonImmediateFilterPermMask(non_immediate_filter_perm_mask),
mContextConeOpacity(0.f)
mContextConeOpacity(0.f),
mSelectedItemPinned( FALSE )
{
mCanApplyImmediately = can_apply_immediately;
LLUICtrlFactory::getInstance()->buildFloater(this,"floater_texture_ctrl.xml",NULL);
@ -593,6 +596,31 @@ void LLFloaterTexturePicker::draw()
mTentativeLabel->setVisible( TRUE );
drawChild(mTentativeLabel);
}
if (mSelectedItemPinned) return;
LLFolderView* folder_view = mInventoryPanel->getRootFolder();
if (!folder_view) return;
LLInventoryFilter* filter = folder_view->getFilter();
if (!filter) return;
bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() &&
filter->isNotDefault();
// After inventory panel filter is applied we have to update
// constraint rect for the selected item because of folder view
// AutoSelectOverride set to TRUE. We force PinningSelectedItem
// flag to FALSE state and setting filter "dirty" to update
// scroll container to show selected item (see LLFolderView::doIdle()).
if (!is_filter_active && !mSelectedItemPinned)
{
folder_view->setPinningSelectedItem(mSelectedItemPinned);
folder_view->dirtyFilter();
folder_view->arrangeFromRoot();
mSelectedItemPinned = TRUE;
}
}
}

View File

@ -290,8 +290,8 @@ class HTTPGetResponder : public LLCurl::Responder
{
LOG_CLASS(HTTPGetResponder);
public:
HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset)
: mFetcher(fetcher), mID(id), mStartTime(startTime), mRequestedSize(requestedSize), mOffset(offset)
HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset, bool redir)
: mFetcher(fetcher), mID(id), mStartTime(startTime), mRequestedSize(requestedSize), mOffset(offset), mFollowRedir(redir)
{
}
~HTTPGetResponder()
@ -344,6 +344,11 @@ public:
llwarns << "Worker not found: " << mID << llendl;
}
}
virtual bool followRedir()
{
return mFollowRedir;
}
private:
LLTextureFetch* mFetcher;
@ -351,6 +356,7 @@ private:
U64 mStartTime;
S32 mRequestedSize;
U32 mOffset;
bool mFollowRedir;
};
//////////////////////////////////////////////////////////////////////////////
@ -897,7 +903,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
std::vector<std::string> headers;
headers.push_back("Accept: image/x-j2c");
res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize,
new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset));
new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset, true));
}
if (!res)
{
@ -945,17 +951,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
max_attempts = mHTTPFailCount+1; // Keep retrying
LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
}
else if(mGetStatus >= HTTP_MULTIPLE_CHOICES && mGetStatus < HTTP_BAD_REQUEST) //http re-direct
{
++mHTTPFailCount;
max_attempts = 5 ; //try at most 5 times to avoid infinite redirection loop.
llwarns << "HTTP GET failed because of redirection: " << mUrl
<< " Status: " << mGetStatus << " Reason: '" << mGetReason << llendl ;
//assign to the new url
mUrl = mGetReason ;
}
else
{
const S32 HTTP_MAX_RETRY_COUNT = 3;

View File

@ -450,14 +450,14 @@ void LLAvatarTexBar::draw()
text_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
line_num++;
}
const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureTimeout");
const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel");
LLColor4 header_color(1.f, 1.f, 1.f, 0.9f);
const std::string texture_timeout_str = texture_timeout ? llformat("%d",texture_timeout) : "Disabled";
const std::string override_tex_discard_level_str = override_tex_discard_level ? llformat("%d",override_tex_discard_level) : "Disabled";
std::string header_text = llformat("[ Timeout('AvatarBakedTextureTimeout'):%s ] [ LOD_Override('TextureDiscardLevel'):%s ]", texture_timeout_str.c_str(), override_tex_discard_level_str.c_str());
std::string header_text = llformat("[ Timeout('AvatarBakedTextureUploadTimeout'):%s ] [ LOD_Override('TextureDiscardLevel'):%s ]", texture_timeout_str.c_str(), override_tex_discard_level_str.c_str());
LLFontGL::getFontMonospace()->renderUTF8(header_text, 0, l_offset, v_offset + line_height*line_num,
header_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
line_num++;

View File

@ -147,7 +147,7 @@ void LLVisualParamHint::requestHintUpdates( LLVisualParamHint* exception1, LLVis
BOOL LLVisualParamHint::needsRender()
{
return mNeedsUpdate && mDelayFrames-- <= 0 && !gAgentAvatarp->mAppearanceAnimating && mAllowsUpdates;
return mNeedsUpdate && mDelayFrames-- <= 0 && !gAgentAvatarp->getIsAppearanceAnimating() && mAllowsUpdates;
}
void LLVisualParamHint::preRender(BOOL clear_depth)

View File

@ -84,7 +84,7 @@ void LLViewerAttachMenu::populateMenus(const std::string& attach_to_menu_name, c
LLSD cbparams;
cbparams["index"] = curiter->first;
cbparams["label"] = attachment->getName();
cbparams["label"] = p.name;
p.on_click.function_name = "Object.Attach";
p.on_click.parameter = LLSD(attachment->getName());
p.on_enable.function_name = "Attachment.Label";

View File

@ -67,7 +67,7 @@
#include "llsidepanelappearance.h"
///----------------------------------------------------------------------------
/// Helper class to store special inventory item names
/// Helper class to store special inventory item names and their localized values.
///----------------------------------------------------------------------------
class LLLocalizedInventoryItemsDictionary : public LLSingleton<LLLocalizedInventoryItemsDictionary>
{
@ -93,8 +93,10 @@ public:
mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo");
mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture");
mInventoryItemsDict["New Script"] = LLTrans::getString("New Script");
mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder");
mInventoryItemsDict["New Note"] = LLTrans::getString("New Note");
mInventoryItemsDict["Contents"] = LLTrans::getString("Contents");
mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture");
@ -108,7 +110,7 @@ public:
//male
mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me");
mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost");
mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319
mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss");
mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo");
mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored");
@ -120,19 +122,47 @@ public:
mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow");
//female
mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle");
mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry");
mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed");
mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me");
mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost");
mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319
mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss");
mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo");
mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored");
mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey");
mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby");
mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh");
mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good");
mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here");
mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please");
mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed");
mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug");
mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out");
mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow");
}
/**
* Finds passed name in dictionary and replaces it with found localized value.
*
* @param object_name - string to be localized.
* @return true if passed name was found and localized, false otherwise.
*/
bool localizeInventoryObjectName(std::string& object_name)
{
LL_DEBUGS("InventoryLocalize") << "Searching for localization: " << object_name << LL_ENDL;
std::map<std::string, std::string>::const_iterator dictionary_iter = mInventoryItemsDict.find(object_name);
bool found = dictionary_iter != mInventoryItemsDict.end();
if(found)
{
object_name = dictionary_iter->second;
LL_DEBUGS("InventoryLocalize") << "Found, new name is: " << object_name << LL_ENDL;
}
return found;
}
};
@ -391,16 +421,7 @@ BOOL LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* bloc
{
BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num);
std::string localized_str;
std::map<std::string, std::string>::const_iterator dictionary_iter;
dictionary_iter = LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.find(mName);
if(dictionary_iter != LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.end())
{
mName = dictionary_iter->second;
}
LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName);
mIsComplete = TRUE;
return rv;
@ -820,6 +841,11 @@ void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type)
gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
}
void LLViewerInventoryCategory::localizeName()
{
LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName);
}
///----------------------------------------------------------------------------
/// Local function definitions
///----------------------------------------------------------------------------
@ -895,7 +921,7 @@ void ModifiedCOFCallback::fire(const LLUUID& inv_item)
gAgentWearables.editWearableIfRequested(inv_item);
// TODO: camera mode may not be changed if a debug setting is tweaked
if( gAgentCamera.cameraCustomizeAvatar() )
if(gAgentCamera.cameraCustomizeAvatar())
{
// If we're in appearance editing mode, the current tab may need to be refreshed
LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(LLSideTray::getInstance()->getPanel("sidepanel_appearance"));
@ -1132,6 +1158,14 @@ void move_inventory_item(
void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecard_inv_id, const LLInventoryItem *src, U32 callback_id)
{
if (NULL == src)
{
LL_WARNS("copy_inventory_from_notecard") << "Null pointer to item was passed for object_id "
<< object_id << " and notecard_inv_id "
<< notecard_inv_id << LL_ENDL;
return;
}
LLViewerRegion* viewer_region = NULL;
LLViewerObject* vo = NULL;
if (object_id.notNull() && (vo = gObjectList.findObject(object_id)) != NULL)
@ -1154,6 +1188,16 @@ void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecar
return;
}
// check capability to prevent a crash while LL_ERRS in LLCapabilityListener::capListener. See EXT-8459.
std::string url = viewer_region->getCapability("CopyInventoryFromNotecard");
if (url.empty())
{
LL_WARNS("copy_inventory_from_notecard") << "There is no 'CopyInventoryFromNotecard' capability"
<< " for region: " << viewer_region->getName()
<< LL_ENDL;
return;
}
LLSD request, body;
body["notecard-id"] = notecard_inv_id;
body["object-id"] = object_id;

Some files were not shown because too many files have changed in this diff Show More