master
Andrew A. de Laix 2010-06-09 15:47:37 -07:00
commit f2f7f7b3bb
285 changed files with 5031 additions and 2548 deletions

View File

@ -60,3 +60,4 @@ glob:indra/newview/teleport_history.txt
glob:indra/newview/search_history.txt
glob:indra/newview/filters.xml
glob:indra/newview/avatar_icons_cache.txt
glob:indra/newview/avatar_lad.log

View File

@ -323,6 +323,8 @@ Khyota Wulluf
VWR-8885
VWR-9256
VWR-9966
Kitty Barnett
VWR-19699
Kunnis Basiat
VWR-82
VWR-102

View File

@ -388,27 +388,6 @@ void LLCharacter::clearVisualParamWeights()
}
}
//-----------------------------------------------------------------------------
// BOOL visualParamWeightsAreDefault()
//-----------------------------------------------------------------------------
BOOL LLCharacter::visualParamWeightsAreDefault()
{
for (LLVisualParam *param = getFirstVisualParam();
param;
param = getNextVisualParam())
{
if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
{
if (param->getWeight() != param->getDefaultWeight())
return false;
}
}
return true;
}
//-----------------------------------------------------------------------------
// getVisualParam()
//-----------------------------------------------------------------------------

View File

@ -212,12 +212,9 @@ public:
F32 getVisualParamWeight(const char* param_name);
F32 getVisualParamWeight(S32 index);
// set all morph weights to 0
// set all morph weights to defaults
void clearVisualParamWeights();
// see if all the weights are default
BOOL visualParamWeightsAreDefault();
// visual parameter accessors
LLVisualParam* getFirstVisualParam()
{
@ -231,6 +228,21 @@ public:
return (mCurIterator++)->second;
}
S32 getVisualParamCountInGroup(const EVisualParamGroup group) const
{
S32 rtn = 0;
for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin();
iter != mVisualParamIndexMap.end();
/**/ )
{
if ((iter++)->second->getGroup() == group)
{
++rtn;
}
}
return rtn;
}
LLVisualParam* getVisualParam(S32 id) const
{
visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(id);

View File

@ -284,7 +284,7 @@ void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
void LLVisualParam::setNextParam( LLVisualParam *next )
{
llassert(!mNext);
llassert(getWeight() == getDefaultWeight()); // need to establish mNext before we start changing values on this, else initial value won't get mirrored (we can fix that, but better to forbid this pattern)
mNext = next;
}

View File

@ -954,7 +954,12 @@ namespace LLError
std::string class_name = className(site.mClassInfo);
std::string function_name = functionName(site.mFunction);
#if LL_LINUX
// gross, but typeid comparison seems to always fail here with gcc4.1
if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
#else
if (site.mClassInfo != typeid(NoClassInfo))
#endif // LL_LINUX
{
function_name = class_name + "::" + function_name;
}
@ -1079,7 +1084,12 @@ namespace LLError
#if LL_WINDOWS
// DevStudio: __FUNCTION__ already includes the full class name
#else
#if LL_LINUX
// gross, but typeid comparison seems to always fail here with gcc4.1
if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
#else
if (site.mClassInfo != typeid(NoClassInfo))
#endif // LL_LINUX
{
prefix << className(site.mClassInfo) << "::";
}

View File

@ -179,7 +179,7 @@ namespace LLError
{ return s; }
// used to indicate the end of a message
class NoClassInfo { };
class LL_COMMON_API NoClassInfo { };
// used to indicate no class info known for logging
//LLCallStacks keeps track of call stacks and output the call stacks to log file

View File

@ -249,7 +249,7 @@ public:
/////////////////////////////////////////////////////////////////////////////////////////
// Static Utility functions that operate on std::strings
static std::basic_string<T> null;
static const std::basic_string<T> null;
typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
@ -371,7 +371,7 @@ private:
LL_COMMON_API static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
};
template<class T> std::basic_string<T> LLStringUtilBase<T>::null;
template<class T> const std::basic_string<T> LLStringUtilBase<T>::null;
template<class T> std::string LLStringUtilBase<T>::sLocale;
typedef LLStringUtilBase<char> LLStringUtil;

View File

@ -545,15 +545,6 @@ namespace tut
// output order
void ErrorTestObject::test<10>()
{
#if LL_LINUX
skip("Fails on Linux, see comments");
// on Linux:
// [error, 10] fail: 'order is time type location function message: expected
// '1947-07-08T03:04:05Z INFO: llcommon/tests/llerror_test.cpp(268) :
// writeReturningLocationAndFunction: apple' actual
// '1947-07-08T03:04:05Z INFO: llcommon/tests/llerror_test.cpp(268) :
// LLError::NoClassInfo::writeReturningLocationAndFunction: apple''
#endif
LLError::setPrintLocation(true);
LLError::setTimeFunction(roswell);
mRecorder.setWantsTime(true);

View File

@ -68,45 +68,6 @@ void drawSolidSphere(GLdouble radius, GLint slices, GLint stacks)
}
// lat = 0 is Z-axis
// lon = 0, lat = 90 at X-axis
void lat2xyz(LLVector3 * result, F32 lat, F32 lon)
{
// Convert a latitude and longitude to x,y,z on a normal sphere and return it in result
F32 r;
result->mV[VX] = (F32) (cos(lon * DEG_TO_RAD) * sin(lat * DEG_TO_RAD));
result->mV[VY] = (F32) (sin(lon * DEG_TO_RAD) * sin(lat * DEG_TO_RAD));
r = (F32) pow(result->mV[VX] * result->mV[VX] + result->mV[VY] * result->mV[VY], 0.5f);
if (r == 1.0f)
{
result->mV[VZ] = 0.0f;
}
else
{
result->mV[VZ] = (F32) pow(1 - r*r, 0.5f);
if (lat > 90.01)
{
result->mV[VZ] *= -1.0;
}
}
}
void lat2xyz_rad(LLVector3 * result, F32 lat, F32 lon)
{
// Convert a latitude and longitude to x,y,z on a normal sphere and return it in result
F32 r;
result->mV[VX] = (F32) (cos(lon) * sin(lat));
result->mV[VY] = (F32) (sin(lon) * sin(lat));
r = (F32) pow(result->mV[VX] * result->mV[VX] + result->mV[VY] * result->mV[VY], 0.5f);
if (r == 1.0f)
result->mV[VZ] = 0.0f;
else
{
result->mV[VZ] = (F32) pow(1 - r*r, 0.5f);
if (lat > F_PI_BY_TWO) result->mV[VZ] *= -1.0;
}
}
// A couple thoughts on sphere drawing:
// 1) You need more slices than stacks, but little less than 2:1
// 2) At low LOD, setting stacks to an odd number avoids a "band" around the equator, making things look smoother
@ -181,3 +142,50 @@ void LLRenderSphere::render()
{
glCallList(mDList[0]);
}
inline LLVector3 polar_to_cart(F32 latitude, F32 longitude)
{
return LLVector3(sin(F_TWO_PI * latitude) * cos(F_TWO_PI * longitude),
sin(F_TWO_PI * latitude) * sin(F_TWO_PI * longitude),
cos(F_TWO_PI * latitude));
}
void LLRenderSphere::renderGGL()
{
S32 const LATITUDE_SLICES = 20;
S32 const LONGITUDE_SLICES = 30;
if (mSpherePoints.empty())
{
mSpherePoints.resize(LATITUDE_SLICES + 1);
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES + 1; lat_i++)
{
mSpherePoints[lat_i].resize(LONGITUDE_SLICES + 1);
for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES + 1; lon_i++)
{
F32 lat = (F32)lat_i / LATITUDE_SLICES;
F32 lon = (F32)lon_i / LONGITUDE_SLICES;
mSpherePoints[lat_i][lon_i] = polar_to_cart(lat, lon);
}
}
}
gGL.begin(LLRender::TRIANGLES);
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
{
for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
{
gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV);
gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i+1].mV);
}
}
gGL.end();
}

View File

@ -52,6 +52,10 @@ public:
void cleanupGL();
void render(F32 pixel_area); // of a box of size 1.0 at that position
void render(); // render at highest LOD
void renderGGL(); // render using LLRender
private:
std::vector< std::vector<LLVector3> > mSpherePoints;
};
extern LLRenderSphere gSphere;

View File

@ -636,8 +636,8 @@ void LLButton::draw()
if (mFlashing)
{
// if we have icon for flashing, use it as image for button
if(flash && mImageFlash->getName() != "FlashIconAbsent")
// if button should flash and we have icon for flashing, use it as image for button
if(flash && mImageFlash)
{
// setting flash to false to avoid its further influence on glow
flash = false;

View File

@ -314,8 +314,7 @@ private:
/* There are two ways an image can flash- by making changes in color according to flash_color attribute
or by changing icon from current to the one specified in image_flash. Second way is used only if
the name of flash icon is different from "FlashIconAbsent" which is there by default. First way is used
otherwise. */
flash icon name is set in attributes(by default it isn't). First way is used otherwise. */
LLPointer<LLUIImage> mImageFlash;
LLUIColor mHighlightColor;

View File

@ -330,6 +330,7 @@ void LLFloater::addDragHandle()
addChild(mDragHandle);
}
layoutDragHandle();
applyTitle();
}
void LLFloater::layoutDragHandle()
@ -348,7 +349,6 @@ void LLFloater::layoutDragHandle()
}
mDragHandle->setRect(rect);
updateTitleButtons();
applyTitle();
}
void LLFloater::addResizeCtrls()
@ -2519,7 +2519,7 @@ LLFloater *LLFloaterView::getBackmost() const
void LLFloaterView::syncFloaterTabOrder()
{
// look for a visible modal dialog, starting from first (should be only one)
// look for a visible modal dialog, starting from first
LLModalDialog* modal_dialog = NULL;
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{

View File

@ -2949,7 +2949,6 @@ BOOL LLScrollListCtrl::operateOnAll(EOperation op)
//virtual
void LLScrollListCtrl::setFocus(BOOL b)
{
mSearchString.clear();
// for tabbing into pristine scroll lists (Finder)
if (!getFirstSelected())
{
@ -2994,6 +2993,9 @@ void LLScrollListCtrl::onFocusLost()
{
gFocusMgr.setMouseCapture(NULL);
}
mSearchString.clear();
LLUICtrl::onFocusLost();
}

View File

@ -962,18 +962,19 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
{
if (width != getRect().getWidth() || height != getRect().getHeight())
{
//EXT-4288
//to keep consistance scrolling behaviour
//when scrolling from top and from bottom...
bool is_scrolled_to_end = (mScroller!=NULL) && scrolledToEnd();
bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;
LLUICtrl::reshape( width, height, called_from_parent );
if (is_scrolled_to_end)
if (mScroller && scrolled_to_bottom && mTrackEnd)
{
deselect();
endOfDoc();
}
// keep bottom of text buffer visible
// do this here as well as in reflow to handle case
// where shrinking from top, which causes buffer to temporarily
// not be scrolled to the bottom, since the scroll index
// specified the _top_ of the visible document region
mScroller->goToBottom();
}
// do this first after reshape, because other things depend on
// up-to-date mVisibleTextRect
@ -1100,7 +1101,7 @@ S32 LLTextBase::getLeftOffset(S32 width)
case LLFontGL::LEFT:
return mHPad;
case LLFontGL::HCENTER:
return mHPad + (mVisibleTextRect.getWidth() - width - mHPad) / 2;
return mHPad + llmax(0, (mVisibleTextRect.getWidth() - width - mHPad) / 2);
case LLFontGL::RIGHT:
return mVisibleTextRect.getWidth() - width;
default:
@ -1116,6 +1117,34 @@ void LLTextBase::reflow()
updateSegments();
if (mReflowIndex == S32_MAX)
{
return;
}
bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;
LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
bool follow_selection = getLocalRect().overlaps(cursor_rect); // cursor is (potentially) visible
// store in top-left relative coordinates to avoid issues with horizontal scrollbar appearing and disappearing
cursor_rect.mTop = mVisibleTextRect.mTop - cursor_rect.mTop;
cursor_rect.mBottom = mVisibleTextRect.mTop - cursor_rect.mBottom;
S32 first_line = getFirstVisibleLine();
// if scroll anchor not on first line, update it to first character of first line
if (!mLineInfoList.empty()
&& (mScrollIndex < mLineInfoList[first_line].mDocIndexStart
|| mScrollIndex >= mLineInfoList[first_line].mDocIndexEnd))
{
mScrollIndex = mLineInfoList[first_line].mDocIndexStart;
}
LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex);
// store in top-left relative coordinates to avoid issues with horizontal scrollbar appearing and disappearing
first_char_rect.mTop = mVisibleTextRect.mTop - first_char_rect.mTop;
first_char_rect.mBottom = mVisibleTextRect.mTop - first_char_rect.mBottom;
S32 reflow_count = 0;
while(mReflowIndex < S32_MAX)
{
@ -1129,6 +1158,7 @@ void LLTextBase::reflow()
lldebugs << "Breaking out of reflow due to possible infinite loop in " << getName() << llendl;
break;
}
S32 start_index = mReflowIndex;
mReflowIndex = S32_MAX;
@ -1136,25 +1166,6 @@ void LLTextBase::reflow()
// to force inlined widgets with follows set to shrink
mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight());
bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;
LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos);
bool follow_selection = mVisibleTextRect.overlaps(old_cursor_rect); // cursor is visible
old_cursor_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom);
S32 first_line = getFirstVisibleLine();
// if scroll anchor not on first line, update it to first character of first line
if (!mLineInfoList.empty()
&& (mScrollIndex < mLineInfoList[first_line].mDocIndexStart
|| mScrollIndex >= mLineInfoList[first_line].mDocIndexEnd))
{
mScrollIndex = mLineInfoList[first_line].mDocIndexStart;
}
LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex);
// subtract off effect of horizontal scrollbar from local position of first char
first_char_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom);
S32 cur_top = 0;
segment_set_t::iterator seg_iter = mSegments.begin();
@ -1196,11 +1207,6 @@ void LLTextBase::reflow()
// grow line height as necessary based on reported height of this segment
line_height = llmax(line_height, segment_height);
remaining_pixels -= segment_width;
if (remaining_pixels < 0)
{
// getNumChars() and getDimensions() should return consistent results
remaining_pixels = 0;
}
seg_offset += character_count;
@ -1275,32 +1281,42 @@ void LLTextBase::reflow()
segmentp->updateLayout(*this);
}
// apply scroll constraints after reflowing text
if (!hasMouseCapture() && mScroller)
{
if (scrolled_to_bottom && mTrackEnd)
{
// keep bottom of text buffer visible
endOfDoc();
}
else if (hasSelection() && follow_selection)
{
// keep cursor in same vertical position on screen when selecting text
LLRect new_cursor_rect_doc = getDocRectFromDocIndex(mCursorPos);
mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect);
}
else
{
// keep first line of text visible
LLRect new_first_char_rect = getDocRectFromDocIndex(mScrollIndex);
mScroller->scrollToShowRect(new_first_char_rect, first_char_rect);
}
}
// reset desired x cursor position
updateCursorXPos();
}
// apply scroll constraints after reflowing text
if (!hasMouseCapture() && mScroller)
{
if (scrolled_to_bottom && mTrackEnd)
{
// keep bottom of text buffer visible
endOfDoc();
}
else if (hasSelection() && follow_selection)
{
// keep cursor in same vertical position on screen when selecting text
LLRect new_cursor_rect_doc = getDocRectFromDocIndex(mCursorPos);
LLRect old_cursor_rect = cursor_rect;
old_cursor_rect.mTop = mVisibleTextRect.mTop - cursor_rect.mTop;
old_cursor_rect.mBottom = mVisibleTextRect.mTop - cursor_rect.mBottom;
mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect);
}
else
{
// keep first line of text visible
LLRect new_first_char_rect = getDocRectFromDocIndex(mScrollIndex);
// pass in desired rect in the coordinate frame of the document viewport
LLRect old_first_char_rect = first_char_rect;
old_first_char_rect.mTop = mVisibleTextRect.mTop - first_char_rect.mTop;
old_first_char_rect.mBottom = mVisibleTextRect.mTop - first_char_rect.mBottom;
mScroller->scrollToShowRect(new_first_char_rect, old_first_char_rect);
}
}
// reset desired x cursor position
updateCursorXPos();
}
LLRect LLTextBase::getTextBoundingRect()
@ -1562,7 +1578,7 @@ std::string LLTextBase::getText() const
return getViewModel()->getValue().asString();
}
void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
{
LLStyle::Params style_params(input_params);
style_params.fillFrom(getDefaultStyleParams());
@ -1598,8 +1614,7 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
part = (S32)LLTextParser::MIDDLE;
}
std::string subtext=text.substr(0,start);
appendAndHighlightText(subtext, prepend_newline, part, style_params);
prepend_newline = false;
appendAndHighlightTextImpl(subtext, part, style_params);
}
// output an optional icon before the Url
@ -1613,19 +1628,18 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
// Text will be replaced during rendering with the icon,
// but string cannot be empty or the segment won't be
// added (or drawn).
appendAndHighlightText(" ", prepend_newline, part, icon);
prepend_newline = false;
appendImageSegment(part, icon);
}
}
// output the styled Url (unless we've been asked to suppress hyperlinking)
if (match.isLinkDisabled())
{
appendAndHighlightText(match.getLabel(), prepend_newline, part, style_params);
appendAndHighlightTextImpl(match.getLabel(), part, style_params);
}
else
{
appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params);
appendAndHighlightTextImpl(match.getLabel(), part, link_params);
// set the tooltip for the Url label
if (! match.getTooltip().empty())
@ -1638,8 +1652,6 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
}
}
}
prepend_newline = false;
// move on to the rest of the text after the Url
if (end < (S32)text.length())
{
@ -1652,25 +1664,71 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
break;
}
}
if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END;
if (end < (S32)text.length()) appendAndHighlightText(text, prepend_newline, part, style_params);
if (part != (S32)LLTextParser::WHOLE)
part=(S32)LLTextParser::END;
if (end < (S32)text.length())
appendAndHighlightTextImpl(text, part, style_params);
}
else
{
appendAndHighlightText(new_text, prepend_newline, part, style_params);
appendAndHighlightTextImpl(new_text, part, style_params);
}
}
void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
{
if (new_text.empty())
return;
if(prepend_newline)
appendLineBreakSegment(input_params);
std::string::size_type start = 0;
std::string::size_type pos = new_text.find("\n",start);
while(pos!=-1)
{
if(pos!=start)
{
std::string str = std::string(new_text,start,pos-start);
appendTextImpl(str,input_params);
}
appendLineBreakSegment(input_params);
start = pos+1;
pos = new_text.find("\n",start);
}
std::string str = std::string(new_text,start,new_text.length()-start);
appendTextImpl(str,input_params);
}
void LLTextBase::needsReflow(S32 index)
{
lldebugs << "reflow on object " << (void*)this << " index = " << mReflowIndex << ", new index = " << index << llendl;
mReflowIndex = llmin(mReflowIndex, index);
}
void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& style_params)
void LLTextBase::appendLineBreakSegment(const LLStyle::Params& style_params)
{
if (new_text.empty()) return;
segment_vec_t segments;
LLStyleConstSP sp(new LLStyle(style_params));
segments.push_back(new LLLineBreakTextSegment(sp, getLength()));
insertStringNoUndo(getLength(), utf8str_to_wstring("\n"), &segments);
}
void LLTextBase::appendImageSegment(S32 highlight_part, const LLStyle::Params& style_params)
{
segment_vec_t segments;
LLStyleConstSP sp(new LLStyle(style_params));
segments.push_back(new LLImageTextSegment(sp, getLength(),*this));
insertStringNoUndo(getLength(), utf8str_to_wstring(" "), &segments);
}
void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params)
{
// Save old state
S32 selection_start = mSelectionStart;
S32 selection_end = mSelectionEnd;
@ -1683,13 +1741,11 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
setCursorPos(old_length);
LLTextParser* highlight = LLTextParser::getInstance();
if (mParseHighlights && highlight)
if (mParseHighlights)
{
LLStyle::Params highlight_params(style_params);
LLSD pieces = highlight->parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part);
LLSD pieces = LLTextParser::instance().parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part);
for (S32 i = 0; i < pieces.size(); i++)
{
LLSD color_llsd = pieces[i]["color"];
@ -1698,14 +1754,8 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
highlight_params.color = lcolor;
LLWString wide_text;
if (prepend_newline && (i == 0 || pieces.size() <= 1 ))
{
wide_text = utf8str_to_wstring(std::string("\n") + pieces[i]["text"].asString());
}
else
{
wide_text = utf8str_to_wstring(pieces[i]["text"].asString());
}
wide_text = utf8str_to_wstring(pieces[i]["text"].asString());
S32 cur_length = getLength();
LLStyleConstSP sp(new LLStyle(highlight_params));
LLTextSegmentPtr segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this);
@ -1717,17 +1767,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
else
{
LLWString wide_text;
// Add carriage return if not first line
if (getLength() != 0
&& prepend_newline)
{
wide_text = utf8str_to_wstring(std::string("\n") + new_text);
}
else
{
wide_text = utf8str_to_wstring(new_text);
}
wide_text = utf8str_to_wstring(new_text);
segment_vec_t segments;
S32 segment_start = old_length;
@ -1755,11 +1795,32 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
{
setCursorPos(cursor_pos);
}
}
//if( !allow_undo )
//{
// blockUndo();
//}
void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& style_params)
{
if (new_text.empty()) return;
if(prepend_newline)
appendLineBreakSegment(style_params);
std::string::size_type start = 0;
std::string::size_type pos = new_text.find("\n",start);
while(pos!=-1)
{
if(pos!=start)
{
std::string str = std::string(new_text,start,pos-start);
appendAndHighlightTextImpl(str,highlight_part, style_params);
}
appendLineBreakSegment(style_params);
start = pos+1;
pos = new_text.find("\n",start);
}
std::string str = std::string(new_text,start,new_text.length()-start);
appendAndHighlightTextImpl(str,highlight_part, style_params);
}
@ -1827,7 +1888,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
{
// Figure out which line we're nearest to.
LLRect visible_region = getVisibleDocumentRect();
// binary search for line that starts before local_y
line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mVisibleTextRect.mBottom + visible_region.mBottom, compare_bottom());
@ -1837,7 +1898,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
}
S32 pos = getLength();
S32 start_x = mVisibleTextRect.mLeft + line_iter->mRect.mLeft;
S32 start_x = mVisibleTextRect.mLeft + line_iter->mRect.mLeft - visible_region.mLeft;
segment_set_t::iterator line_seg_iter;
S32 line_seg_offset;
@ -1852,14 +1913,19 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
S32 text_width, text_height;
bool newline = segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height);
if(newline)
{
pos = segment_line_start + segmentp->getOffset(local_x - start_x, line_seg_offset, segment_line_length, round);
break;
}
// if we've reached a line of text *below* the mouse cursor, doc index is first character on that line
if (hit_past_end_of_line && local_y - mVisibleTextRect.mBottom + visible_region.mBottom > line_iter->mRect.mTop)
{
pos = segment_line_start;
break;
}
if (local_x < start_x + text_width // cursor to left of right edge of text
|| newline) // or this line ends with a newline, set doc pos to newline char
if (local_x < start_x + text_width) // cursor to left of right edge of text
{
// Figure out which character we're nearest to.
S32 offset;
@ -1883,13 +1949,13 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
pos = segment_line_start + offset;
break;
}
else if (hit_past_end_of_line && segmentp->getEnd() >= line_iter->mDocIndexEnd - 1)
else if (hit_past_end_of_line && segmentp->getEnd() > line_iter->mDocIndexEnd - 1)
{
// segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
pos = llmin(getLength(), line_iter->mDocIndexEnd);
// segment wraps to next line, so just set doc pos to the end of the line
// segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
pos = llmin(getLength(), line_iter->mDocIndexEnd);
break;
}
start_x += text_width;
}
@ -1958,11 +2024,18 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
{
LLRect content_window_rect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
if (mBorderVisible)
{
content_window_rect.stretch(-1);
}
LLRect local_rect;
if (mLineInfoList.empty())
{
// return default height rect in upper left
local_rect = mVisibleTextRect;
local_rect = content_window_rect;
local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
return local_rect;
}
@ -1973,8 +2046,8 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
// compensate for scrolled, inset view of doc
LLRect scrolled_view_rect = getVisibleDocumentRect();
local_rect = doc_rect;
local_rect.translate(mVisibleTextRect.mLeft - scrolled_view_rect.mLeft,
mVisibleTextRect.mBottom - scrolled_view_rect.mBottom);
local_rect.translate(content_window_rect.mLeft - scrolled_view_rect.mLeft,
content_window_rect.mBottom - scrolled_view_rect.mBottom);
return local_rect;
}
@ -2346,25 +2419,6 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec
{
if( end - start > 0 )
{
if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart))
{
// ...for images, only render the image, not the underlying text,
// which is only a placeholder space
LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha;
LLUIImagePtr image = mStyle->getImage();
S32 style_image_height = image->getHeight();
S32 style_image_width = image->getWidth();
// Text is drawn from the top of the draw_rect downward
S32 text_center = draw_rect.mTop - (mFontHeight / 2);
// Align image to center of text
S32 image_bottom = text_center - (style_image_height / 2);
image->draw(draw_rect.mLeft, image_bottom,
style_image_width, style_image_height, color);
const S32 IMAGE_HPAD = 3;
return draw_rect.mLeft + style_image_width + IMAGE_HPAD;
}
return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect);
}
return draw_rect.mLeft;
@ -2377,11 +2431,6 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
const LLWString &text = mEditor.getWText();
if ( text[seg_end-1] == '\n' )
{
--seg_end;
}
F32 right_x = rect.mLeft;
if (!mStyle->isVisible())
{
@ -2540,33 +2589,14 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
{
height = 0;
width = 0;
bool force_newline = false;
if (num_chars > 0)
{
height = mFontHeight;
const LLWString &text = mEditor.getWText();
// if last character is a newline, then return true, forcing line break
llwchar last_char = text[mStart + first_char + num_chars - 1];
if (last_char == '\n')
{
force_newline = true;
// don't count newline in font width
width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars - 1);
}
else
{
width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
}
width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
}
LLUIImagePtr image = mStyle->getImage();
if( image.notNull())
{
width += image->getWidth();
height = llmax(height, image->getHeight());
}
return force_newline;
return false;
}
S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
@ -2589,15 +2619,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
num_pixels = llmax(0, num_pixels - image->getWidth());
}
// search for newline and if found, truncate there
S32 last_char = mStart + segment_offset;
for (; last_char != mEnd; ++last_char)
{
if (text[last_char] == '\n')
{
break;
}
}
S32 last_char = mEnd;
// set max characters to length of segment, or to first newline
max_chars = llmin(max_chars, last_char - (mStart + segment_offset));
@ -2625,8 +2647,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
S32 last_char_in_run = mStart + segment_offset + num_chars;
// check length first to avoid indexing off end of string
if (last_char_in_run < mEnd
&& (last_char_in_run >= mEditor.getLength()
|| text[last_char_in_run] == '\n'))
&& (last_char_in_run >= mEditor.getLength() ))
{
num_chars++;
}
@ -2721,3 +2742,87 @@ void LLInlineViewSegment::linkToDocument(LLTextBase* editor)
{
editor->addDocumentChild(mView);
}
LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1)
{
mFontHeight = llceil(style->getFont()->getLineHeight());
}
LLLineBreakTextSegment::~LLLineBreakTextSegment()
{
}
bool LLLineBreakTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
{
width = 0;
height = mFontHeight;
return true;
}
S32 LLLineBreakTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
return 1;
}
F32 LLLineBreakTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
{
return draw_rect.mLeft;
}
LLImageTextSegment::LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor)
:LLTextSegment(pos,pos+1)
,mStyle( style )
,mEditor(editor)
{
}
LLImageTextSegment::~LLImageTextSegment()
{
}
static const S32 IMAGE_HPAD = 3;
bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
{
width = 0;
height = llceil(mStyle->getFont()->getLineHeight());;
LLUIImagePtr image = mStyle->getImage();
if( image.notNull())
{
width += image->getWidth() + IMAGE_HPAD;
height = llmax(height, image->getHeight() + IMAGE_HPAD );
}
return false;
}
S32 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
LLUIImagePtr image = mStyle->getImage();
S32 image_width = image->getWidth();
if(num_pixels>image_width + IMAGE_HPAD)
{
return 1;
}
return 0;
}
F32 LLImageTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
{
if ( (start >= 0) && (end <= mEnd - mStart))
{
LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha;
LLUIImagePtr image = mStyle->getImage();
S32 style_image_height = image->getHeight();
S32 style_image_width = image->getWidth();
// Text is drawn from the top of the draw_rect downward
S32 text_center = draw_rect.mTop - (draw_rect.getHeight() / 2);
// Align image to center of draw rect
S32 image_bottom = text_center - (style_image_height / 2);
image->draw(draw_rect.mLeft, image_bottom,
style_image_width, style_image_height, color);
const S32 IMAGE_HPAD = 3;
return draw_rect.mLeft + style_image_width + IMAGE_HPAD;
}
return 0.0;
}

View File

@ -316,6 +316,13 @@ protected:
void needsScroll() { mScrollNeeded = TRUE; }
void replaceUrlLabel(const std::string &url, const std::string &label);
void appendLineBreakSegment(const LLStyle::Params& style_params);
void appendImageSegment(S32 highlight_part, const LLStyle::Params& style_params);
void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params);
protected:
// text segmentation and flow
segment_set_t mSegments;
@ -507,5 +514,32 @@ private:
bool mForceNewLine;
};
class LLLineBreakTextSegment : public LLTextSegment
{
public:
LLLineBreakTextSegment(LLStyleConstSP style,S32 pos);
~LLLineBreakTextSegment();
bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
private:
S32 mFontHeight;
};
class LLImageTextSegment : public LLTextSegment
{
public:
LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor);
~LLImageTextSegment();
bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
private:
class LLTextBase& mEditor;
LLStyleConstSP mStyle;
};
#endif

View File

@ -1083,6 +1083,28 @@ void LLTextEditor::addChar(llwchar wc)
setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
}
void LLTextEditor::addLineBreakChar()
{
if( !getEnabled() )
{
return;
}
if( hasSelection() )
{
deleteSelection(TRUE);
}
else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
{
removeChar(mCursorPos);
}
LLStyleConstSP sp(new LLStyle(LLStyle::Params()));
LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos);
S32 pos = execute(new TextCmdAddChar(mCursorPos, FALSE, '\n', segment));
setCursorPos(mCursorPos + pos);
}
BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask)
@ -1404,7 +1426,27 @@ void LLTextEditor::pasteHelper(bool is_primary)
}
// Insert the new text into the existing text.
setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE, LLTextSegmentPtr()));
//paste text with linebreaks.
std::basic_string<llwchar>::size_type start = 0;
std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start);
while(pos!=-1)
{
if(pos!=start)
{
std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,pos-start);
setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
}
addLineBreakChar();
start = pos+1;
pos = clean_string.find('\n',start);
}
std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start);
setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
deselect();
onKeyStroke();
@ -2169,7 +2211,10 @@ void LLTextEditor::autoIndent()
}
// Insert that number of spaces on the new line
addChar( '\n' );
//appendLineBreakSegment(LLStyle::Params());//addChar( '\n' );
addLineBreakChar();
for( i = 0; i < space_count; i++ )
{
addChar( ' ' );

View File

@ -240,6 +240,7 @@ protected:
// Undoable operations
void addChar(llwchar c); // at mCursorPos
S32 addChar(S32 pos, llwchar wc);
void addLineBreakChar();
S32 overwriteChar(S32 pos, llwchar wc);
void removeChar();
S32 removeChar(S32 pos);

View File

@ -43,29 +43,14 @@
#include "v4color.h"
#include "lldir.h"
// Routines used for parsing text for TextParsers and html
LLTextParser* LLTextParser::sInstance = NULL;
//
// Member Functions
//
LLTextParser::~LLTextParser()
{
sInstance=NULL;
}
LLTextParser::LLTextParser()
: mLoaded(false)
{}
// static
LLTextParser* LLTextParser::getInstance()
{
if (!sInstance)
{
sInstance = new LLTextParser();
sInstance->loadFromDisk();
}
return sInstance;
}
// Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency.
@ -105,6 +90,8 @@ S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index)
{
loadKeywords();
//evil recursive string atomizer.
LLSD ret_llsd, start_llsd, middle_llsd, end_llsd;
@ -195,6 +182,8 @@ LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLC
bool LLTextParser::parseFullLineHighlights(const std::string &text, LLColor4 *color)
{
loadKeywords();
for (S32 i=0;i<mHighlights.size();i++)
{
if ((S32)mHighlights[i]["highlight"]==ALL || (S32)mHighlights[i]["condition"]==MATCHES)
@ -221,14 +210,14 @@ std::string LLTextParser::getFileName()
return path;
}
LLSD LLTextParser::loadFromDisk()
void LLTextParser::loadKeywords()
{
std::string filename=getFileName();
if (filename.empty())
{
llwarns << "LLTextParser::loadFromDisk() no valid user directory." << llendl;
if (mLoaded)
{// keywords already loaded
return;
}
else
std::string filename=getFileName();
if (!filename.empty())
{
llifstream file;
file.open(filename.c_str());
@ -237,9 +226,8 @@ LLSD LLTextParser::loadFromDisk()
LLSDSerialize::fromXML(mHighlights, file);
}
file.close();
mLoaded = true;
}
return mHighlights;
}
bool LLTextParser::saveToDisk(LLSD highlights)

View File

@ -35,12 +35,13 @@
#define LL_LLTEXTPARSER_H
#include "llsd.h"
#include "llsingleton.h"
class LLUUID;
class LLVector3d;
class LLColor4;
class LLTextParser
class LLTextParser : public LLSingleton<LLTextParser>
{
public:
typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType;
@ -48,22 +49,20 @@ public:
typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition;
typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction;
static LLTextParser* getInstance();
LLTextParser(){};
~LLTextParser();
LLTextParser();
S32 findPattern(const std::string &text, LLSD highlight);
LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0);
bool parseFullLineHighlights(const std::string &text, LLColor4 *color);
private:
S32 findPattern(const std::string &text, LLSD highlight);
std::string getFileName();
LLSD loadFromDisk();
void loadKeywords();
bool saveToDisk(LLSD highlights);
public:
LLSD mHighlights;
private:
static LLTextParser* sInstance;
bool mLoaded;
};
#endif

View File

@ -94,6 +94,8 @@ public:
/// is this a match for a URL that should not be hyperlinked?
bool isLinkDisabled() const { return mDisabledLink; }
virtual LLUUID getID(const std::string &string) const { return LLUUID::null; }
protected:
std::string getIDStringFromUrl(const std::string &url) const;
std::string escapeUrl(const std::string &url) const;

View File

@ -51,7 +51,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
const std::string &icon, const LLUIColor& color,
const std::string &menu, const std::string &location,
bool disabled_link)
bool disabled_link, const LLUUID& id)
{
mStart = start;
mEnd = end;
@ -63,4 +63,5 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mMenuName = menu;
mLocation = location;
mDisabledLink = disabled_link;
mID = id;
}

View File

@ -90,7 +90,10 @@ public:
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
const LLUIColor& color, const std::string &menu,
const std::string &location, bool disabled_link);
const std::string &location, bool disabled_link
, const LLUUID& id );
const LLUUID& getID() const { return mID;}
private:
U32 mStart;
@ -101,6 +104,8 @@ private:
std::string mIcon;
std::string mMenuName;
std::string mLocation;
LLUUID mID;
LLUIColor mColor;
bool mDisabledLink;
};

View File

@ -183,7 +183,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getColor(),
match_entry->getMenuName(),
match_entry->getLocation(url),
match_entry->isLinkDisabled());
match_entry->isLinkDisabled(),
match_entry->getID(url));
return true;
}
@ -217,7 +218,8 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
match.getColor(),
match.getMenuName(),
match.getLocation(),
match.isLinkDisabled());
match.isLinkDisabled(),
match.getID());
return true;
}
return false;

View File

@ -54,7 +54,7 @@ namespace tut
LLUrlMatch match;
ensure("empty()", match.empty());
match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false);
match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure("! empty()", ! match.empty());
}
@ -67,7 +67,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getStart() == 0", match.getStart(), 0);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getStart() == 10", match.getStart(), 10);
}
@ -80,7 +80,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getEnd() == 0", match.getEnd(), 0);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getEnd() == 20", match.getEnd(), 20);
}
@ -93,10 +93,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getUrl() == ''", match.getUrl(), "");
match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
}
@ -109,10 +109,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getLabel() == ''", match.getLabel(), "");
match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
}
@ -125,10 +125,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getTooltip() == ''", match.getTooltip(), "");
match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
}
@ -141,10 +141,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getIcon() == ''", match.getIcon(), "");
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
}
@ -157,10 +157,10 @@ namespace tut
LLUrlMatch match;
ensure("getMenuName() empty", match.getMenuName().empty());
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false);
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false,LLUUID::null);
ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure("getMenuName() empty (2)", match.getMenuName().empty());
}
@ -173,10 +173,10 @@ namespace tut
LLUrlMatch match;
ensure("getLocation() empty", match.getLocation().empty());
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false);
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false,LLUUID::null);
ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
ensure("getLocation() empty (2)", match.getLocation().empty());
}
}

View File

@ -356,6 +356,7 @@ set(viewer_SOURCE_FILES
llpanelprofileview.cpp
llpanelteleporthistory.cpp
llpaneltiptoast.cpp
llpaneltopinfobar.cpp
llpanelvolume.cpp
llpanelvolumepulldown.cpp
llparcelselection.cpp
@ -466,6 +467,7 @@ set(viewer_SOURCE_FILES
llviewchildren.cpp
llviewerassetstorage.cpp
llviewerassettype.cpp
llviewerattachmenu.cpp
llvieweraudio.cpp
llviewercamera.cpp
llviewerchat.cpp
@ -870,6 +872,7 @@ set(viewer_HEADER_FILES
llpanelprofileview.h
llpanelteleporthistory.h
llpaneltiptoast.h
llpaneltopinfobar.h
llpanelvolume.h
llpanelvolumepulldown.h
llparcelselection.h
@ -984,6 +987,7 @@ set(viewer_HEADER_FILES
llviewchildren.h
llviewerassetstorage.h
llviewerassettype.h
llviewerattachmenu.h
llvieweraudio.h
llviewercamera.h
llviewerchat.h

View File

@ -594,7 +594,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>0</integer>
<integer>180</integer>
</map>
<key>AvatarSex</key>
<map>
@ -643,7 +643,18 @@
<key>BlockAvatarAppearanceMessages</key>
<map>
<key>Comment</key>
<string>Ignore's appearance messages (for simulating Ruth)</string>
<string>Ignores appearance messages (for simulating Ruth)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>BlockSomeAvatarAppearanceVisualParams</key>
<map>
<key>Comment</key>
<string>Drop around 50% of VisualParam occurances in appearance messages (for simulating Ruth)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -3862,7 +3873,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<integer>1</integer>
</map>
<key>InBandwidth</key>
<map>
@ -8305,17 +8316,6 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowSidebarButton</key>
<map>
<key>Comment</key>
<string>Shows/hides Sidebar button in the bottom tray.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowSnapshotButton</key>
<map>
<key>Comment</key>
@ -8371,6 +8371,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowMiniLocationPanel</key>
<map>
<key>Comment</key>
<string>Show/Hide Mini-Location Panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SidebarCameraMovement</key>
<map>
<key>Comment</key>
@ -8858,17 +8869,6 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>SidebarWithButtonsVisibility</key>
<map>
<key>Comment</key>
<string>Sets visibility of sidebar with its tabs' buttons</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>SkinCurrent</key>
<map>
<key>Comment</key>
@ -11395,5 +11395,16 @@
<string>mini_map</string>
</array>
</map>
<key>LandmarksSortedByDate</key>
<map>
<key>Comment</key>
<string>Reflects landmarks panel sorting order.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
</map>
</llsd>

View File

@ -4782,7 +4782,7 @@
group="1"
name="Saddlebags"
wearable="shape"
edit_grouo="driven"
edit_group="driven"
value_min="-.5"
value_max="3">
<param_morph>

View File

@ -26,6 +26,7 @@ list all
RenderAnisotropic 1 0
RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxVisible 1 35
RenderAvatarVP 1 1
RenderCubeMap 1 1
RenderDelayVBUpdate 1 0

View File

@ -26,6 +26,7 @@ list all
RenderAnisotropic 1 0
RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxVisible 1 35
RenderAvatarVP 1 1
RenderCubeMap 1 1
RenderDelayVBUpdate 1 0

View File

@ -26,6 +26,7 @@ list all
RenderAnisotropic 1 0
RenderAvatarCloth 0 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxVisible 1 35
RenderAvatarVP 1 0
RenderCubeMap 1 1
RenderDelayVBUpdate 1 0

View File

@ -35,6 +35,7 @@
import collections
import fnmatch
import itertools
import operator
import os
import sys
import shlex
@ -51,15 +52,13 @@ class MissingModuleError(Exception):
self.modules = modules
def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file):
# print "generate_breakpad_symbols: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file))
print "generate_breakpad_symbols run with args: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file))
# split up list of viewer_exes
# "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin']
viewer_exes = shlex.split(viewer_exes)
found_required = dict()
for required in viewer_exes:
found_required[required] = False
found_required = dict([(module, False) for module in viewer_exes])
def matches(f):
if f in viewer_exes:
@ -98,13 +97,33 @@ def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_fil
else:
print >>sys.stderr, "warning: failed to dump symbols for '%s': %s" % (filename, err)
out.close()
missing_modules = [m for (m,_) in
itertools.ifilter(lambda (k,v): not v, found_required.iteritems())
]
if missing_modules:
print >> sys.stderr, "failed to generate %s" % viewer_symbol_file
os.remove(viewer_symbol_file)
raise MissingModuleError(missing_modules)
out.close()
symbols = tarfile.open(viewer_symbol_file, 'r:bz2')
tarfile_members = symbols.getnames()
symbols.close()
for required_module in viewer_exes:
def match_module_basename(m):
return os.path.splitext(required_module)[0].lower() \
== os.path.splitext(os.path.basename(m))[0].lower()
# there must be at least one .sym file in tarfile_members that matches
# each required module (ignoring file extensions)
if not reduce(operator.or_, itertools.imap(match_module_basename, tarfile_members)):
print >> sys.stderr, "failed to find required %s in generated %s" \
% (required_module, viewer_symbol_file)
os.remove(viewer_symbol_file)
raise MissingModuleError([required_module])
print "successfully generated %s including required modules '%s'" % (viewer_symbol_file, viewer_exes)
return 0

View File

@ -204,8 +204,8 @@ NVIDIA GeForce 7200 .*NVIDIA.*GeForce 72.* 1 1
NVIDIA GeForce 7300 .*NVIDIA.*GeForce 73.* 1 1
NVIDIA GeForce 7500 .*NVIDIA.*GeForce 75.* 1 1
NVIDIA GeForce 7600 .*NVIDIA.*GeForce 76.* 1 1
NVIDIA GeForce 7800 .*NVIDIA.*GeForce.*78.* 1 1
NVIDIA GeForce 7900 .*NVIDIA.*GeForce.*79.* 1 1
NVIDIA GeForce 7800 .*NVIDIA.*GeForce 78.* 1 1
NVIDIA GeForce 7900 .*NVIDIA.*GeForce 79.* 1 1
NVIDIA GeForce 8100 .*NVIDIA.*GeForce 81.* 1 1
NVIDIA GeForce 8200 .*NVIDIA.*GeForce 82.* 1 1
NVIDIA GeForce 8300 .*NVIDIA.*GeForce 83.* 1 1
@ -259,6 +259,7 @@ NVIDIA G84 .*G84.* 1 1
NVIDIA G92 .*G92.* 3 1
NVIDIA G94 .*G94.* 3 1
NVIDIA GeForce Go 6 .*GeForce Go 6.* 1 1
NVIDIA ION .*NVIDIA ION.* 1 1
NVIDIA NB9M .*GeForce NB9M.* 1 1
NVIDIA NB9P .*GeForce NB9P.* 1 1
NVIDIA GeForce PCX .*GeForce PCX.* 0 1

View File

@ -3585,7 +3585,13 @@ void LLAgent::sendAgentSetAppearance()
llinfos << "TAT: Sending cached texture data" << llendl;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index);
BOOL generate_valid_hash = TRUE;
if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLVOAvatarDefines::EBakedTextureIndex)baked_index))
{
generate_valid_hash = FALSE;
}
LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash);
if (hash.notNull())
{

View File

@ -2360,7 +2360,6 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came
mAnimationDuration = gSavedSettings.getF32("ZoomTime");
}
}
setFocusGlobal(LLVector3d::zero);
}
else
{

View File

@ -1445,6 +1445,8 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
queryWearableCache();
updateServer();
gAgentAvatarp->dumpAvatarTEs("setWearableOutfit");
lldebugs << "setWearableOutfit() end" << llendl;
}
@ -1617,13 +1619,13 @@ void LLAgentWearables::queryWearableCache()
gAgentQueryManager.mWearablesCacheQueryID++;
}
LLUUID LLAgentWearables::computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex index)
LLUUID LLAgentWearables::computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex baked_index,
BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache
{
LLUUID hash_id;
bool hash_computed = false;
LLMD5 hash;
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(index);
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index);
for (U8 i=0; i < baked_dict->mWearables.size(); i++)
{
@ -1643,6 +1645,15 @@ LLUUID LLAgentWearables::computeBakedTextureHash(LLVOAvatarDefines::EBakedTextur
if (hash_computed)
{
hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES);
// Add some garbage into the hash so that it becomes invalid.
if (!generate_valid_hash)
{
if (isAgentAvatarValid())
{
hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES);
}
}
hash.finalize();
hash.raw_digest(hash_id.mData);
}
@ -1973,6 +1984,32 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos
return false;
}
// static
void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, const LLUUID& parent_id)
{
LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
LLAssetType::EType asset_type = wearable->getAssetType();
LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
LLPointer<LLInventoryCallback> cb = wear ? new WearOnAvatarCallback : NULL;
LLUUID folder_id;
if (parent_id.notNull())
{
folder_id = parent_id;
}
else
{
LLFolderType::EType folder_type = LLFolderType::assetTypeToFolderType(asset_type);
folder_id = gInventory.findCategoryUUIDForType(folder_type);
}
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
folder_id, wearable->getTransactionID(), wearable->getName(),
wearable->getDescription(), asset_type, inv_type, wearable->getType(),
wearable->getPermissions().getMaskNextOwner(),
cb);
}
// static
void LLAgentWearables::editWearable(const LLUUID& item_id)
{

View File

@ -144,6 +144,7 @@ protected:
//--------------------------------------------------------------------
public:
static void createWearable(LLWearableType::EType type, bool wear = false, const LLUUID& parent_id = LLUUID::null);
static void editWearable(const LLUUID& item_id);
bool moveWearable(const LLViewerInventoryItem* item, bool closer_to_body);
@ -164,7 +165,8 @@ protected:
public:
// Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant)
static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data);
LLUUID computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex index);
LLUUID computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex baked_index,
BOOL generate_valid_hash = TRUE);
protected:
void sendAgentWearablesUpdate();

View File

@ -276,12 +276,14 @@ void LLWearableHoldingPattern::checkMissingWearables()
if (found_by_type[type] > 0)
continue;
if (
// Need to recover if at least one wearable of that type
// was requested but none was found (prevent missing
// pants)
(requested_by_type[type] > 0) ||
// or if type is a body part and no wearables were found.
((type == LLWearableType::WT_SHAPE) || (type == LLWearableType::WT_SKIN) || (type == LLWearableType::WT_HAIR) || (type == LLWearableType::WT_EYES)))
// If at least one wearable of certain types (pants/shirt/skirt)
// was requested but none was found, create a default asset as a replacement.
// In all other cases, don't do anything.
// For critical types (shape/hair/skin/eyes), this will keep the avatar as a cloud
// due to logic in LLVOAvatarSelf::getIsCloud().
// For non-critical types (tatoo, socks, etc.) the wearable will just be missing.
(requested_by_type[type] > 0) &&
((type == LLWearableType::WT_PANTS) || (type == LLWearableType::WT_SHIRT) || (type == LLWearableType::WT_SKIRT)))
{
mTypesToRecover.insert(type);
mTypesToLink.insert(type);
@ -654,15 +656,37 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
{
if (item_id_to_wear.isNull()) return false;
//only the item from a user's inventory is allowed
if (!gInventory.isObjectDescendentOf(item_id_to_wear, gInventory.getRootFolderID())) return false;
LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear);
if (!item_to_wear) return false;
if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
{
LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(replace);
copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(),cb);
return false;
}
else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))
{
return false; // not in library and not in agent's inventory
}
else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))
{
LLNotificationsUtil::add("CannotWearTrash");
return false;
}
switch (item_to_wear->getType())
{
case LLAssetType::AT_CLOTHING:
if (gAgentWearables.areWearablesLoaded())
{
S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType());
if ((replace && wearable_count != 0) ||
(wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) )
{
removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false);
}
}
case LLAssetType::AT_BODYPART:
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
@ -674,7 +698,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
// Remove the existing wearables of the same type.
// Remove existing body parts anyway because we must not be able to wear e.g. two skins.
if (replace || item_to_wear->getType() == LLAssetType::AT_BODYPART)
if (item_to_wear->getType() == LLAssetType::AT_BODYPART)
{
removeCOFLinksOfType(item_to_wear->getWearableType(), false);
}
@ -704,6 +728,40 @@ void LLAppearanceMgr::replaceCurrentOutfit(const LLUUID& new_outfit)
wearInventoryCategory(cat, false, false);
}
// Open outfit renaming dialog.
void LLAppearanceMgr::renameOutfit(const LLUUID& outfit_id)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(outfit_id);
if (!cat)
{
return;
}
LLSD args;
args["NAME"] = cat->getName();
LLSD payload;
payload["cat_id"] = outfit_id;
LLNotificationsUtil::add("RenameOutfit", args, payload, boost::bind(onOutfitRename, _1, _2));
}
// User typed new outfit name.
// static
void LLAppearanceMgr::onOutfitRename(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return; // canceled
std::string outfit_name = response["new_name"].asString();
LLStringUtil::trim(outfit_name);
if (!outfit_name.empty())
{
LLUUID cat_id = notification["payload"]["cat_id"].asUUID();
rename_category(&gInventory, cat_id, outfit_name);
}
}
void LLAppearanceMgr::addCategoryToCurrentOutfit(const LLUUID& cat_id)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
@ -714,7 +772,7 @@ void LLAppearanceMgr::takeOffOutfit(const LLUUID& cat_id)
{
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLFindWearables collector;
LLFindWorn collector;
gInventory.collectDescendentsIf(cat_id, cats, items, FALSE, collector);
@ -842,6 +900,41 @@ BOOL LLAppearanceMgr::getCanMakeFolderIntoOutfit(const LLUUID& folder_id)
return ((required_wearables & folder_wearables) == required_wearables);
}
bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id)
{
// Disallow removing the base outfit.
if (outfit_cat_id == getBaseOutfitUUID())
{
return false;
}
// Check if the outfit folder itself is removable.
if (!get_is_category_removable(&gInventory, outfit_cat_id))
{
return false;
}
// Check if the folder contains worn items.
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLFindWorn filter_worn;
gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_worn);
if (!items.empty())
{
return false;
}
// Check for the folder's non-removable descendants.
LLFindNonRemovableObjects filter_non_removable;
LLInventoryModel::item_array_t::const_iterator it;
gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_non_removable);
if (!cats.empty() || !items.empty())
{
return false;
}
return true;
}
void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
{
@ -1488,6 +1581,7 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update
item_array,
LLInventoryModel::EXCLUDE_TRASH);
bool linked_already = false;
U32 count = 0;
for (S32 i=0; i<item_array.count(); i++)
{
// Are these links to the same object?
@ -1505,15 +1599,21 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update
}
// Are these links to different items of the same body part
// type? If so, new item will replace old.
// TODO: MULTI-WEARABLE: check for wearable limit for clothing types
else if (is_body_part && (vitem->isWearableType()) && (vitem->getWearableType() == wearable_type))
else if ((vitem->isWearableType()) && (vitem->getWearableType() == wearable_type))
{
if (inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type))
++count;
if (is_body_part && inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type))
{
gInventory.purgeObject(inv_item->getUUID());
}
else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
{
// MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE
gInventory.purgeObject(inv_item->getUUID());
}
}
}
if (linked_already)
{
if (do_update)

View File

@ -59,6 +59,7 @@ public:
void wearOutfitByName(const std::string& name);
void changeOutfit(bool proceed, const LLUUID& category, bool append);
void replaceCurrentOutfit(const LLUUID& new_outfit);
void renameOutfit(const LLUUID& outfit_id);
void takeOffOutfit(const LLUUID& cat_id);
void addCategoryToCurrentOutfit(const LLUUID& cat_id);
@ -69,6 +70,9 @@ public:
// Return whether this folder contains minimal contents suitable for making a full outfit.
BOOL getCanMakeFolderIntoOutfit(const LLUUID& folder_id);
// Determine whether a given outfit can be removed.
bool getCanRemoveOutfit(const LLUUID& outfit_cat_id);
// Copy all items in a category.
void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
LLPointer<LLInventoryCallback> cb);
@ -180,6 +184,8 @@ private:
void purgeCategory(const LLUUID& category, bool keep_outfit_links);
void purgeBaseOutfitLink(const LLUUID& category);
static void onOutfitRename(const LLSD& notification, const LLSD& response);
std::set<LLUUID> mRegisteredAttachments;
bool mAttachmentInvLinkEnabled;
bool mOutfitIsDirty;

View File

@ -898,14 +898,20 @@ bool LLAppViewer::init()
LLViewerMedia::initClass();
LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
//EXT-7013 - On windows for some locale (Japanese) standard
//datetime formatting functions didn't support some parameters such as "weekday".
std::string language = LLControlGroup::getInstance(sGlobalSettingsName)->getString("Language");
if(language == "ja")
{
LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
LLStringOps::sAM = LLTrans::getString("dateTimeAM");
LLStringOps::sPM = LLTrans::getString("dateTimePM");
LLStringOps::sAM = LLTrans::getString("dateTimeAM");
LLStringOps::sPM = LLTrans::getString("dateTimePM");
}
return true;
}
@ -1830,7 +1836,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
}
else
{
llwarns << "Cannot load " << full_settings_path << " - No settings found." << llendl;
llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
}
}
else

View File

@ -78,7 +78,7 @@ public:
boost::function<void(const LLUUID& uuid)> mCallback;
};
class LLBakedUploadData;
struct LLBakedUploadData;
class LLSendTexLayerResponder : public LLAssetUploadResponder
{
public:

View File

@ -475,6 +475,138 @@ namespace action_give_inventory
return acceptable;
}
static void build_residents_string(const std::vector<std::string>& avatar_names, std::string& residents_string)
{
llassert(avatar_names.size() > 0);
const std::string& separator = LLTrans::getString("words_separator");
for (std::vector<std::string>::const_iterator it = avatar_names.begin(); ; )
{
residents_string.append(*it);
if (++it == avatar_names.end())
{
break;
}
residents_string.append(separator);
}
}
static void build_items_string(const uuid_set_t& inventory_selected_uuids , std::string& items_string)
{
llassert(inventory_selected_uuids.size() > 0);
const std::string& separator = LLTrans::getString("words_separator");
for (uuid_set_t::const_iterator it = inventory_selected_uuids.begin(); ; )
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (NULL != inv_cat)
{
items_string = inv_cat->getName();
break;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
if (NULL != inv_item)
{
items_string.append(inv_item->getName());
}
if(++it == inventory_selected_uuids.end())
{
break;
}
items_string.append(separator);
}
}
struct LLShareInfo : public LLSingleton<LLShareInfo>
{
std::vector<std::string> mAvatarNames;
uuid_vec_t mAvatarUuids;
};
static void give_inventory_cb(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// if Cancel pressed
if (option == 1)
{
return;
}
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
if (NULL == active_panel)
{
return;
}
const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
if (inventory_selected_uuids.empty())
{
return;
}
S32 count = LLShareInfo::instance().mAvatarNames.size();
bool shared = false;
// iterate through avatars
for(S32 i = 0; i < count; ++i)
{
const std::string& avatar_name = LLShareInfo::instance().mAvatarNames[i];
const LLUUID& avatar_uuid = LLShareInfo::instance().mAvatarUuids[i];
// Start up IM before give the item
const LLUUID session_id = gIMMgr->addSession(avatar_name, IM_NOTHING_SPECIAL, avatar_uuid);
uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
const std::string& separator = LLTrans::getString("words_separator");
std::string noncopy_item_names;
LLSD noncopy_items = LLSD::emptyArray();
// iterate through selected inventory objects
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (inv_cat)
{
LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id);
shared = true;
break;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
if (!inv_item->getPermissions().allowCopyBy(gAgentID))
{
if (!noncopy_item_names.empty())
{
noncopy_item_names.append(separator);
}
noncopy_item_names.append(inv_item->getName());
noncopy_items.append(*it);
}
else
{
LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
shared = true;
}
}
if (noncopy_items.beginArray() != noncopy_items.endArray())
{
LLSD substitutions;
substitutions["ITEMS"] = noncopy_item_names;
LLSD payload;
payload["agent_id"] = avatar_uuid;
payload["items"] = noncopy_items;
LLNotificationsUtil::add("CannotCopyWarning", substitutions, payload,
&LLGiveInventory::handleCopyProtectedItem);
break;
}
}
if (shared)
{
LLFloaterReg::hideInstance("avatar_picker");
LLNotificationsUtil::add("ItemsShared");
}
}
/**
* Performs "give inventory" operations for provided avatars.
*
@ -488,39 +620,31 @@ namespace action_give_inventory
{
llassert(avatar_names.size() == avatar_uuids.size());
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
if (NULL == active_panel) return;
if (NULL == active_panel)
{
return;
}
const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
if (inventory_selected_uuids.empty()) return;
S32 count = llmin(avatar_names.size(), avatar_uuids.size());
// iterate through avatars
for(S32 i = 0; i < count; ++i)
if (inventory_selected_uuids.empty())
{
const std::string& avatar_name = avatar_names[i];
const LLUUID& avatar_uuid = avatar_uuids[i];
// Start up IM before give the item
const LLUUID session_id = gIMMgr->addSession(avatar_name, IM_NOTHING_SPECIAL, avatar_uuid);
uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
// iterate through selected inventory objects
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (inv_cat)
{
LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id);
break;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
}
return;
}
std::string residents;
build_residents_string(avatar_names, residents);
std::string items;
build_items_string(inventory_selected_uuids, items);
LLSD substitutions;
substitutions["RESIDENTS"] = residents;
substitutions["ITEMS"] = items;
LLShareInfo::instance().mAvatarNames = avatar_names;
LLShareInfo::instance().mAvatarUuids = avatar_uuids;
LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, LLSD(), &give_inventory_cb);
}
}
@ -532,7 +656,6 @@ void LLAvatarActions::shareWithAvatars()
LLFloaterAvatarPicker* picker =
LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE);
picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable));
LLNotificationsUtil::add("ShareNotification");
}
// static

View File

@ -1170,7 +1170,6 @@ void LLBottomTray::initResizeStateContainers()
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, getChild<LLPanel>("movement_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, getChild<LLPanel>("cam_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, getChild<LLPanel>("snapshot_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SIDEBAR, getChild<LLPanel>("sidebar_btn_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_BUILD, getChild<LLPanel>("build_btn_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SEARCH, getChild<LLPanel>("search_btn_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_WORLD_MAP, getChild<LLPanel>("world_map_btn_panel")));
@ -1181,7 +1180,6 @@ void LLBottomTray::initResizeStateContainers()
mButtonsProcessOrder.push_back(RS_BUTTON_MOVEMENT);
mButtonsProcessOrder.push_back(RS_BUTTON_CAMERA);
mButtonsProcessOrder.push_back(RS_BUTTON_SNAPSHOT);
mButtonsProcessOrder.push_back(RS_BUTTON_SIDEBAR);
mButtonsProcessOrder.push_back(RS_BUTTON_BUILD);
mButtonsProcessOrder.push_back(RS_BUTTON_SEARCH);
mButtonsProcessOrder.push_back(RS_BUTTON_WORLD_MAP);
@ -1217,7 +1215,6 @@ void LLBottomTray::initButtonsVisibility()
setVisibleAndFitWidths(RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"));
setVisibleAndFitWidths(RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"));
setVisibleAndFitWidths(RS_BUTTON_SNAPSHOT, gSavedSettings.getBOOL("ShowSnapshotButton"));
setVisibleAndFitWidths(RS_BUTTON_SIDEBAR, gSavedSettings.getBOOL("ShowSidebarButton"));
setVisibleAndFitWidths(RS_BUTTON_BUILD, gSavedSettings.getBOOL("ShowBuildButton"));
setVisibleAndFitWidths(RS_BUTTON_SEARCH, gSavedSettings.getBOOL("ShowSearchButton"));
setVisibleAndFitWidths(RS_BUTTON_WORLD_MAP, gSavedSettings.getBOOL("ShowWorldMapButton"));
@ -1230,7 +1227,6 @@ void LLBottomTray::setButtonsControlsAndListeners()
gSavedSettings.getControl("ShowMoveButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MOVEMENT, _2));
gSavedSettings.getControl("ShowCameraButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_CAMERA, _2));
gSavedSettings.getControl("ShowSnapshotButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SNAPSHOT, _2));
gSavedSettings.getControl("ShowSidebarButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SIDEBAR, _2));
gSavedSettings.getControl("ShowBuildButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_BUILD, _2));
gSavedSettings.getControl("ShowSearchButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SEARCH, _2));
gSavedSettings.getControl("ShowWorldMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_WORLD_MAP, _2));

View File

@ -124,7 +124,6 @@ private:
, RS_BUTTON_SEARCH = 0x0400
, RS_BUTTON_WORLD_MAP = 0x0800
, RS_BUTTON_MINI_MAP = 0x1000
, RS_BUTTON_SIDEBAR = 0x2000
/*
Once new button that can be hidden on resize is added don't forget to update related places:
@ -139,7 +138,6 @@ private:
*/
, RS_BUTTONS_CAN_BE_HIDDEN = RS_BUTTON_SNAPSHOT | RS_BUTTON_CAMERA | RS_BUTTON_MOVEMENT | RS_BUTTON_GESTURES
| RS_BUTTON_BUILD | RS_BUTTON_SEARCH | RS_BUTTON_WORLD_MAP | RS_BUTTON_MINI_MAP
| RS_BUTTON_SIDEBAR
}EResizeState;
/**

View File

@ -846,12 +846,3 @@ void LLChatHistory::draw()
LLUICtrl::draw();
}
void LLChatHistory::reshape(S32 width, S32 height, BOOL called_from_parent)
{
bool is_scrolled_to_end = mEditor->scrolledToEnd();
LLUICtrl::reshape( width, height, called_from_parent );
// update scroll
if (is_scrolled_to_end)
mEditor->setCursorAndScrollToEnd();
}

View File

@ -122,7 +122,6 @@ class LLChatHistory : public LLUICtrl
*/
void appendMessage(const LLChat& chat, const LLSD &args = LLSD(), const LLStyle::Params& input_append_params = LLStyle::Params());
/*virtual*/ void clear();
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
private:
std::string mLastFromName;

View File

@ -45,8 +45,7 @@
#include "llwearableitemslist.h"
#include "llpaneloutfitedit.h"
#include "llsidetray.h"
static LLRegisterPanelClassWrapper<LLCOFAccordionListAdaptor> t_cof_accodion_list_adaptor("accordion_list_adaptor");
#include "lltrans.h"
static LLRegisterPanelClassWrapper<LLCOFWearables> t_cof_wearables("cof_wearables");
@ -54,6 +53,39 @@ const LLSD REARRANGE = LLSD().with("rearrange", LLSD());
static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR;
//////////////////////////////////////////////////////////////////////////
class CofContextMenu : public LLListContextMenu
{
protected:
static void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id)
{
LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new");
// Hide the "Create new <WEARABLE_TYPE>" if it's irrelevant.
LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
if (!item || !item->isWearableType())
{
menu_item->setVisible(FALSE);
return;
}
// Set proper label for the "Create new <WEARABLE_TYPE>" menu item.
LLStringUtil::format_map_t args;
LLWearableType::EType w_type = item->getWearableType();
args["[WEARABLE_TYPE]"] = LLWearableType::getTypeDefaultNewName(w_type);
std::string new_label = LLTrans::getString("CreateNewWearable", args);
menu_item->setLabel(new_label);
}
static void createNew(const LLUUID& item_id)
{
LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
if (!item || !item->isWearableType()) return;
LLAgentWearables::createWearable(item->getWearableType(), true);
}
};
//////////////////////////////////////////////////////////////////////////
@ -74,7 +106,7 @@ protected:
//////////////////////////////////////////////////////////////////////////
class CofClothingContextMenu : public LLListContextMenu
class CofClothingContextMenu : public CofContextMenu
{
protected:
@ -89,10 +121,17 @@ protected:
registrar.add("Clothing.MoveUp", boost::bind(moveWearable, selected_id, false));
registrar.add("Clothing.MoveDown", boost::bind(moveWearable, selected_id, true));
registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
registrar.add("Clothing.Create", boost::bind(createNew, selected_id));
enable_registrar.add("Clothing.OnEnable", boost::bind(&CofClothingContextMenu::onEnable, this, _2));
return createFromFile("menu_cof_clothing.xml");
LLContextMenu* menu = createFromFile("menu_cof_clothing.xml");
llassert(menu);
if (menu)
{
updateCreateWearableLabel(menu, selected_id);
}
return menu;
}
bool onEnable(const LLSD& data)
@ -108,6 +147,10 @@ protected:
{
return gAgentWearables.canMoveWearable(selected_id, true);
}
else if ("take_off" == param)
{
return get_is_item_worn(selected_id);
}
else if ("edit" == param)
{
return gAgentWearables.isWearableModifiable(selected_id);
@ -122,12 +165,11 @@ protected:
LLViewerInventoryItem* item = gInventory.getItem(item_id);
return LLAppearanceMgr::instance().moveWearable(item, closer_to_body);
}
};
//////////////////////////////////////////////////////////////////////////
class CofBodyPartContextMenu : public LLListContextMenu
class CofBodyPartContextMenu : public CofContextMenu
{
protected:
@ -142,10 +184,17 @@ protected:
LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit"));
registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id));
registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
registrar.add("BodyPart.Create", boost::bind(createNew, selected_id));
enable_registrar.add("BodyPart.OnEnable", boost::bind(&CofBodyPartContextMenu::onEnable, this, _2));
return createFromFile("menu_cof_body_part.xml");
LLContextMenu* menu = createFromFile("menu_cof_body_part.xml");
llassert(menu);
if (menu)
{
updateCreateWearableLabel(menu, selected_id);
}
return menu;
}
bool onEnable(const LLSD& data)
@ -338,7 +387,13 @@ LLPanelClothingListItem* LLCOFWearables::buildClothingListItem(LLViewerInventory
item_panel->childSetAction("btn_edit", mCOFCallbacks.mEditWearable);
//turning on gray separator line for the last item in the items group of the same wearable type
item_panel->childSetVisible("wearable_type_separator_panel", last);
if (last)
{
LLRect rect = item_panel->getRect();
item_panel->reshape(rect.getWidth(), rect.getHeight() +
item_panel->getChild<LLView>("wearable_type_separator_icon")->getRect().getHeight());
item_panel->childSetVisible("wearable_type_separator_icon", true);
}
return item_panel;
}

View File

@ -45,53 +45,6 @@ class LLPanelClothingListItem;
class LLPanelBodyPartsListItem;
class LLPanelDeletableWearableListItem;
/**
* Adaptor between LLAccordionCtrlTab and LLFlatListView to facilitate communication between them
* (notify, notifyParent) regarding size changes of a list and selection changes across accordion tabs.
* Besides that it acts as a container for the LLFlatListView and a button bar on top of it.
*/
class LLCOFAccordionListAdaptor : public LLPanel
{
public:
LLCOFAccordionListAdaptor() : LLPanel() {};
~LLCOFAccordionListAdaptor() {};
S32 notifyParent(const LLSD& info)
{
LLView* parent = getParent();
if (!parent) return -1;
if (!(info.has("action") && "size_changes" == info["action"].asString()))
{
return parent->notifyParent(info);
}
LLRect rc;
childGetRect("button_bar", rc);
LLSD params;
params["action"] = "size_changes";
params["width"] = info["width"];
params["height"] = info["height"].asInteger() + rc.getHeight();
return parent->notifyParent(params);
}
S32 notify(const LLSD& info)
{
for (child_list_const_iter_t iter = beginChild(); iter != endChild(); iter++)
{
if (dynamic_cast<LLFlatListView*>(*iter))
{
return (*iter)->notify(info);
}
}
return LLPanel::notify(info);
};
};
class LLCOFWearables : public LLPanel
{
public:

View File

@ -68,7 +68,7 @@ LLColorSwatchCtrl::Params::Params()
LLColorSwatchCtrl::LLColorSwatchCtrl(const Params& p)
: LLUICtrl(p),
mValid( TRUE ),
mColor(p.color),
mColor(p.color()),
mCanApplyImmediately(p.can_apply_immediately),
mAlphaGradientImage(p.alpha_background_image),
mOnCancelCallback(p.cancel_callback()),

View File

@ -60,7 +60,7 @@ public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<LLColor4> color;
Optional<LLUIColor> color;
Optional<bool> can_apply_immediately;
Optional<LLUIImage*> alpha_background_image;
Optional<commit_callback_t> cancel_callback;

View File

@ -634,7 +634,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (!single_avatar && !avatarp->isFullyLoaded() )
{
if (pass==1 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
{
// debug code to draw a sphere in place of avatar
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
@ -646,8 +646,10 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
gGL.translatef((F32)(pos.mV[VX]),
(F32)(pos.mV[VY]),
(F32)(pos.mV[VZ]));
gGL.scalef(0.15f, 0.15f, 0.3f);
gSphere.render();
gGL.scalef(0.15f, 0.15f, 0.3f);
gSphere.renderGGL();
gGL.popMatrix();
gGL.setColorMask(true, false);
}

View File

@ -54,6 +54,15 @@ LLFilteredWearableListManager::~LLFilteredWearableListManager()
void LLFilteredWearableListManager::changed(U32 mask)
{
if (LLInventoryObserver::CALLING_CARD == mask
|| LLInventoryObserver::GESTURE == mask
|| LLInventoryObserver::SORT == mask
)
{
// skip non-related changes
return;
}
if(!gInventory.isInventoryUsable())
{
return;

View File

@ -437,7 +437,7 @@ BOOL LLFloaterAvatarPicker::handleDragAndDrop(S32 x, S32 y, MASK mask,
session_id = gIMMgr->addSession(avatar_name, IM_NOTHING_SPECIAL, dest_agent_id);
}
return LLToolDragAndDrop::handleGiveDragAndDrop(dest_agent_id, session_id, drop,
cargo_type, cargo_data, accept);
cargo_type, cargo_data, accept, getName());
}
}
}

View File

@ -572,7 +572,7 @@ void LLPanelLandGeneral::refresh()
if (regionp)
{
insert_maturity_into_textbox(mContentRating, gFloaterView->getParentFloater(this), MATURITY);
mLandType->setText(regionp->getSimProductName());
mLandType->setText(LLTrans::getString(regionp->getSimProductName()));
}
// estate owner/manager cannot edit other parts of the parcel

View File

@ -106,6 +106,8 @@ BOOL LLFloaterMap::postBuild()
mPopupMenu->setItemEnabled ("Stop Tracking", false);
}
stretchMiniMap(getRect().getWidth(),getRect().getHeight());
updateMinorDirections();
// Get the drag handle all the way in back
@ -229,10 +231,8 @@ void LLFloaterMap::onFocusLost()
LLPanel::onFocusLost();
}
void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent)
void LLFloaterMap::stretchMiniMap(S32 width,S32 height)
{
LLFloater::reshape(width, height, called_from_parent);
//fix for ext-7112
//by default ctrl can't overlap caption area
if(mMap)
@ -242,6 +242,13 @@ void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent)
mMap->reshape( width, height, 1);
mMap->setRect(map_rect);
}
}
void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLFloater::reshape(width, height, called_from_parent);
stretchMiniMap(width, height);
updateMinorDirections();
}

View File

@ -61,6 +61,8 @@ private:
void handleStopTracking (const LLSD& userdata);
void setDirectionPos( LLTextBox* text_box, F32 rotation );
void updateMinorDirections();
void stretchMiniMap(S32 width,S32 height);
LLMenuGL* mPopupMenu;

View File

@ -501,7 +501,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)
if (can_choose_maturity)
{
// if they're not adult or a god, they shouldn't see the adult selection, so delete it
if (!gAgent.isAdult() && !gAgent.isGodlike())
if (!gAgent.isAdult() && !gAgent.isGodlikeWithoutAdminMenuFakery())
{
// we're going to remove the adult entry from the combo
LLScrollListCtrl* maturity_list = maturity_combo->findChild<LLScrollListCtrl>("ComboBox");
@ -966,7 +966,7 @@ void LLFloaterPreference::cleanupBadSetting()
{
if (gSavedPerAccountSettings.getString("BusyModeResponse2") == "|TOKEN COPY BusyModeResponse|")
{
llwarns << "cleaning old BusyModeResponse" << llendl;
llinfos << "cleaning old BusyModeResponse" << llendl;
//LLTrans::getString("BusyModeResponseDefault") is used here for localization (EXT-5885)
gSavedPerAccountSettings.setString("BusyModeResponse2", LLTrans::getString("BusyModeResponseDefault"));
}

View File

@ -192,15 +192,16 @@ bool LLGiveInventory::isInventoryGroupGiveAcceptable(const LLInventoryItem* item
}
// static
void LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent,
bool LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent,
const LLInventoryItem* item,
const LLUUID& im_session_id/* = LLUUID::null*/)
{
bool res = true;
llinfos << "LLGiveInventory::giveInventory()" << llendl;
if (!isInventoryGiveAcceptable(item))
{
return;
return false;
}
if (item->getPermissions().allowCopyBy(gAgentID))
{
@ -210,12 +211,19 @@ void LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent,
else
{
// ask if the agent is sure.
LLSD substitutions;
substitutions["ITEMS"] = item->getName();
LLSD payload;
payload["agent_id"] = to_agent;
payload["item_id"] = item->getUUID();
LLNotificationsUtil::add("CannotCopyWarning", LLSD(), payload,
LLSD items = LLSD::emptyArray();
items.append(item->getUUID());
payload["items"] = items;
LLNotificationsUtil::add("CannotCopyWarning", substitutions, payload,
&LLGiveInventory::handleCopyProtectedItem);
res = false;
}
return res;
}
void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
@ -318,23 +326,27 @@ void LLGiveInventory::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im
bool LLGiveInventory::handleCopyProtectedItem(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLSD itmes = notification["payload"]["items"];
LLInventoryItem* item = NULL;
switch(option)
{
case 0: // "Yes"
item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
if (item)
for (LLSD::array_iterator it = itmes.beginArray(); it != itmes.endArray(); it++)
{
LLGiveInventory::commitGiveInventoryItem(notification["payload"]["agent_id"].asUUID(),
item);
// delete it for now - it will be deleted on the server
// quickly enough.
gInventory.deleteObject(notification["payload"]["item_id"].asUUID());
gInventory.notifyObservers();
}
else
{
LLNotificationsUtil::add("CannotGiveItem");
item = gInventory.getItem((*it).asUUID());
if (item)
{
LLGiveInventory::commitGiveInventoryItem(notification["payload"]["agent_id"].asUUID(),
item);
// delete it for now - it will be deleted on the server
// quickly enough.
gInventory.deleteObject(item->getUUID());
gInventory.notifyObservers();
}
else
{
LLNotificationsUtil::add("CannotGiveItem");
}
}
break;

View File

@ -61,7 +61,7 @@ public:
/**
* Gives passed inventory item to specified avatar in specified session.
*/
static void doGiveInventoryItem(const LLUUID& to_agent,
static bool doGiveInventoryItem(const LLUUID& to_agent,
const LLInventoryItem* item,
const LLUUID& im_session_id = LLUUID::null);
@ -72,6 +72,9 @@ public:
const LLInventoryCategory* item,
const LLUUID &session_id = LLUUID::null);
// give inventory item functionality
static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response);
private:
// this class is not intended to be instantiated.
LLGiveInventory();
@ -82,8 +85,6 @@ private:
static void logInventoryOffer(const LLUUID& to_agent,
const LLUUID &im_session_id = LLUUID::null);
// give inventory item functionality
static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response);
static void commitGiveInventoryItem(const LLUUID& to_agent,
const LLInventoryItem* item,
const LLUUID &im_session_id = LLUUID::null);

View File

@ -103,7 +103,6 @@ void dec_busy_count()
}
// Function declarations
void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
void remove_inventory_category_from_avatar(LLInventoryCategory* category);
void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
@ -164,38 +163,7 @@ time_t LLInvFVBridge::getCreationDate() const
// Can be destroyed (or moved to trash)
BOOL LLInvFVBridge::isItemRemovable() const
{
const LLInventoryModel* model = getInventoryModel();
if(!model)
{
return FALSE;
}
// Can't delete an item that's in the library.
if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
{
return FALSE;
}
// Disable delete from COF folder; have users explicitly choose "detach/take off",
// unless the item is not worn but in the COF (i.e. is bugged).
if (LLAppearanceMgr::instance().getIsProtectedCOFItem(mUUID))
{
if (get_is_item_worn(mUUID))
{
return FALSE;
}
}
const LLInventoryObject *obj = model->getItem(mUUID);
if (obj && obj->getIsLinkType())
{
return TRUE;
}
if (get_is_item_worn(mUUID))
{
return FALSE;
}
return TRUE;
return get_is_item_removable(getInventoryModel(), mUUID);
}
// Can be moved to another folder
@ -833,24 +801,7 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
const LLUUID& new_parent_id,
BOOL restamp)
{
// Can't move a folder into a child of itself.
if (model->isObjectDescendentOf(new_parent_id, cat->getUUID()))
{
return;
}
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
update.push_back(old_folder);
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
update.push_back(new_folder);
model->accountForUpdate(update);
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->setParent(new_parent_id);
new_cat->updateParentOnServer(restamp);
model->updateCategory(new_cat);
model->notifyObservers();
change_category_parent(model, cat, new_parent_id, restamp);
}
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
@ -1242,18 +1193,18 @@ void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
{
U8 font = LLFontGL::NORMAL;
const LLViewerInventoryItem* item = getItem();
if (get_is_item_worn(mUUID))
{
// llinfos << "BOLD" << llendl;
font |= LLFontGL::BOLD;
}
const LLViewerInventoryItem* item = getItem();
if (item && item->getIsLinkType())
else if(item && item->getIsLinkType())
{
font |= LLFontGL::ITALIC;
}
return (LLFontGL::StyleFlags)font;
}
@ -1538,26 +1489,7 @@ public:
// Can be destroyed (or moved to trash)
BOOL LLFolderBridge::isItemRemovable() const
{
LLInventoryModel* model = getInventoryModel();
if(!model)
{
return FALSE;
}
if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
{
return FALSE;
}
if (!isAgentAvatarValid()) return FALSE;
LLInventoryCategory* category = model->getCategory(mUUID);
if(!category)
{
return FALSE;
}
if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
if (!get_is_category_removable(getInventoryModel(), mUUID))
{
return FALSE;
}
@ -1573,6 +1505,7 @@ BOOL LLFolderBridge::isItemRemovable() const
return FALSE;
}
}
return TRUE;
}
@ -2333,10 +2266,20 @@ LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type, BOOL is
else
return LLUI::getUIImage("Inv_FolderClosed_Link");
}
if (preferred_type == LLFolderType::FT_OUTFIT)
switch (preferred_type)
{
case LLFolderType::FT_OUTFIT:
return LLUI::getUIImage("Inv_LookFolderClosed");
else
case LLFolderType::FT_LOST_AND_FOUND:
return LLUI::getUIImage("Inv_LostClosed");
case LLFolderType::FT_TRASH:
return LLUI::getUIImage("Inv_TrashClosed");
case LLFolderType::FT_NONE:
return LLUI::getUIImage("Inv_FolderClosed");
default:
return LLUI::getUIImage("Inv_SysClosed");
}
}
LLUIImagePtr LLFolderBridge::getOpenIcon() const
@ -2350,29 +2293,27 @@ LLUIImagePtr LLFolderBridge::getOpenIcon() const
else
return LLUI::getUIImage("Inv_FolderOpen_Link");
}
if (getPreferredType() == LLFolderType::FT_OUTFIT)
switch (getPreferredType())
{
case LLFolderType::FT_OUTFIT:
return LLUI::getUIImage("Inv_LookFolderOpen");
else
case LLFolderType::FT_LOST_AND_FOUND:
return LLUI::getUIImage("Inv_LostOpen");
case LLFolderType::FT_TRASH:
return LLUI::getUIImage("Inv_TrashOpen");
case LLFolderType::FT_NONE:
return LLUI::getUIImage("Inv_FolderOpen");
default:
return LLUI::getUIImage("Inv_SysOpen");
}
}
BOOL LLFolderBridge::renameItem(const std::string& new_name)
{
if(!isItemRenameable())
return FALSE;
LLInventoryModel* model = getInventoryModel();
if(!model)
return FALSE;
LLViewerInventoryCategory* cat = getCategory();
if(cat && (cat->getName() != new_name))
{
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
rename_category(getInventoryModel(), mUUID, new_name);
model->notifyObservers();
}
// return FALSE because we either notified observers (& therefore
// rebuilt) or we didn't update.
return FALSE;
@ -2426,36 +2367,7 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re
{
// move it to the trash
LLPreview::hide(mUUID);
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
// Look for any gestures and deactivate them
LLInventoryModel::cat_array_t descendent_categories;
LLInventoryModel::item_array_t descendent_items;
gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
iter != descendent_items.end();
++iter)
{
const LLViewerInventoryItem* item = (*iter);
const LLUUID& item_id = item->getUUID();
if (item->getType() == LLAssetType::AT_GESTURE
&& LLGestureMgr::instance().isGestureActive(item_id))
{
LLGestureMgr::instance().deactivateGesture(item_id);
}
}
// go ahead and do the normal remove if no 'last calling
// cards' are being removed.
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
}
remove_category(getInventoryModel(), mUUID);
return TRUE;
}
return FALSE;
@ -2651,22 +2563,6 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
return ((item_array.count() > 0) ? TRUE : FALSE );
}
class LLFindWorn : public LLInventoryCollectFunctor
{
public:
LLFindWorn() {}
virtual ~LLFindWorn() {}
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if (item && get_is_item_worn(item->getUUID()))
{
return TRUE;
}
return FALSE;
}
};
BOOL LLFolderBridge::areAnyContentsWorn(LLInventoryModel* model) const
{
LLInventoryModel::cat_array_t cat_array;
@ -2985,22 +2881,7 @@ void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::ETyp
{
if(!bridge) return;
LLUUID parent_id = bridge->getUUID();
createWearable(parent_id, type);
}
// Separate function so can be called by global menu as well as right-click
// menu.
// static
void LLFolderBridge::createWearable(const LLUUID &parent_id, LLWearableType::EType type)
{
LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
LLAssetType::EType asset_type = wearable->getAssetType();
LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
parent_id, wearable->getTransactionID(), wearable->getName(),
wearable->getDescription(), asset_type, inv_type, wearable->getType(),
wearable->getPermissions().getMaskNextOwner(),
LLPointer<LLInventoryCallback>(NULL));
LLAgentWearables::createWearable(type, false, parent_id);
}
void LLFolderBridge::modifyOutfit(BOOL append)
@ -4147,24 +4028,6 @@ void LLObjectBridge::openItem()
get_is_item_worn(mUUID) ? "detach" : "attach");
}
LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
{
U8 font = LLFontGL::NORMAL;
if(get_is_item_worn( mUUID ) )
{
font |= LLFontGL::BOLD;
}
LLInventoryItem* item = getItem();
if (item && item->getIsLinkType())
{
font |= LLFontGL::ITALIC;
}
return (LLFontGL::StyleFlags)font;
}
std::string LLObjectBridge::getLabelSuffix() const
{
if (get_is_item_worn(mUUID))
@ -4413,33 +4276,6 @@ LLWearableBridge::LLWearableBridge(LLInventoryPanel* inventory,
mInvType = inv_type;
}
// *NOTE: hack to get from avatar inventory to avatar
void wear_inventory_item_on_avatar( LLInventoryItem* item )
{
if(item)
{
lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
<< " )" << llendl;
LLAppearanceMgr::getInstance()->wearItemOnAvatar(item->getUUID(), true, false);
}
}
void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
{
if(item)
{
lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
<< " )" << llendl;
LLWearableList::instance().getAsset(item->getAssetUUID(),
item->getName(),
item->getType(),
LLWearableBridge::onWearAddOnAvatarArrived,
new LLUUID(item->getUUID()));
}
}
void remove_inventory_category_from_avatar( LLInventoryCategory* category )
{
if(!category) return;
@ -4755,21 +4591,7 @@ void LLWearableBridge::wearOnAvatar()
LLViewerInventoryItem* item = getItem();
if(item)
{
if(!isAgentInventory())
{
LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
LLUUID::null,
std::string(),
cb);
}
else
{
wear_inventory_item_on_avatar(item);
}
LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true);
}
}
@ -4786,21 +4608,7 @@ void LLWearableBridge::wearAddOnAvatar()
LLViewerInventoryItem* item = getItem();
if(item)
{
if(!isAgentInventory())
{
LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
LLUUID::null,
std::string(),
cb);
}
else
{
wear_add_inventory_item_on_avatar(item);
}
LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, false);
}
}
@ -4877,13 +4685,7 @@ void LLWearableBridge::onEditOnAvatar(void* user_data)
void LLWearableBridge::editOnAvatar()
{
LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID);
if( wearable )
{
LLPanel * panel = LLSideTray::getInstance()->getPanel("sidepanel_appearance");
LLSidepanelAppearance::editWearable(wearable, panel);
}
LLAgentWearables::editWearable(mUUID);
}
// static
@ -5331,41 +5133,7 @@ class LLWearableBridgeAction: public LLInvFVBridgeAction
public:
virtual void doIt()
{
if(isItemInTrash())
{
LLNotificationsUtil::add("CannotWearTrash");
}
else if(isAgentInventory())
{
if(!get_is_item_worn(mUUID))
{
wearOnAvatar();
}
}
else
{
// must be in the inventory library. copy it to our inventory
// and put it on right away.
LLViewerInventoryItem* item = getItem();
if(item && item->isFinished())
{
LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
LLUUID::null,
std::string(),
cb);
}
else if(item)
{
// *TODO: We should fetch the item details, and then do
// the operation above.
LLNotificationsUtil::add("CannotWearInfoNotComplete");
}
}
LLInvFVBridgeAction::doIt();
wearOnAvatar();
}
virtual ~LLWearableBridgeAction(){}
protected:
@ -5404,21 +5172,7 @@ void LLWearableBridgeAction::wearOnAvatar()
LLViewerInventoryItem* item = getItem();
if(item)
{
if(!isAgentInventory())
{
LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
LLUUID::null,
std::string(),
cb);
}
else
{
wear_inventory_item_on_avatar(item);
}
LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true);
}
}

View File

@ -270,7 +270,6 @@ public:
virtual BOOL copyToClipboard() const;
static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);
static void createWearable(const LLUUID &parent_folder_id, LLWearableType::EType type);
LLViewerInventoryCategory* getCategory() const;
@ -437,7 +436,6 @@ public:
virtual LLUIImagePtr getIcon() const;
virtual void performAction(LLInventoryModel* model, std::string action);
virtual void openItem();
virtual LLFontGL::StyleFlags getLabelStyle() const;
virtual std::string getLabelSuffix() const;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual BOOL renameItem(const std::string& new_name);
@ -593,8 +591,6 @@ public:
U32 flags = 0x00) const;
};
void wear_inventory_item_on_avatar(LLInventoryItem* item);
void rez_attachment(LLViewerInventoryItem* item,
LLViewerJointAttachment* attachment);

View File

@ -130,6 +130,88 @@ void change_item_parent(LLInventoryModel* model,
}
}
void change_category_parent(LLInventoryModel* model,
LLViewerInventoryCategory* cat,
const LLUUID& new_parent_id,
BOOL restamp)
{
if (!model || !cat)
{
return;
}
// Can't move a folder into a child of itself.
if (model->isObjectDescendentOf(new_parent_id, cat->getUUID()))
{
return;
}
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
update.push_back(old_folder);
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
update.push_back(new_folder);
model->accountForUpdate(update);
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->setParent(new_parent_id);
new_cat->updateParentOnServer(restamp);
model->updateCategory(new_cat);
model->notifyObservers();
}
void remove_category(LLInventoryModel* model, const LLUUID& cat_id)
{
if (!model || !get_is_category_removable(model, cat_id))
{
return;
}
// Look for any gestures and deactivate them
LLInventoryModel::cat_array_t descendent_categories;
LLInventoryModel::item_array_t descendent_items;
gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
iter != descendent_items.end();
++iter)
{
const LLViewerInventoryItem* item = (*iter);
const LLUUID& item_id = item->getUUID();
if (item->getType() == LLAssetType::AT_GESTURE
&& LLGestureMgr::instance().isGestureActive(item_id))
{
LLGestureMgr::instance().deactivateGesture(item_id);
}
}
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (cat)
{
const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
change_category_parent(model, cat, trash_id, TRUE);
}
}
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name)
{
LLViewerInventoryCategory* cat;
if (!model ||
!get_is_category_renameable(model, cat_id) ||
(cat = model->getCategory(cat_id)) == NULL ||
cat->getName() == new_name)
{
return;
}
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
model->notifyObservers();
}
BOOL get_is_item_worn(const LLUUID& id)
{
@ -160,6 +242,83 @@ BOOL get_is_item_worn(const LLUUID& id)
return FALSE;
}
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
{
if (!model)
{
return FALSE;
}
// Can't delete an item that's in the library.
if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
{
return FALSE;
}
// Disable delete from COF folder; have users explicitly choose "detach/take off",
// unless the item is not worn but in the COF (i.e. is bugged).
if (LLAppearanceMgr::instance().getIsProtectedCOFItem(id))
{
if (get_is_item_worn(id))
{
return FALSE;
}
}
const LLInventoryObject *obj = model->getItem(id);
if (obj && obj->getIsLinkType())
{
return TRUE;
}
if (get_is_item_worn(id))
{
return FALSE;
}
return TRUE;
}
BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
{
// This function doesn't check the folder's children.
if (!model)
{
return FALSE;
}
if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
{
return FALSE;
}
if (!isAgentAvatarValid()) return FALSE;
LLInventoryCategory* category = model->getCategory(id);
if (!category)
{
return FALSE;
}
if (LLFolderType::lookupIsProtectedType(category->getPreferredType()))
{
return FALSE;
}
return TRUE;
}
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
{
LLViewerInventoryCategory* cat = model->getCategory(id);
if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) &&
cat->getOwnerID() == gAgent.getID())
{
return TRUE;
}
return FALSE;
}
void show_item_profile(const LLUUID& item_uuid)
{
LLUUID linked_uuid = gInventory.getLinkedItemID(item_uuid);
@ -376,6 +535,26 @@ void LLFindWearablesOfType::setType(LLWearableType::EType type)
mWearableType = type;
}
bool LLFindWorn::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return item && get_is_item_worn(item->getUUID());
}
bool LLFindNonRemovableObjects::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if (item)
{
return !get_is_item_removable(&gInventory, item->getUUID());
}
if (cat)
{
return !get_is_category_removable(&gInventory, cat->getUUID());
}
llwarns << "Not a category and not an item?" << llendl;
return false;
}
///----------------------------------------------------------------------------
/// LLAssetIDMatches
///----------------------------------------------------------------------------

View File

@ -46,6 +46,12 @@
// Is this item or its baseitem is worn, attached, etc...
BOOL get_is_item_worn(const LLUUID& id);
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id);
BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id);
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id);
void show_item_profile(const LLUUID& item_uuid);
void show_item_original(const LLUUID& item_uuid);
@ -55,6 +61,15 @@ void change_item_parent(LLInventoryModel* model,
const LLUUID& new_parent_id,
BOOL restamp);
void change_category_parent(LLInventoryModel* model,
LLViewerInventoryCategory* cat,
const LLUUID& new_parent_id,
BOOL restamp);
void remove_category(LLInventoryModel* model, const LLUUID& cat_id);
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name);
// Generates a string containing the path to the item specified by item_id.
void append_path(const LLUUID& id, std::string& path);
@ -309,6 +324,22 @@ private:
LLWearableType::EType mWearableType;
};
// Find worn items.
class LLFindWorn : public LLInventoryCollectFunctor
{
public:
LLFindWorn() {}
virtual ~LLFindWorn() {}
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
};
// Collect non-removable folders and items.
class LLFindNonRemovableObjects : public LLInventoryCollectFunctor
{
public:
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
};
/** Inventory Collector Functions
** **
*******************************************************************************/

View File

@ -132,7 +132,8 @@ BOOL LLPanelInventoryListItemBase::postBuild()
setIconCtrl(getChild<LLIconCtrl>("item_icon"));
setTitleCtrl(getChild<LLTextBox>("item_name"));
mIconImage = LLInventoryIcon::getIcon(mItem->getType(), mItem->getInventoryType(), mItem->getIsLinkType(), mItem->getFlags(), FALSE);
BOOL show_links = mForceNoLinksOnIcons ? FALSE : mItem->getIsLinkType();
mIconImage = LLInventoryIcon::getIcon(mItem->getType(), mItem->getInventoryType(), show_links, mItem->getFlags(), FALSE);
setNeedsRefresh(true);
@ -198,6 +199,7 @@ LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem
, mLeftWidgetsWidth(0)
, mRightWidgetsWidth(0)
, mNeedsRefresh(false)
, mForceNoLinksOnIcons(false)
{
}

View File

@ -179,6 +179,9 @@ protected:
/** Set item title - inventory item name usually */
void setTitle(const std::string& title, const std::string& highlit_text);
// force not showing link icon on item's icon
bool mForceNoLinksOnIcons;
private:
/** reshape left side widgets

View File

@ -35,6 +35,7 @@
#include "llagent.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "llinventorypanel.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
@ -2561,7 +2562,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
{
LLViewerInventoryItem* wearable_item;
wearable_item = gInventory.getItem(wearable_ids[i]);
wear_inventory_item_on_avatar(wearable_item);
LLAppearanceMgr::instance().wearItemOnAvatar(wearable_item->getUUID(), true, true);
}
}

View File

@ -112,6 +112,8 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive
{
if (!mAllFoldersFetched)
{
LL_DEBUGS("InventoryFetch") << "Start fetching category: " << cat_id << ", recursive: " << recursive << LL_ENDL;
mBackgroundFetchActive = TRUE;
if (cat_id.isNull())
{

View File

@ -68,7 +68,7 @@
// you're fetching an item and a notification gets triggered because
// you renamed some other item). This counter is to specify how many
// notification to wait for before giving up.
static const U32 MAX_NUM_NOTIFICATIONS_TO_PROCESS = 20;
static const U32 MAX_NUM_NOTIFICATIONS_TO_PROCESS = 127;
LLInventoryObserver::LLInventoryObserver()
{

View File

@ -49,6 +49,7 @@
#include "llsidepanelinventory.h"
#include "llsidetray.h"
#include "llscrollcontainer.h"
#include "llviewerattachmenu.h"
#include "llviewerfoldertype.h"
#include "llvoavatarself.h"
@ -877,48 +878,19 @@ bool LLInventoryPanel::beginIMSession()
bool LLInventoryPanel::attachObject(const LLSD& userdata)
{
// Copy selected item UUIDs to a vector.
std::set<LLUUID> selected_items = mFolderRoot->getSelectionList();
std::string joint_name = userdata.asString();
LLViewerJointAttachment* attachmentp = NULL;
for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
iter != gAgentAvatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
if (attachment->getName() == joint_name)
{
attachmentp = attachment;
break;
}
}
if (attachmentp == NULL)
{
return true;
}
uuid_vec_t items;
for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin();
set_iter != selected_items.end();
++set_iter)
{
const LLUUID &id = *set_iter;
LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id);
if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()))
{
rez_attachment(item, attachmentp);
}
else if(item && item->isFinished())
{
// must be in library. copy it to our inventory and put it on.
LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp);
copy_inventory_item(gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
LLUUID::null,
std::string(),
cb);
}
items.push_back(*set_iter);
}
// Attach selected items.
LLViewerAttachMenu::attachObjects(items, userdata.asString());
gFocusMgr.setKeyboardFocus(NULL);
return true;

View File

@ -72,7 +72,7 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
// public
void LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos,
BOOL enabled, std::string& suffix)
BOOL enabled, const std::string& suffix)
{
//llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl;
@ -268,7 +268,7 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition p
LLScrollListItem* LLNameListCtrl::addNameItemRow(
const LLNameListCtrl::NameItem& name_item,
EAddPosition pos,
std::string& suffix)
const std::string& suffix)
{
LLUUID id = name_item.value().asUUID();
LLNameListItem* item = NULL;

View File

@ -90,11 +90,11 @@ public:
// Add a user to the list by name. It will be added, the name
// requested from the cache, and updated as necessary.
void addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM,
BOOL enabled = TRUE, std::string& suffix = LLStringUtil::null);
BOOL enabled = TRUE, const std::string& suffix = LLStringUtil::null);
void addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM);
/*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, std::string& suffix = LLStringUtil::null);
LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, const std::string& suffix = LLStringUtil::null);
// Add a user to the list by name. It will be added, the name
// requested from the cache, and updated as necessary.

View File

@ -48,6 +48,7 @@
#include "lllandmarkactions.h"
#include "lllocationhistory.h"
#include "lllocationinputctrl.h"
#include "llpaneltopinfobar.h"
#include "llteleporthistory.h"
#include "llsearchcombobox.h"
#include "llsidetray.h"
@ -713,6 +714,8 @@ void LLNavigationBar::onNavigationButtonHeldUp(LLButton* nav_button)
void LLNavigationBar::handleLoginComplete()
{
LLTeleportHistory::getInstance()->handleLoginComplete();
LLPanelTopInfoBar::instance().handleLoginComplete();
mCmbLocation->handleLoginComplete();
}

View File

@ -43,12 +43,16 @@
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "lllistcontextmenu.h"
#include "llnotificationsutil.h"
#include "llsidetray.h"
#include "lltransutil.h"
#include "llviewermenu.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
#include "llwearableitemslist.h"
static bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y);
//////////////////////////////////////////////////////////////////////////
class OutfitContextMenu : public LLListContextMenu
@ -66,12 +70,63 @@ protected:
boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
registrar.add("Outfit.TakeOff",
boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id));
// *TODO: implement this
// registrar.add("Outfit.Rename", boost::bind());
// registrar.add("Outfit.Delete", boost::bind());
registrar.add("Outfit.Edit", boost::bind(editOutfit));
registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
registrar.add("Outfit.Delete", boost::bind(deleteOutfit, selected_id));
enable_registrar.add("Outfit.OnEnable", boost::bind(&OutfitContextMenu::onEnable, this, _2));
return createFromFile("menu_outfit_tab.xml");
}
bool onEnable(const LLSD& data)
{
std::string param = data.asString();
LLUUID outfit_cat_id = mUUIDs.back();
bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id;
if ("wear_replace" == param)
{
return !is_worn;
}
else if ("wear_add" == param)
{
return !is_worn;
}
else if ("take_off" == param)
{
return is_worn;
}
else if ("edit" == param)
{
return is_worn;
}
else if ("rename" == param)
{
return get_is_category_renameable(&gInventory, outfit_cat_id);
}
else if ("delete" == param)
{
return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id);
}
return true;
}
static void editOutfit()
{
LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit"));
}
static void renameOutfit(const LLUUID& outfit_cat_id)
{
LLAppearanceMgr::instance().renameOutfit(outfit_cat_id);
}
static void deleteOutfit(const LLUUID& outfit_cat_id)
{
remove_category(&gInventory, outfit_cat_id);
}
};
//////////////////////////////////////////////////////////////////////////
@ -82,11 +137,9 @@ LLOutfitsList::LLOutfitsList()
: LLPanel()
, mAccordion(NULL)
, mListCommands(NULL)
, mIsInitialized(false)
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
gInventory.addObserver(mCategoriesObserver);
gInventory.addObserver(this);
mOutfitMenu = new OutfitContextMenu();
}
@ -100,11 +153,6 @@ LLOutfitsList::~LLOutfitsList()
gInventory.removeObserver(mCategoriesObserver);
delete mCategoriesObserver;
}
if (gInventory.containsObserver(this))
{
gInventory.removeObserver(this);
}
}
BOOL LLOutfitsList::postBuild()
@ -115,32 +163,36 @@ BOOL LLOutfitsList::postBuild()
}
//virtual
void LLOutfitsList::changed(U32 mask)
void LLOutfitsList::onOpen(const LLSD& /*info*/)
{
if (!gInventory.isInventoryUsable())
return;
if (!mIsInitialized)
{
// *TODO: I'm not sure is this check necessary but it never match while developing.
if (!gInventory.isInventoryUsable())
return;
const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
LLViewerInventoryCategory* category = gInventory.getCategory(outfits);
if (!category)
return;
const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
// Start observing changes in "My Outfits" category.
mCategoriesObserver->addCategory(outfits,
// *TODO: I'm not sure is this check necessary but it never match while developing.
LLViewerInventoryCategory* category = gInventory.getCategory(outfits);
if (!category)
return;
gInventory.addObserver(mCategoriesObserver);
// Start observing changes in "My Outfits" category.
mCategoriesObserver->addCategory(outfits,
boost::bind(&LLOutfitsList::refreshList, this, outfits));
// Fetch "My Outfits" contents and refresh the list to display
// initially fetched items. If not all items are fetched now
// the observer will refresh the list as soon as the new items
// arrive.
category->fetch();
refreshList(outfits);
// Fetch "My Outfits" contents and refresh the list to display
// initially fetched items. If not all items are fetched now
// the observer will refresh the list as soon as the new items
// arrive.
category->fetch();
refreshList(outfits);
// This observer is used to start the initial outfits fetch
// when inventory becomes usable. It is no longer needed because
// "My Outfits" category is now observed by
// LLInventoryCategoriesObserver.
gInventory.removeObserver(this);
mIsInitialized = true;
}
}
void LLOutfitsList::refreshList(const LLUUID& category_id)
@ -176,8 +228,6 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
static LLXMLNodePtr accordionXmlNode = getAccordionTabXMLNode();
LLAccordionCtrlTab* tab = LLUICtrlFactory::defaultBuilder<LLAccordionCtrlTab>(accordionXmlNode, NULL, NULL);
tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this,
_1, _2, _3, cat_id));
tab->setName(name);
tab->setTitle(name);
@ -198,6 +248,12 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
// Map the new tab with outfit category UUID.
mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab));
tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this,
_1, _2, _3, cat_id));
tab->setDoubleClickCallback(boost::bind(&LLOutfitsList::onAccordionTabDoubleClick, this,
_1, _2, _3, cat_id));
// Setting tab focus callback to monitor currently selected outfit.
tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id));
@ -301,6 +357,10 @@ void LLOutfitsList::performAction(std::string action)
{
LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, TRUE );
}
else if ("rename_outfit" == action)
{
LLAppearanceMgr::instance().renameOutfit(mSelectedOutfitUUID);
}
}
void LLOutfitsList::setFilterSubString(const std::string& string)
@ -426,6 +486,10 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)
// hide tab if its title doesn't pass filter
// and it has no visible items
tab->setVisible(list->size() != 0);
// remove title highlighting because it might
// have been previously highlighted by less restrictive filter
tab->setTitle(tab->getTitle());
}
else
{
@ -478,6 +542,10 @@ void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
// hide tab if its title doesn't pass filter
// and it has no visible items
tab->setVisible(list->size() != 0);
// remove title highlighting because it might
// have been previously highlighted by less restrictive filter
tab->setTitle(tab->getTitle());
}
else
{
@ -510,22 +578,30 @@ void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
{
LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);
if(mOutfitMenu && tab && tab->getHeaderVisible() && cat_id.notNull())
if(mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull())
{
S32 header_bottom = tab->getLocalRect().getHeight() - tab->getHeaderHeight();
if(y >= header_bottom)
// Focus tab header to trigger tab selection change.
LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header");
if (header)
{
// Focus tab header to trigger tab selection change.
LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header");
if (header)
{
header->setFocus(TRUE);
}
uuid_vec_t selected_uuids;
selected_uuids.push_back(cat_id);
mOutfitMenu->show(ctrl, selected_uuids, x, y);
header->setFocus(TRUE);
}
uuid_vec_t selected_uuids;
selected_uuids.push_back(cat_id);
mOutfitMenu->show(ctrl, selected_uuids, x, y);
}
}
void LLOutfitsList::onAccordionTabDoubleClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
{
LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);
if(is_tab_header_clicked(tab, y) && cat_id.notNull())
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (!cat) return;
LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, FALSE );
}
}
@ -551,4 +627,13 @@ void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
LLWearableItemsList::ContextMenu::instance().show(list, selected_uuids, x, y);
}
bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)
{
if(!tab || !tab->getHeaderVisible()) return false;
S32 header_bottom = tab->getLocalRect().getHeight() - tab->getHeaderHeight();
return y >= header_bottom;
}
// EOF

View File

@ -49,12 +49,10 @@ class LLListContextMenu;
* A list of agents's outfits from "My Outfits" inventory category
* which displays each outfit in an accordion tab with a flat list
* of items inside it.
* Uses LLInventoryCategoriesObserver to monitor changes to "My Outfits"
* inventory category and refresh the outfits listed in it.
* This class is derived from LLInventoryObserver to know when inventory
* becomes usable and it is safe to request data from inventory model.
*
* Starts fetching nevessary inventory content on first openning.
*/
class LLOutfitsList : public LLPanel, public LLInventoryObserver
class LLOutfitsList : public LLPanel
{
public:
LLOutfitsList();
@ -62,16 +60,16 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void changed(U32 mask);
/*virtual*/ void onOpen(const LLSD& info);
void refreshList(const LLUUID& category_id);
void onSelectionChange(LLUICtrl* ctrl);
void performAction(std::string action);
void setFilterSubString(const std::string& string);
const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
private:
/**
* Reads xml with accordion tab and Flat list from xml file.
@ -107,9 +105,13 @@ private:
void applyFilter(const std::string& new_filter_substring);
void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
void onAccordionTabDoubleClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
void onSelectionChange(LLUICtrl* ctrl);
static void onOutfitRename(const LLSD& notification, const LLSD& response);
LLInventoryCategoriesObserver* mCategoriesObserver;
LLAccordionCtrl* mAccordion;
@ -128,6 +130,8 @@ private:
outfits_map_t mOutfitsMap;
LLListContextMenu* mOutfitMenu;
bool mIsInitialized;
};
#endif //LL_LLOUTFITSLIST_H

View File

@ -51,6 +51,7 @@
#include "llagentwearables.h"
#include "llscrollingpanelparam.h"
#include "llradiogroup.h"
#include "llnotificationsutil.h"
#include "llcolorswatch.h"
#include "lltexturectrl.h"
@ -520,7 +521,8 @@ static void init_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, co
LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild<LLColorSwatchCtrl>(entry->mControlName);
if (color_swatch_ctrl)
{
color_swatch_ctrl->setOriginal(self->getWearable()->getClothesColor(entry->mTextureIndex));
// Can't get the color from the wearable here, since the wearable may not be set when this is called.
color_swatch_ctrl->setOriginal(LLColor4::white);
}
}
@ -623,6 +625,7 @@ BOOL LLPanelEditWearable::postBuild()
mDescTitle = getChild<LLTextBox>("description_text");
getChild<LLRadioGroup>("sex_radio")->setCommitCallback(boost::bind(&LLPanelEditWearable::onCommitSexChange, this));
getChild<LLButton>("save_as_button")->setCommitCallback(boost::bind(&LLPanelEditWearable::onSaveAsButtonClicked, this));
// The following panels will be shown/hidden based on what wearable we're editing
// body parts
@ -654,6 +657,49 @@ BOOL LLPanelEditWearable::postBuild()
configureAlphaCheckbox(LLVOAvatarDefines::TEX_EYES_ALPHA, "eye alpha texture invisible");
configureAlphaCheckbox(LLVOAvatarDefines::TEX_HAIR_ALPHA, "hair alpha texture invisible");
// configure tab expanded callbacks
for (U32 type_index = 0; type_index < (U32)LLWearableType::WT_COUNT; ++type_index)
{
LLWearableType::EType type = (LLWearableType::EType) type_index;
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
if (!wearable_entry)
{
llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl;
continue;
}
U8 num_subparts = wearable_entry->mSubparts.size();
for (U8 index = 0; index < num_subparts; ++index)
{
// dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
if (!subpart_entry)
{
llwarns << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << llendl;
continue;
}
const std::string accordion_tab = subpart_entry->mAccordionTab;
LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
if (!tab)
{
llwarns << "could not get llaccordionctrltab from UI with name: " << accordion_tab << llendl;
continue;
}
// initialize callback to ensure camera view changes appropriately.
tab->setDropDownStateChangedCallback(boost::bind(&LLPanelEditWearable::onTabExpandedCollapsed,this,_2,index));
}
// initialize texture and color picker controls
for_each_picker_ctrl_entry <LLColorSwatchCtrl> (getPanel(type), type, boost::bind(init_color_swatch_ctrl, this, _1, _2));
for_each_picker_ctrl_entry <LLTextureCtrl> (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2));
}
return TRUE;
}
@ -690,10 +736,9 @@ void LLPanelEditWearable::setWearable(LLWearable *wearable)
showWearable(mWearablePtr, FALSE);
mWearablePtr = wearable;
showWearable(mWearablePtr, TRUE);
initializePanel();
}
//static
void LLPanelEditWearable::onRevertButtonClicked(void* userdata)
{
@ -701,6 +746,28 @@ void LLPanelEditWearable::onRevertButtonClicked(void* userdata)
panel->revertChanges();
}
void LLPanelEditWearable::onSaveAsButtonClicked()
{
LLSD args;
args["DESC"] = mTextEditor->getText();
LLNotificationsUtil::add("SaveWearableAs", args, LLSD(), boost::bind(&LLPanelEditWearable::saveAsCallback, this, _1, _2));
}
void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
std::string wearable_name = response["message"].asString();
LLStringUtil::trim(wearable_name);
if( !wearable_name.empty() )
{
mTextEditor->setText(wearable_name);
saveChanges();
}
}
}
void LLPanelEditWearable::onCommitSexChange()
{
@ -880,29 +947,89 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
std::string title;
std::string description_title;
const LLEditWearableDictionary::WearableEntry *entry = LLEditWearableDictionary::getInstance()->getWearable(type);
if (!entry)
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
if (!wearable_entry)
{
llwarns << "called LLPanelEditWearable::showWearable with an invalid wearable type! (" << type << ")" << llendl;
return;
}
targetPanel = getPanel(type);
title = getString(entry->mTitle);
description_title = getString(entry->mDescTitle);
targetPanel->setVisible(show);
if (show)
{
mPanelTitle->setText(title);
mDescTitle->setText(description_title);
}
title = getString(wearable_entry->mTitle);
description_title = getString(wearable_entry->mDescTitle);
// Update picker controls state
for_each_picker_ctrl_entry <LLColorSwatchCtrl> (targetPanel, type, boost::bind(set_enabled_color_swatch_ctrl, show, _1, _2));
for_each_picker_ctrl_entry <LLTextureCtrl> (targetPanel, type, boost::bind(set_enabled_texture_ctrl, show, _1, _2));
showDefaultSubpart();
targetPanel->setVisible(show);
toggleTypeSpecificControls(type);
if (show)
{
mPanelTitle->setText(title);
mDescTitle->setText(description_title);
// set name
mTextEditor->setText(wearable->getName());
updatePanelPickerControls(type);
updateTypeSpecificControls(type);
// clear and rebuild visual param list
U8 num_subparts = wearable_entry->mSubparts.size();
for (U8 index = 0; index < num_subparts; ++index)
{
// dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
if (!subpart_entry)
{
llwarns << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << llendl;
continue;
}
const std::string scrolling_panel = subpart_entry->mParamList;
const std::string accordion_tab = subpart_entry->mAccordionTab;
LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
if (!panel_list)
{
llwarns << "could not get scrolling panel list: " << scrolling_panel << llendl;
continue;
}
if (!tab)
{
llwarns << "could not get llaccordionctrltab from UI with name: " << accordion_tab << llendl;
continue;
}
// what edit group do we want to extract params for?
const std::string edit_group = subpart_entry->mEditGroup;
// storage for ordered list of visual params
value_map_t sorted_params;
getSortedParams(sorted_params, edit_group);
LLJoint* jointp = gAgentAvatarp->getJoint( subpart_entry->mTargetJoint );
if (!jointp)
{
jointp = gAgentAvatarp->getJoint("mHead");
}
buildParamList(panel_list, sorted_params, tab, jointp);
updateScrollingPanelUI();
}
showDefaultSubpart();
updateVerbs();
}
}
void LLPanelEditWearable::showDefaultSubpart()
@ -967,91 +1094,6 @@ void LLPanelEditWearable::updateScrollingPanelList()
updateScrollingPanelUI();
}
void LLPanelEditWearable::initializePanel()
{
if (!mWearablePtr)
{
// cannot initialize with a null reference.
return;
}
LLWearableType::EType type = mWearablePtr->getType();
// set name
mTextEditor->setText(mWearablePtr->getName());
// toggle wearable type-specific controls
toggleTypeSpecificControls(type);
// clear and rebuild visual param list
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
if (!wearable_entry)
{
llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl;
return;
}
U8 num_subparts = wearable_entry->mSubparts.size();
for (U8 index = 0; index < num_subparts; ++index)
{
// dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
if (!subpart_entry)
{
llwarns << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << llendl;
continue;
}
const std::string scrolling_panel = subpart_entry->mParamList;
const std::string accordion_tab = subpart_entry->mAccordionTab;
LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
if (!panel_list)
{
llwarns << "could not get scrolling panel list: " << scrolling_panel << llendl;
continue;
}
if (!tab)
{
llwarns << "could not get llaccordionctrltab from UI with name: " << accordion_tab << llendl;
continue;
}
// what edit group do we want to extract params for?
const std::string edit_group = subpart_entry->mEditGroup;
// initialize callback to ensure camera view changes appropriately.
tab->setDropDownStateChangedCallback(boost::bind(&LLPanelEditWearable::onTabExpandedCollapsed,this,_2,index));
// storage for ordered list of visual params
value_map_t sorted_params;
getSortedParams(sorted_params, edit_group);
buildParamList(panel_list, sorted_params, tab);
updateScrollingPanelUI();
}
// initialize texture and color picker controls
for_each_picker_ctrl_entry <LLColorSwatchCtrl> (getPanel(type), type, boost::bind(init_color_swatch_ctrl, this, _1, _2));
for_each_picker_ctrl_entry <LLTextureCtrl> (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2));
showDefaultSubpart();
updateVerbs();
if (getWearable())
{
LLWearableType::EType type = getWearable()->getType();
updatePanelPickerControls(type);
updateTypeSpecificControls(type);
}
}
void LLPanelEditWearable::toggleTypeSpecificControls(LLWearableType::EType type)
{
// Toggle controls specific to shape editing panel.
@ -1217,7 +1259,7 @@ void LLPanelEditWearable::getSortedParams(value_map_t &sorted_params, const std:
}
}
void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab)
void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab, LLJoint* jointp)
{
// sorted_params is sorted according to magnitude of effect from
// least to greatest. Adding to the front of the child list
@ -1231,7 +1273,7 @@ void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value
{
LLPanel::Params p;
p.name("LLScrollingPanelParam");
LLScrollingPanelParam* panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable());
LLScrollingPanelParam* panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable(), jointp);
height = panel_list->addPanel( panel_param );
}
}

View File

@ -48,6 +48,7 @@ class LLViewerVisualParam;
class LLVisualParamHint;
class LLViewerJointMesh;
class LLAccordionCtrlTab;
class LLJoint;
class LLPanelEditWearable : public LLPanel
{
@ -72,17 +73,18 @@ public:
static void onRevertButtonClicked(void* userdata);
void onCommitSexChange();
void onSaveAsButtonClicked();
void saveAsCallback(const LLSD& notification, const LLSD& response);
private:
typedef std::map<F32, LLViewerVisualParam*> value_map_t;
void showWearable(LLWearable* wearable, BOOL show);
void initializePanel();
void updateScrollingPanelUI();
LLPanel* getPanel(LLWearableType::EType type);
void getSortedParams(value_map_t &sorted_params, const std::string &edit_group);
void buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab);
void buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab, LLJoint* jointp);
// update bottom bar buttons ("Save", "Revert", etc)
void updateVerbs();

View File

@ -221,8 +221,6 @@ BOOL LLLandmarksPanel::postBuild()
// mast be called before any other initXXX methods to init Gear menu
initListCommandsHandlers();
U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER);
mSortByDate = sort_order & LLInventoryFilter::SO_DATE;
initFavoritesInventoryPanel();
initLandmarksInventoryPanel();
initMyInventoryPanel();
@ -607,7 +605,8 @@ void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list
inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2));
inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
updateSortOrder(inventory_list, mSortByDate);
bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate");
updateSortOrder(inventory_list, sorting_order);
LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder());
if (root_folder)
@ -875,10 +874,12 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
}
else if ("sort_by_date" == command_name)
{
mSortByDate = !mSortByDate;
updateSortOrder(mLandmarksInventoryPanel, mSortByDate);
updateSortOrder(mMyInventoryPanel, mSortByDate);
updateSortOrder(mLibraryInventoryPanel, mSortByDate);
bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate");
sorting_order=!sorting_order;
gSavedSettings.setBOOL("LandmarksSortedByDate",sorting_order);
updateSortOrder(mLandmarksInventoryPanel, sorting_order);
updateSortOrder(mMyInventoryPanel, sorting_order);
updateSortOrder(mLibraryInventoryPanel, sorting_order);
}
else
{
@ -895,7 +896,8 @@ bool LLLandmarksPanel::isActionChecked(const LLSD& userdata) const
if ( "sort_by_date" == command_name)
{
return mSortByDate;
bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate");
return sorting_order;
}
return false;

View File

@ -167,7 +167,6 @@ private:
LLInventoryObserver* mInventoryObserver;
LLPanel* mListCommands;
bool mSortByDate;
typedef std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
accordion_tabs_t mAccordionTabs;

View File

@ -215,7 +215,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
// change z sort of clickable text to be behind buttons
sendChildToBack(getChildView("channel_text"));
//sendChildToBack(getChildView("channel_text"));
sendChildToBack(getChildView("forgot_password_text"));
LLLineEditor* edit = getChild<LLLineEditor>("password_edit");
@ -241,10 +241,10 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
std::string version = llformat("%s (%d)",
LLVersionInfo::getShortVersion().c_str(),
LLVersionInfo::getBuild());
LLTextBox* channel_text = getChild<LLTextBox>("channel_text");
channel_text->setTextArg("[CHANNEL]", channel); // though not displayed
channel_text->setTextArg("[VERSION]", version);
channel_text->setClickedCallback(onClickVersion, this);
//LLTextBox* channel_text = getChild<LLTextBox>("channel_text");
//channel_text->setTextArg("[CHANNEL]", channel); // though not displayed
//channel_text->setTextArg("[VERSION]", version);
//channel_text->setClickedCallback(onClickVersion, this);
LLTextBox* forgot_password_text = getChild<LLTextBox>("forgot_password_text");
forgot_password_text->setClickedCallback(onClickForgotPassword, NULL);

View File

@ -79,6 +79,70 @@ const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;
static const std::string REVERT_BTN("revert_btn");
class LLPanelOutfitEditGearMenu
{
public:
static LLMenuGL* create()
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("Wearable.Create", boost::bind(onCreate, _2));
LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
"menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(menu);
if (menu)
{
populateCreateWearableSubmenus(menu);
menu->buildDrawLabels();
}
return menu;
}
private:
static void onCreate(const LLSD& param)
{
LLWearableType::EType type = LLWearableType::typeNameToType(param.asString());
if (type == LLWearableType::WT_NONE)
{
llwarns << "Invalid wearable type" << llendl;
return;
}
LLAgentWearables::createWearable(type, true);
}
// Populate the menu with items like "New Skin", "New Pants", etc.
static void populateCreateWearableSubmenus(LLMenuGL* menu)
{
LLView* menu_clothes = gMenuHolder->findChildView("COF.Gear.New_Clothes", FALSE);
LLView* menu_bp = gMenuHolder->findChildView("COF.Geear.New_Body_Parts", FALSE);
if (!menu_clothes || !menu_bp)
{
llassert(menu_clothes && menu_bp);
return;
}
for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i)
{
LLWearableType::EType type = (LLWearableType::EType) i;
const std::string& type_name = LLWearableType::getTypeName(type);
LLMenuItemCallGL::Params p;
p.name = type_name;
p.label = LLWearableType::getTypeDefaultNewName(type);
p.on_click.function_name = "Wearable.Create";
p.on_click.parameter = LLSD(type_name);
LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ?
menu_clothes : menu_bp;
LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
}
}
};
class LLCOFObserver : public LLInventoryObserver
{
public:
@ -259,7 +323,6 @@ BOOL LLPanelOutfitEdit::postBuild()
mFolderViewBtn = getChild<LLButton>("folder_view_btn");
mListViewBtn = getChild<LLButton>("list_view_btn");
mAddToOutfitBtn = getChild<LLButton>("add_to_outfit_btn");
childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL);
childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredFolderWearablesPanel, this), NULL);
@ -275,8 +338,6 @@ BOOL LLPanelOutfitEdit::postBuild()
mCOFWearables->getCOFCallbacks().mMoveWearableCloser = boost::bind(&LLPanelOutfitEdit::moveWearable, this, true);
mCOFWearables->getCOFCallbacks().mMoveWearableFurther = boost::bind(&LLPanelOutfitEdit::moveWearable, this, false);
mCOFWearables->childSetAction("add_btn", boost::bind(&LLPanelOutfitEdit::toggleAddWearablesPanel, this));
mAddWearablesPanel = getChild<LLPanel>("add_wearables_panel");
mInventoryItemsPanel = getChild<LLInventoryPanel>("inventory_items");
@ -298,7 +359,8 @@ BOOL LLPanelOutfitEdit::postBuild()
mSearchFilter = getChild<LLFilterEditor>("look_item_filter");
mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2));
childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::toggleAddWearablesPanel, this));
childSetAction("add_to_outfit_btn", boost::bind(&LLPanelOutfitEdit::onAddToOutfitClicked, this));
mEditWearableBtn = getChild<LLButton>("edit_wearable_btn");
@ -313,7 +375,6 @@ BOOL LLPanelOutfitEdit::postBuild()
mWearableItemsPanel = getChild<LLPanel>("filtered_wearables_panel");
mWearableItemsList = getChild<LLInventoryItemsList>("filtered_wearables_list");
mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mWearableListMaskCollector);
mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this));
return TRUE;
@ -324,6 +385,10 @@ void LLPanelOutfitEdit::onOpen(const LLSD& key)
{
if (!mInitialized)
{
// *TODO: this method is called even panel is not visible to user because its parent layout panel is hidden.
// So, we can defer initializing a bit.
mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mWearableListMaskCollector);
mWearableListManager->populateList();
displayCurrentOutfit();
mInitialized = true;
}
@ -341,15 +406,28 @@ void LLPanelOutfitEdit::moveWearable(bool closer_to_body)
void LLPanelOutfitEdit::toggleAddWearablesPanel()
{
BOOL current_visibility = mAddWearablesPanel->getVisible();
mAddWearablesPanel->setVisible(!current_visibility);
showAddWearablesPanel(!current_visibility);
}
mFolderViewBtn->setVisible(!current_visibility);
mListViewBtn->setVisible(!current_visibility);
mAddToOutfitBtn->setVisible(!current_visibility);
void LLPanelOutfitEdit::showAddWearablesPanel(bool show_add_wearables)
{
mAddWearablesPanel->setVisible(show_add_wearables);
childSetValue("show_add_wearables_btn", show_add_wearables);
// Change right dummy icon to fill the toggled buttons space.
childSetVisible("add_wearables_dummy_icon", !current_visibility);
childSetVisible("dummy_right_icon", current_visibility);
childSetVisible("filter_wearables_combobox", show_add_wearables);
childSetVisible("filter_button", show_add_wearables);
//search filter should be disabled
if (!show_add_wearables)
{
childSetValue("filter_button", false);
showWearablesFilter();
}
//switching button bars
childSetVisible("no_add_wearables_button_bar", !show_add_wearables);
childSetVisible("add_wearables_button_bar", show_add_wearables);
}
void LLPanelOutfitEdit::showWearablesFilter()
@ -708,34 +786,18 @@ void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)
{
if(!mGearMenu)
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("Gear.OnClick", boost::bind(&LLPanelOutfitEdit::onGearMenuItemClick, this, _2));
mGearMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
"menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
mGearMenu->buildDrawLabels();
mGearMenu->updateParent(LLMenuGL::sMenuContainer);
mGearMenu = LLPanelOutfitEditGearMenu::create();
}
S32 menu_y = mGearMenu->getRect().getHeight() + clicked_button->getRect().getHeight();
LLMenuGL::showPopup(clicked_button, mGearMenu, 0, menu_y);
}
void LLPanelOutfitEdit::onGearMenuItemClick(const LLSD& data)
{
std::string param = data.asString();
if("add" == param)
{
// TODO
}
}
void LLPanelOutfitEdit::showFilteredWearableItemsList(LLWearableType::EType type)
{
mWearableListTypeCollector->setType(type);
mWearableListManager->setFilterCollector(mWearableListTypeCollector);
mAddWearablesPanel->setVisible(TRUE);
showAddWearablesPanel(true);
showFilteredWearablesPanel();
}

View File

@ -93,6 +93,7 @@ public:
void moveWearable(bool closer_to_body);
void toggleAddWearablesPanel();
void showAddWearablesPanel(bool show__add_wearables);
void showWearablesFilter();
void showFilteredWearablesPanel();
void showFilteredFolderWearablesPanel();
@ -131,7 +132,6 @@ public:
private:
void onGearButtonClick(LLUICtrl* clicked_button);
void onGearMenuItemClick(const LLSD& data);
void showFilteredWearableItemsList(LLWearableType::EType type);
@ -144,7 +144,6 @@ private:
LLButton* mEditWearableBtn;
LLButton* mFolderViewBtn;
LLButton* mListViewBtn;
LLButton* mAddToOutfitBtn;
LLPanel* mAddWearablesPanel;
LLFindNonLinksByMask* mWearableListMaskCollector;

View File

@ -42,6 +42,7 @@
#include "llfloaterworldmap.h"
#include "llfloaterinventory.h"
#include "llfoldervieweventlistener.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventorypanel.h"
@ -70,11 +71,134 @@ static const std::string COF_TAB_NAME = "cof_tab";
static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
class LLOutfitListGearMenu
{
public:
LLOutfitListGearMenu(LLOutfitsList* olist)
: mOutfitList(olist),
mMenu(NULL)
{
llassert_always(mOutfitList);
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this));
registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this));
registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this));
registrar.add("Gear.Delete", boost::bind(&LLOutfitListGearMenu::onDelete, this));
registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2));
enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2));
mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
"menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(mMenu);
}
LLMenuGL* getMenu() { return mMenu; }
private:
const LLUUID& getSelectedOutfitID()
{
return mOutfitList->getSelectedOutfitUUID();
}
LLViewerInventoryCategory* getSelectedOutfit()
{
const LLUUID& selected_outfit_id = getSelectedOutfitID();
if (selected_outfit_id.isNull())
{
return NULL;
}
LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
return cat;
}
void onWear()
{
LLViewerInventoryCategory* selected_outfit = getSelectedOutfit();
if (selected_outfit)
{
LLAppearanceMgr::instance().wearInventoryCategory(
selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE);
}
}
void onTakeOff()
{
const LLUUID& selected_outfit_id = getSelectedOutfitID();
if (selected_outfit_id.notNull())
{
LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id);
}
}
void onRename()
{
const LLUUID& selected_outfit_id = getSelectedOutfitID();
if (selected_outfit_id.notNull())
{
LLAppearanceMgr::instance().renameOutfit(selected_outfit_id);
}
}
void onDelete()
{
const LLUUID& selected_outfit_id = getSelectedOutfitID();
if (selected_outfit_id.notNull())
{
remove_category(&gInventory, selected_outfit_id);
}
}
void onCreate(const LLSD& data)
{
LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
if (type == LLWearableType::WT_NONE)
{
llwarns << "Invalid wearable type" << llendl;
return;
}
LLAgentWearables::createWearable(type, true);
}
bool onEnable(LLSD::String param)
{
const LLUUID& selected_outfit_id = getSelectedOutfitID();
bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id;
if ("wear" == param)
{
return !is_worn;
}
else if ("take_off" == param)
{
return is_worn;
}
else if ("rename" == param)
{
return get_is_category_renameable(&gInventory, selected_outfit_id);
}
else if ("delete" == param)
{
return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id);
}
return true;
}
LLOutfitsList* mOutfitList;
LLMenuGL* mMenu;
};
LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
mMyOutfitsPanel(NULL),
mCurrentOutfitPanel(NULL),
mParent(NULL),
mGearMenu(NULL),
mInitialized(false)
{
mSavedFolderState = new LLSaveFolderState();
@ -84,6 +208,7 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
{
delete mGearMenu;
delete mSavedFolderState;
}
@ -374,7 +499,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()
{
mListCommands = getChild<LLPanel>("bottom_panel");
mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this));
mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::showGearMenu, this));
mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
@ -385,8 +510,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()
, _7 // EAcceptance* accept
));
mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_outfit_gear.xml",
gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGearMenu = new LLOutfitListGearMenu(mMyOutfitsPanel);
}
void LLPanelOutfitsInventory::updateListCommands()
@ -401,18 +525,14 @@ void LLPanelOutfitsInventory::updateListCommands()
mSaveComboBtn->setSaveBtnEnabled(make_outfit_enabled);
}
void LLPanelOutfitsInventory::onGearButtonClick()
{
showActionMenu(mMenuGearDefault,"options_gear_btn");
}
void LLPanelOutfitsInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
void LLPanelOutfitsInventory::showGearMenu()
{
LLMenuGL* menu = mGearMenu ? mGearMenu->getMenu() : NULL;
if (menu)
{
menu->buildDrawLabels();
menu->updateParent(LLMenuGL::sMenuContainer);
LLView* spawning_view = getChild<LLView> (spawning_view_name);
LLView* spawning_view = getChild<LLView>("options_gear_btn");
S32 menu_x, menu_y;
//show menu in co-ordinates of panel
spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
@ -632,6 +752,7 @@ void LLPanelOutfitsInventory::onTabChange()
else
{
mMyOutfitsPanel->setFilterSubString(mFilterSubString);
mMyOutfitsPanel->onOpen(LLSD());
}
updateVerbs();

View File

@ -47,6 +47,7 @@ class LLMenuGL;
class LLSidepanelAppearance;
class LLTabContainer;
class LLSaveOutfitComboBtn;
class LLOutfitListGearMenu;
class LLPanelOutfitsInventory : public LLPanel
{
@ -116,9 +117,8 @@ private:
protected:
void initListCommandsHandlers();
void updateListCommands();
void onGearButtonClick();
void onWearButtonClick();
void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
void showGearMenu();
void onTrashButtonClick();
void onClipboardAction(const LLSD& userdata);
BOOL isActionEnabled(const LLSD& command_name);
@ -129,7 +129,7 @@ protected:
void onWearablesLoaded();
private:
LLPanel* mListCommands;
LLMenuGL* mMenuGearDefault;
LLOutfitListGearMenu* mGearMenu;
LLMenuGL* mMenuAdd;
// List Commands //
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,393 @@
/**
* @file llpaneltopinfobar.cpp
* @brief Coordinates and Parcel Settings information panel definition
*
* $LicenseInfo:firstyear=2010&license=viewergpl$
*
* Copyright (c) 2010, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llpaneltopinfobar.h"
#include "llagent.h"
#include "llagentui.h"
#include "lllocationinputctrl.h"
#include "llnotificationsutil.h"
#include "llparcel.h"
#include "llsidetray.h"
#include "llstatusbar.h"
#include "llviewercontrol.h"
#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
class LLPanelTopInfoBar::LLParcelChangeObserver : public LLParcelObserver
{
public:
LLParcelChangeObserver(LLPanelTopInfoBar* topInfoBar) : mTopInfoBar(topInfoBar) {}
private:
/*virtual*/ void changed()
{
if (mTopInfoBar)
{
mTopInfoBar->updateParcelIcons();
}
}
LLPanelTopInfoBar* mTopInfoBar;
};
LLPanelTopInfoBar::LLPanelTopInfoBar(): mParcelChangedObserver(0)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_topinfo_bar.xml");
}
LLPanelTopInfoBar::~LLPanelTopInfoBar()
{
if (mParcelChangedObserver)
{
LLViewerParcelMgr::getInstance()->removeObserver(mParcelChangedObserver);
delete mParcelChangedObserver;
}
if (mParcelPropsCtrlConnection.connected())
{
mParcelPropsCtrlConnection.disconnect();
}
if (mParcelMgrConnection.connected())
{
mParcelMgrConnection.disconnect();
}
if (mShowCoordsCtrlConnection.connected())
{
mShowCoordsCtrlConnection.disconnect();
}
}
void LLPanelTopInfoBar::initParcelIcons()
{
mParcelIcon[VOICE_ICON] = getChild<LLIconCtrl>("voice_icon");
mParcelIcon[FLY_ICON] = getChild<LLIconCtrl>("fly_icon");
mParcelIcon[PUSH_ICON] = getChild<LLIconCtrl>("push_icon");
mParcelIcon[BUILD_ICON] = getChild<LLIconCtrl>("build_icon");
mParcelIcon[SCRIPTS_ICON] = getChild<LLIconCtrl>("scripts_icon");
mParcelIcon[DAMAGE_ICON] = getChild<LLIconCtrl>("damage_icon");
mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, VOICE_ICON));
mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, FLY_ICON));
mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, PUSH_ICON));
mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, BUILD_ICON));
mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, SCRIPTS_ICON));
mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, DAMAGE_ICON));
mDamageText->setText(LLStringExplicit("100%"));
}
void LLPanelTopInfoBar::handleLoginComplete()
{
// An agent parcel update hasn't occurred yet, so
// we have to manually set location and the icons.
update();
}
BOOL LLPanelTopInfoBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
show_navbar_context_menu(this, x, y);
return TRUE;
}
BOOL LLPanelTopInfoBar::postBuild()
{
mInfoBtn = getChild<LLButton>("place_info_btn");
mInfoBtn->setClickedCallback(boost::bind(&LLPanelTopInfoBar::onInfoButtonClicked, this));
mParcelInfoText = getChild<LLTextBox>("parcel_info_text");
mDamageText = getChild<LLTextBox>("damage_text");
initParcelIcons();
mParcelChangedObserver = new LLParcelChangeObserver(this);
LLViewerParcelMgr::getInstance()->addObserver(mParcelChangedObserver);
// Connecting signal for updating parcel icons on "Show Parcel Properties" setting change.
LLControlVariable* ctrl = gSavedSettings.getControl("NavBarShowParcelProperties").get();
if (ctrl)
{
mParcelPropsCtrlConnection = ctrl->getSignal()->connect(boost::bind(&LLPanelTopInfoBar::updateParcelIcons, this));
}
// Connecting signal for updating parcel text on "Show Coordinates" setting change.
ctrl = gSavedSettings.getControl("NavBarShowCoordinates").get();
if (ctrl)
{
mShowCoordsCtrlConnection = ctrl->getSignal()->connect(boost::bind(&LLPanelTopInfoBar::onNavBarShowParcelPropertiesCtrlChanged, this));
}
mParcelMgrConnection = LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
boost::bind(&LLPanelTopInfoBar::onAgentParcelChange, this));
return TRUE;
}
void LLPanelTopInfoBar::onNavBarShowParcelPropertiesCtrlChanged()
{
std::string new_text;
// don't need to have separate show_coords variable; if user requested the coords to be shown
// they will be added during the next call to the draw() method.
buildLocationString(new_text, false);
setParcelInfoText(new_text);
}
void LLPanelTopInfoBar::draw()
{
updateParcelInfoText();
updateHealth();
LLPanel::draw();
}
void LLPanelTopInfoBar::buildLocationString(std::string& loc_str, bool show_coords)
{
LLAgentUI::ELocationFormat format =
(show_coords ? LLAgentUI::LOCATION_FORMAT_FULL : LLAgentUI::LOCATION_FORMAT_NO_COORDS);
if (!LLAgentUI::buildLocationString(loc_str, format))
{
loc_str = "???";
}
}
void LLPanelTopInfoBar::setParcelInfoText(const std::string& new_text)
{
const LLFontGL* font = mParcelInfoText->getDefaultFont();
S32 new_text_width = font->getWidth(new_text);
mParcelInfoText->setText(new_text);
LLRect rect = mParcelInfoText->getRect();
rect.setOriginAndSize(rect.mLeft, rect.mBottom, new_text_width, rect.getHeight());
mParcelInfoText->reshape(rect.getWidth(), rect.getHeight(), TRUE);
mParcelInfoText->setRect(rect);
layoutParcelIcons();
}
void LLPanelTopInfoBar::update()
{
std::string new_text;
// don't need to have separate show_coords variable; if user requested the coords to be shown
// they will be added during the next call to the draw() method.
buildLocationString(new_text, false);
setParcelInfoText(new_text);
updateParcelIcons();
}
void LLPanelTopInfoBar::updateParcelInfoText()
{
static LLUICachedControl<bool> show_coords("NavBarShowCoordinates", false);
if (show_coords)
{
std::string new_text;
buildLocationString(new_text, show_coords);
setParcelInfoText(new_text);
}
}
void LLPanelTopInfoBar::updateParcelIcons()
{
LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
LLViewerRegion* agent_region = gAgent.getRegion();
LLParcel* agent_parcel = vpm->getAgentParcel();
if (!agent_region || !agent_parcel)
return;
if (gSavedSettings.getBOOL("NavBarShowParcelProperties"))
{
LLParcel* current_parcel;
LLViewerRegion* selection_region = vpm->getSelectionRegion();
LLParcel* selected_parcel = vpm->getParcelSelection()->getParcel();
// If agent is in selected parcel we use its properties because
// they are updated more often by LLViewerParcelMgr than agent parcel properties.
// See LLViewerParcelMgr::processParcelProperties().
// This is needed to reflect parcel restrictions changes without having to leave
// the parcel and then enter it again. See EXT-2987
if (selected_parcel && selected_parcel->getLocalID() == agent_parcel->getLocalID()
&& selection_region == agent_region)
{
current_parcel = selected_parcel;
}
else
{
current_parcel = agent_parcel;
}
bool allow_voice = vpm->allowAgentVoice(agent_region, current_parcel);
bool allow_fly = vpm->allowAgentFly(agent_region, current_parcel);
bool allow_push = vpm->allowAgentPush(agent_region, current_parcel);
bool allow_build = vpm->allowAgentBuild(current_parcel); // true when anyone is allowed to build. See EXT-4610.
bool allow_scripts = vpm->allowAgentScripts(agent_region, current_parcel);
bool allow_damage = vpm->allowAgentDamage(agent_region, current_parcel);
// Most icons are "block this ability"
mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
mParcelIcon[FLY_ICON]->setVisible( !allow_fly );
mParcelIcon[PUSH_ICON]->setVisible( !allow_push );
mParcelIcon[BUILD_ICON]->setVisible( !allow_build );
mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
mDamageText->setVisible(allow_damage);
layoutParcelIcons();
}
else
{
for (S32 i = 0; i < ICON_COUNT; ++i)
{
mParcelIcon[i]->setVisible(false);
}
mDamageText->setVisible(false);
}
}
void LLPanelTopInfoBar::updateHealth()
{
static LLUICachedControl<bool> show_icons("NavBarShowParcelProperties", false);
// *FIXME: Status bar owns health information, should be in agent
if (show_icons && gStatusBar)
{
static S32 last_health = -1;
S32 health = gStatusBar->getHealth();
if (health != last_health)
{
std::string text = llformat("%d%%", health);
mDamageText->setText(text);
last_health = health;
}
}
}
void LLPanelTopInfoBar::layoutParcelIcons()
{
// TODO: remove hard-coded values and read them as xml parameters
static const int FIRST_ICON_HPAD = 32;
static const int LAST_ICON_HPAD = 11;
S32 left = mParcelInfoText->getRect().mRight + FIRST_ICON_HPAD;
left = layoutWidget(mDamageText, left);
for (int i = ICON_COUNT - 1; i >= 0; --i)
{
left = layoutWidget(mParcelIcon[i], left);
}
LLRect rect = getRect();
rect.set(rect.mLeft, rect.mTop, left + LAST_ICON_HPAD, rect.mBottom);
setRect(rect);
}
S32 LLPanelTopInfoBar::layoutWidget(LLUICtrl* ctrl, S32 left)
{
// TODO: remove hard-coded values and read them as xml parameters
static const int ICON_HPAD = 2;
if (ctrl->getVisible())
{
LLRect rect = ctrl->getRect();
rect.mRight = left + rect.getWidth();
rect.mLeft = left;
ctrl->setRect(rect);
left += rect.getWidth() + ICON_HPAD;
}
return left;
}
void LLPanelTopInfoBar::onParcelIconClick(EParcelIcon icon)
{
switch (icon)
{
case VOICE_ICON:
LLNotificationsUtil::add("NoVoice");
break;
case FLY_ICON:
LLNotificationsUtil::add("NoFly");
break;
case PUSH_ICON:
LLNotificationsUtil::add("PushRestricted");
break;
case BUILD_ICON:
LLNotificationsUtil::add("NoBuild");
break;
case SCRIPTS_ICON:
{
LLViewerRegion* region = gAgent.getRegion();
if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
{
LLNotificationsUtil::add("ScriptsStopped");
}
else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
{
LLNotificationsUtil::add("ScriptsNotRunning");
}
else
{
LLNotificationsUtil::add("NoOutsideScripts");
}
break;
}
case DAMAGE_ICON:
LLNotificationsUtil::add("NotSafe");
break;
case ICON_COUNT:
break;
// no default to get compiler warning when a new icon gets added
}
}
void LLPanelTopInfoBar::onAgentParcelChange()
{
update();
}
void LLPanelTopInfoBar::onInfoButtonClicked()
{
LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "agent"));
}

View File

@ -0,0 +1,154 @@
/**
* @file llpaneltopinfobar.h
* @brief Coordinates and Parcel Settings information panel definition
*
* $LicenseInfo:firstyear=2010&license=viewergpl$
*
* Copyright (c) 2010, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LLPANELTOPINFOBAR_H_
#define LLPANELTOPINFOBAR_H_
#include "llpanel.h"
class LLButton;
class LLTextBox;
class LLIconCtrl;
class LLParcelChangeObserver;
class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>
{
LOG_CLASS(LLPanelTopInfoBar);
public:
LLPanelTopInfoBar();
~LLPanelTopInfoBar();
/*virtual*/ BOOL postBuild();
/*virtual*/ void draw();
/**
* Updates location and parcel icons on login complete
*/
void handleLoginComplete();
private:
class LLParcelChangeObserver;
friend class LLParcelChangeObserver;
enum EParcelIcon
{
VOICE_ICON = 0,
FLY_ICON,
PUSH_ICON,
BUILD_ICON,
SCRIPTS_ICON,
DAMAGE_ICON,
ICON_COUNT
};
/**
* Initializes parcel icons controls. Called from the constructor.
*/
void initParcelIcons();
BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/**
* Handles clicks on the parcel icons.
*/
void onParcelIconClick(EParcelIcon icon);
/**
* Handles clicks on the info buttons.
*/
void onInfoButtonClicked();
/**
* Called when agent changes the parcel.
*/
void onAgentParcelChange();
/**
* Called when user checks/unchecks Show Coordinates menu item.
*/
void onNavBarShowParcelPropertiesCtrlChanged();
/**
* Shorthand to call updateParcelInfoText() and updateParcelIcons().
*/
void update();
/**
* Updates parcel info text (mParcelInfoText).
*/
void updateParcelInfoText();
/**
* Updates parcel icons (mParcelIcon[]).
*/
void updateParcelIcons();
/**
* Updates health information (mDamageText).
*/
void updateHealth();
/**
* Lays out all parcel icons starting from right edge of the mParcelInfoText + 11px
* (see screenshots in EXT-5808 for details).
*/
void layoutParcelIcons();
/**
* Lays out a widget. Widget's rect mLeft becomes equal to the 'left' argument.
*/
S32 layoutWidget(LLUICtrl* ctrl, S32 left);
/**
* Generates location string and returns it in the loc_str parameter.
*/
void buildLocationString(std::string& loc_str, bool show_coords);
/**
* Sets new value to the mParcelInfoText and updates the size of the top bar.
*/
void setParcelInfoText(const std::string& new_text);
LLButton* mInfoBtn;
LLTextBox* mParcelInfoText;
LLTextBox* mDamageText;
LLIconCtrl* mParcelIcon[ICON_COUNT];
LLParcelChangeObserver* mParcelChangedObserver;
boost::signals2::connection mParcelPropsCtrlConnection;
boost::signals2::connection mShowCoordsCtrlConnection;
boost::signals2::connection mParcelMgrConnection;
};
#endif /* LLPANELTOPINFOBAR_H_ */

View File

@ -827,7 +827,8 @@ void LLParticipantList::LLParticipantListMenu::moderateVoiceAllParticipants(bool
void LLParticipantList::LLParticipantListMenu::confirmMuteAllCallback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 1)
// if Cancel pressed
if (option == 1)
{
return;
}

View File

@ -56,7 +56,7 @@ const S32 LLScrollingPanelParam::PARAM_HINT_HEIGHT = 128;
S32 LLScrollingPanelParam::sUpdateDelayFrames = 0;
LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_params,
LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable )
LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp )
: LLScrollingPanel( panel_params ),
mParam(param),
mAllowModify(allow_modify),
@ -73,9 +73,9 @@ LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_param
F32 min_weight = param->getMinWeight();
F32 max_weight = param->getMaxWeight();
mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, (LLViewerVisualParam*) wearable->getVisualParam(param->getID()), wearable, min_weight);
mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, (LLViewerVisualParam*) wearable->getVisualParam(param->getID()), wearable, min_weight, jointp);
pos_x = getChild<LLViewBorder>("right_border")->getRect().mLeft + left_border->getBorderWidth();
mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, (LLViewerVisualParam*) wearable->getVisualParam(param->getID()), wearable, max_weight );
mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, (LLViewerVisualParam*) wearable->getVisualParam(param->getID()), wearable, max_weight, jointp );
mHintMin->setAllowsUpdates( FALSE );
mHintMax->setAllowsUpdates( FALSE );

View File

@ -42,12 +42,13 @@ class LLViewerVisualParam;
class LLWearable;
class LLVisualParamHint;
class LLViewerVisualParam;
class LLJoint;
class LLScrollingPanelParam : public LLScrollingPanel
{
public:
LLScrollingPanelParam( const LLPanel::Params& panel_params,
LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable );
LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp );
virtual ~LLScrollingPanelParam();
virtual void draw();

View File

@ -59,7 +59,7 @@ void initializeSecHandler()
gSecAPIHandler = gHandlerMap[BASIC_SECHANDLER];
// initialize all SecAPIHandlers
LLProtectedDataException ex = LLProtectedDataException("");
std::string exception_msg;
std::map<std::string, LLPointer<LLSecAPIHandler> >::const_iterator itr;
for(itr = gHandlerMap.begin(); itr != gHandlerMap.end(); ++itr)
{
@ -70,12 +70,12 @@ void initializeSecHandler()
}
catch (LLProtectedDataException e)
{
ex = e;
exception_msg = e.getMessage();
}
}
if (ex.getMessage().length() > 0 ) // an exception was thrown.
if (!exception_msg.empty()) // an exception was thrown.
{
throw ex;
throw LLProtectedDataException(exception_msg.c_str());
}
}

View File

@ -209,7 +209,7 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
{
if ((mOutfitEdit && mOutfitEdit->getVisible()) || (mEditWearable && mEditWearable->getVisible()))
{
if (!gAgentCamera.cameraCustomizeAvatar())
if (!gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement"))
{
gAgentCamera.changeCameraToCustomizeAvatar();
}
@ -217,9 +217,10 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
}
else
{
if (gAgentCamera.cameraCustomizeAvatar())
if (gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement"))
{
gAgentCamera.changeCameraToDefault();
gAgentCamera.resetView();
}
}
}
@ -345,6 +346,7 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam
else if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") )
{
gAgentCamera.changeCameraToDefault();
gAgentCamera.resetView();
}
}
@ -384,6 +386,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we
if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") )
{
gAgentCamera.changeCameraToDefault();
gAgentCamera.resetView();
}
}
}

View File

@ -66,21 +66,6 @@ static const std::string TAB_PANEL_CAPTION_TITLE_BOX = "sidetray_tab_title";
LLSideTray* LLSideTray::sInstance = 0;
/**
* Updates visibility of sidetray tabs buttons according to "SidebarWithButtonsVisibility" setting
*
* @param force_set_visible if true method ignores setting value and set buttons visible.
*/
static void update_tabs_buttons_visibility(bool force_set_visible = false)
{
LLView* side_bar_tabs = gViewerWindow->getRootView()->getChildView("side_bar_tabs");
if (side_bar_tabs)
{
BOOL visible = LLUI::sSettingGroups["config"]->getBOOL("SidebarWithButtonsVisibility");
side_bar_tabs->setVisible(force_set_visible || visible);
}
}
LLSideTray* LLSideTray::getInstance()
{
if (!sInstance)
@ -273,8 +258,6 @@ LLSideTray::LLSideTray(Params& params)
p.name = "buttons_panel";
p.mouse_opaque = false;
mButtonsPanel = LLUICtrlFactory::create<LLPanel>(p);
initControlSettings();
}
@ -563,8 +546,6 @@ void LLSideTray::collapseSideBar()
//mActiveTab->setVisible(FALSE);
reflectCollapseChange();
setFocus( FALSE );
update_tabs_buttons_visibility();
}
void LLSideTray::expandSideBar()
@ -589,8 +570,6 @@ void LLSideTray::expandSideBar()
LLButton* btn = btn_it->second;
btn->setImageOverlay( mActiveTab->mImageSelected );
}
update_tabs_buttons_visibility(true);
}
void LLSideTray::highlightFocused()
@ -658,8 +637,6 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para
panel->onOpen(params);
}
update_tabs_buttons_visibility(true);
return panel;
}
}
@ -751,35 +728,3 @@ void LLSideTray::updateSidetrayVisibility()
}
}
void LLSideTray::initControlSettings()
{
// set listeners to process runtime setting changes
LLUI::sSettingGroups["config"]->getControl("SidebarWithButtonsVisibility")->getSignal()->connect(boost::bind(&LLSideTray::toggleSidetrayAndTabButtonsVisibility, this, _2));
// update visibility according to current value
toggleSidetrayAndTabButtonsVisibility(LLUI::sSettingGroups["config"]->getBOOL("SidebarWithButtonsVisibility"));
}
// sidebar visibility is implemented via its expanding/collapsing
void LLSideTray::toggleSidetrayAndTabButtonsVisibility(const LLSD::Boolean& new_visibility)
{
// If new_visibility==FALSE it gets invisible but still can be expanded in other ways (Ctrl+I to see My Inventory)
// store collapsed state to restore it properly on next call
static bool was_collapsed = false;
if (!new_visibility && !mCollapsed)
{
collapseSideBar();
was_collapsed = true;
}
// should be visible: expand only if it was expanded when has been collapsed on previous call
else if (new_visibility && was_collapsed)
{
if (mCollapsed) expandSideBar();
was_collapsed = false;
}
update_tabs_buttons_visibility(new_visibility);
}

View File

@ -179,16 +179,6 @@ private:
LLSideTray::getInstance()->setEnabled(FALSE);
}
/**
* Initializes listener of SidebarWithButtonsVisibility setting and updates state according to it.
*/
void initControlSettings();
/**
* Updates Sidebar and its Tab Buttons visibility according to passed value.
*/
void toggleSidetrayAndTabButtonsVisibility(const LLSD::Boolean& new_visibility);
private:
LLPanel* mButtonsPanel;

View File

@ -735,6 +735,8 @@ bool idle_startup()
// Make sure the process dialog doesn't hide things
gViewerWindow->setShowProgress(FALSE);
initialize_edit_menu();
// Show the login dialog
login_show();
// connect dialog is already shown, so fill in the names

View File

@ -394,18 +394,21 @@ void LLStatusBar::setBalance(S32 balance)
{
std::string money_str = LLResMgr::getInstance()->getMonetaryString( balance );
LLButton* btn_buy_currency = getChild<LLButton>("buycurrency");
LLTextBox* balance_box = getChild<LLTextBox>("balance");
LLStringUtil::format_map_t string_args;
string_args["[AMT]"] = llformat("%s", money_str.c_str());
std::string label_str = getString("buycurrencylabel", string_args);
btn_buy_currency->setLabel(label_str);
balance_box->setValue(label_str);
// Resize the balance button so that the label fits it, and the button expands to the left.
// *TODO: LLButton should have an option where to expand.
// Resize the L$ balance background to be wide enough for your balance plus the buy button
{
S32 saved_right = btn_buy_currency->getRect().mRight;
btn_buy_currency->autoResize();
btn_buy_currency->translate(saved_right - btn_buy_currency->getRect().mRight, 0);
const S32 HPAD = 24;
LLRect balance_rect = balance_box->getTextBoundingRect();
LLRect buy_rect = getChildView("buyL")->getRect();
LLView* balance_bg_view = getChildView("balance_bg");
LLRect balance_bg_rect = balance_bg_view->getRect();
balance_bg_rect.mLeft = balance_bg_rect.mRight - (buy_rect.getWidth() + balance_rect.getWidth() + HPAD);
balance_bg_view->setShape(balance_bg_rect);
}
if (mBalance && (fabs((F32)(mBalance - balance)) > gSavedSettings.getF32("UISndMoneyChangeThreshold")))

View File

@ -38,6 +38,7 @@
#include "llsdserialize.h"
#include "llagent.h"
#include "llvoavatarself.h"
#include "llslurl.h"
#include "llviewercontrol.h" // for gSavedSettings
#include "llviewerparcelmgr.h"
@ -108,6 +109,16 @@ void LLTeleportHistory::onTeleportFailed()
}
}
void LLTeleportHistory::handleLoginComplete()
{
if( mGotInitialUpdate )
{
return;
}
updateCurrentLocation(gAgent.getPositionGlobal());
}
void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos)
{
if (mRequestedItem != -1) // teleport within the history in progress?
@ -117,6 +128,17 @@ void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos)
}
else
{
//EXT-7034
//skip initial update if agent avatar is no valid yet
//this may happen when updateCurrentLocation called while login process
//sometimes isAgentAvatarValid return false and in this case new_pos
//(which actually is gAgent.getPositionGlobal() ) is invalid
//if this position will be saved then teleport back will teleport user to wrong position
if ( !mGotInitialUpdate && !isAgentAvatarValid() )
{
return ;
}
// If we're getting the initial location update
// while we already have a (loaded) non-empty history,
// there's no need to purge forward items or add a new item.

View File

@ -136,6 +136,10 @@ public:
* @see load()
*/
void dump() const;
/**
* Process login complete event. Basically put current location into history
*/
void handleLoginComplete();
private:

View File

@ -57,17 +57,52 @@
using namespace LLVOAvatarDefines;
class LLTexLayerInfo
{
friend class LLTexLayer;
friend class LLTexLayerTemplate;
friend class LLTexLayerInterface;
public:
LLTexLayerInfo();
~LLTexLayerInfo();
BOOL parseXml(LLXmlTreeNode* node);
BOOL createVisualParams(LLVOAvatar *avatar);
BOOL isUserSettable() { return mLocalTexture != -1; }
S32 getLocalTexture() const { return mLocalTexture; }
BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; }
std::string getName() const { return mName; }
private:
std::string mName;
BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer,
LLTexLayerInterface::ERenderPass mRenderPass;
std::string mGlobalColor;
LLColor4 mFixedColor;
S32 mLocalTexture;
std::string mStaticImageFileName;
BOOL mStaticImageIsMask;
BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask
BOOL mIsVisibilityMask;
typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t;
morph_name_list_t mMorphNameList;
param_color_info_list_t mParamColorInfoList;
param_alpha_info_list_t mParamAlphaInfoList;
};
//-----------------------------------------------------------------------------
// LLBakedUploadData()
//-----------------------------------------------------------------------------
LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
LLTexLayerSet* layerset,
const LLUUID& id,
BOOL highest_lod) :
const LLUUID& id) :
mAvatar(avatar),
mTexLayerSet(layerset),
mID(id),
mHighestLOD(highest_lod),
mStartTime(LLFrameTimer::getTotalTime()) // Record starting time
{
}
@ -87,7 +122,7 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner,
mNeedsUpdate(TRUE),
mNeedsUpload(FALSE),
mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates
mNeedsLowResUpload(TRUE),
mNumLowresUploads(0),
mTexLayerSet(owner)
{
LLTexLayerSetBuffer::sGLByteCount += getSize();
@ -130,6 +165,7 @@ void LLTexLayerSetBuffer::dumpTotalByteCount()
void LLTexLayerSetBuffer::requestUpdate()
{
conditionalRestartUploadTimer();
mNeedsUpdate = TRUE;
// 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.
@ -137,18 +173,27 @@ void LLTexLayerSetBuffer::requestUpdate()
}
void LLTexLayerSetBuffer::requestUpload()
{
conditionalRestartUploadTimer();
mNeedsUpload = TRUE;
mNumLowresUploads = 0;
mUploadPending = TRUE;
}
void LLTexLayerSetBuffer::conditionalRestartUploadTimer()
{
// If we requested a new upload but haven't even uploaded
// a low res version of our last upload request, then
// keep the timer ticking instead of resetting it.
if (mNeedsUpload && mNeedsLowResUpload)
if (mNeedsUpload && (mNumLowresUploads == 0))
{
mNeedsUploadTimer.unpause();
}
else
{
mNeedsUploadTimer.reset();
mNeedsUploadTimer.start();
}
mNeedsUpload = TRUE;
mNeedsLowResUpload = TRUE;
mUploadPending = TRUE;
mNeedsUploadTimer.unpause();
}
void LLTexLayerSetBuffer::cancelUpload()
@ -272,11 +317,26 @@ BOOL LLTexLayerSetBuffer::render()
return success;
}
bool LLTexLayerSetBuffer::isInitialized(void) const
BOOL LLTexLayerSetBuffer::isInitialized(void) const
{
return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated();
}
BOOL LLTexLayerSetBuffer::uploadPending() const
{
return mUploadPending;
}
BOOL LLTexLayerSetBuffer::uploadNeeded() const
{
return mNeedsUpload;
}
BOOL LLTexLayerSetBuffer::uploadInProgress() const
{
return !mUploadID.isNull();
}
BOOL LLTexLayerSetBuffer::isReadyToUpload() const
{
if (!mNeedsUpload) return FALSE; // Don't need to upload if we haven't requested one.
@ -289,10 +349,14 @@ BOOL LLTexLayerSetBuffer::isReadyToUpload() const
const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureTimeout");
if (texture_timeout)
{
// The timeout period increases exponentially between every lowres upload in order to prevent
// spamming the server with frequent uploads.
const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads);
// If we hit our timeout and have textures available at even lower resolution, then upload.
const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout;
const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold;
const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable();
if (has_lower_lod && is_upload_textures_timeout && mNeedsLowResUpload) return TRUE;
if (has_lower_lod && is_upload_textures_timeout) return TRUE;
}
return FALSE;
}
@ -387,14 +451,13 @@ void LLTexLayerSetBuffer::readBackAndUpload()
if( valid )
{
const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal();
// baked_upload_data is owned by the responder and deleted after the request completes
LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp,
this->mTexLayerSet,
asset_id,
highest_lod);
asset_id);
mUploadID = asset_id;
const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal();
// upload the image
std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture");
@ -431,15 +494,21 @@ void LLTexLayerSetBuffer::readBackAndUpload()
LLNotificationsUtil::add("AvatarRezSelfBakeNotification",args);
llinfos << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << llendl;
}
if (highest_lod)
{
// Sending the final LOD for the baked texture.
// All done, pause the upload timer so we know how long it took.
mNeedsUpload = FALSE;
mNeedsUploadTimer.pause();
}
else
{
mNeedsLowResUpload = FALSE;
// Sending a lower level LOD for the baked texture.
// Restart the upload timer.
mNumLowresUploads++;
mNeedsUploadTimer.unpause();
mNeedsUploadTimer.reset();
}
}
else
@ -967,11 +1036,11 @@ void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_
mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex);
}
BOOL LLTexLayerSet::isMorphValid()
BOOL LLTexLayerSet::isMorphValid() const
{
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
for(layer_list_t::const_iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
const LLTexLayerInterface* layer = *iter;
if (layer && !layer->isMorphValid())
{
return FALSE;
@ -1187,7 +1256,6 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set):
mTexLayerSet( layer_set ),
mMorphMasksValid( FALSE ),
mStaticImageInvalid( FALSE ),
mInfo(NULL),
mHasMorph(FALSE)
{
@ -1301,17 +1369,17 @@ void LLTexLayerInterface::invalidateMorphMasks()
mMorphMasksValid = FALSE;
}
LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index)
LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) const
{
LLViewerVisualParam *result = NULL;
for (param_color_list_t::iterator color_iter = mParamColorList.begin(); color_iter != mParamColorList.end() && !result; ++color_iter)
for (param_color_list_t::const_iterator color_iter = mParamColorList.begin(); color_iter != mParamColorList.end() && !result; ++color_iter)
{
if ((*color_iter)->getID() == index)
{
result = *color_iter;
}
}
for (param_alpha_list_t::iterator alpha_iter = mParamAlphaList.begin(); alpha_iter != mParamAlphaList.end() && !result; ++alpha_iter)
for (param_alpha_list_t::const_iterator alpha_iter = mParamAlphaList.begin(); alpha_iter != mParamAlphaList.end() && !result; ++alpha_iter)
{
if ((*alpha_iter)->getID() == index)
{
@ -1565,7 +1633,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
return success;
}
U8* LLTexLayer::getAlphaData()
const U8* LLTexLayer::getAlphaData() const
{
LLCRC alpha_mask_crc;
const LLUUID& uuid = getUUID();
@ -1581,7 +1649,7 @@ U8* LLTexLayer::getAlphaData()
U32 cache_index = alpha_mask_crc.getCRC();
alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index);
alpha_cache_t::const_iterator iter2 = mAlphaCache.find(cache_index);
return (iter2 == mAlphaCache.end()) ? 0 : iter2->second;
}
@ -1804,7 +1872,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
{
S32 size = width * height;
U8* alphaData = getAlphaData();
const U8* alphaData = getAlphaData();
if (!alphaData && hasAlphaParams())
{
LLColor4 net_color;
@ -1827,7 +1895,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32
}
}
/*virtual*/ BOOL LLTexLayer::isInvisibleAlphaMask()
/*virtual*/ BOOL LLTexLayer::isInvisibleAlphaMask() const
{
if (mLocalTextureObject)
{
@ -1840,8 +1908,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32
return FALSE;
}
// private helper function
LLUUID LLTexLayer::getUUID()
LLUUID LLTexLayer::getUUID() const
{
LLUUID uuid;
if( getInfo()->mLocalTexture != -1 )
@ -1900,7 +1967,7 @@ LLTexLayerTemplate::~LLTexLayerTemplate()
return LLTexLayerInterface::setInfo(info, wearable);
}
U32 LLTexLayerTemplate::updateWearableCache()
U32 LLTexLayerTemplate::updateWearableCache() const
{
mWearableCache.clear();
@ -1925,7 +1992,7 @@ U32 LLTexLayerTemplate::updateWearableCache()
}
return added;
}
LLTexLayer* LLTexLayerTemplate::getLayer(U32 i)
LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
{
if (mWearableCache.size() <= i)
{
@ -2034,7 +2101,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i)
}
}
/*virtual*/ BOOL LLTexLayerTemplate::isInvisibleAlphaMask()
/*virtual*/ BOOL LLTexLayerTemplate::isInvisibleAlphaMask() const
{
U32 num_wearables = updateWearableCache();
for (U32 i = 0; i < num_wearables; i++)
@ -2058,19 +2125,17 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i)
//-----------------------------------------------------------------------------
LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name)
{
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
for (layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
if (layer->getName() == name)
{
return layer;
}
}
for( layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ )
for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
if (layer->getName() == name)
{
return layer;
@ -2115,7 +2180,7 @@ LLTexLayerStaticImageList::~LLTexLayerStaticImageList()
deleteCachedImages();
}
void LLTexLayerStaticImageList::dumpByteCount()
void LLTexLayerStaticImageList::dumpByteCount() const
{
llinfos << "Avatar Static Textures " <<
"KB GL:" << (mGLBytes / 1024) <<
@ -2235,11 +2300,18 @@ const std::string LLTexLayerSetBuffer::dumpTextureInfo() const
if (!isAgentAvatarValid()) return "";
const BOOL is_high_res = !mNeedsUpload;
const BOOL is_low_res = !mNeedsLowResUpload;
const U32 num_low_res = mNumLowresUploads;
const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32();
const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(mTexLayerSet);
std::string text = llformat("[ HiRes:%d LoRes:%d Timer:%d ] %s",
is_high_res, is_low_res, upload_time,
std::string status = "CREATING ";
if (!uploadNeeded()) status = "DONE ";
if (uploadInProgress()) status = "UPLOADING";
std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s",
status.c_str(),
is_high_res, num_low_res,
upload_time,
local_texture_info.c_str());
return text;
}

View File

@ -1,6 +1,6 @@
/**
* @file lltexlayer.h
* @brief A texture layer. Used for avatars.
* @brief Texture layer classes. Used for avatars.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
@ -35,40 +35,31 @@
#include <deque>
#include "lldynamictexture.h"
#include "llwearable.h"
#include "llvoavatardefines.h"
#include "lltexlayerparams.h"
class LLVOAvatar;
class LLVOAvatarSelf;
class LLImageTGA;
class LLImageRaw;
class LLXmlTreeNode;
class LLPolyMorphTarget;
class LLTexLayerSet;
class LLTexLayerSetInfo;
class LLTexLayerInfo;
class LLTexLayerSetBuffer;
class LLTexLayerParamColor;
class LLTexLayerParamColorInfo;
class LLTexLayerParamAlpha;
class LLTexLayerParamAlphaInfo;
class LLWearable;
class LLViewerVisualParam;
typedef std::vector<LLTexLayerParamColor *> param_color_list_t;
typedef std::vector<LLTexLayerParamAlpha *> param_alpha_list_t;
typedef std::vector<LLTexLayerParamColorInfo *> param_color_info_list_t;
typedef std::vector<LLTexLayerParamAlphaInfo *> param_alpha_info_list_t;
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerInterface
// Interface class to generalize functionality shared by LLTexLayer and LLTexLayerTemplate.
//
// Interface class to generalize functionality shared by LLTexLayer
// and LLTexLayerTemplate.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerInterface
{
public:
enum ERenderPass
enum ERenderPass
{
RP_COLOR,
RP_BUMP,
@ -79,84 +70,78 @@ public:
LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable);
virtual ~LLTexLayerInterface() {}
const LLTexLayerInfo* getInfo() const { return mInfo; }
virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0;
void requestUpdate();
LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; }
virtual void deleteCaches() = 0;
void invalidateMorphMasks();
virtual void setHasMorph(BOOL newval) { mHasMorph = newval; }
BOOL hasMorph() { return mHasMorph; }
BOOL isMorphValid() { return mMorphMasksValid; }
virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0;
virtual BOOL isInvisibleAlphaMask() const = 0;
const LLTexLayerInfo* getInfo() const { return mInfo; }
virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions
const std::string& getName() const;
ERenderPass getRenderPass() const;
const std::string& getGlobalColor() const;
const LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; }
LLTexLayerSet* const getTexLayerSet() { return mTexLayerSet; }
virtual BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) = 0;
void invalidateMorphMasks();
virtual void setHasMorph(BOOL newval) { mHasMorph = newval; }
BOOL hasMorph() const { return mHasMorph; }
BOOL isMorphValid() const { return mMorphMasksValid; }
void requestUpdate();
virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0;
BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); }
BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); }
ERenderPass getRenderPass() const;
BOOL isVisibilityMask() const;
virtual BOOL isInvisibleAlphaMask() = 0;
LLTexLayerSet* getLayerSet() {return mTexLayerSet;}
LLViewerVisualParam* getVisualParamPtr(S32 index);
protected:
LLTexLayerSet* const mTexLayerSet;
const std::string& getGlobalColor() const;
LLViewerVisualParam* getVisualParamPtr(S32 index) const;
protected:
LLTexLayerSet* const mTexLayerSet;
const LLTexLayerInfo* mInfo;
BOOL mMorphMasksValid;
BOOL mHasMorph;
// Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order.
param_color_list_t mParamColorList;
param_alpha_list_t mParamAlphaList;
// mGlobalColor name stored in mInfo
// mFixedColor value stored in mInfo
param_alpha_list_t mParamAlphaList;
BOOL mMorphMasksValid;
BOOL mStaticImageInvalid;
BOOL mHasMorph;
const LLTexLayerInfo *mInfo;
};
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerTemplate
// Template class
// Only exists for llvoavatarself
//
// Only exists for llvoavatarself.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerTemplate : public LLTexLayerInterface
{
public:
LLTexLayerTemplate(LLTexLayerSet* const layer_set);
LLTexLayerTemplate(const LLTexLayerTemplate &layer);
/*virtual*/ ~LLTexLayerTemplate();
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
/*virtual*/ BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions
/*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
/*virtual*/ void setHasMorph(BOOL newval);
/*virtual*/ void deleteCaches();
/*virtual*/ BOOL isInvisibleAlphaMask();
/*virtual*/ BOOL isInvisibleAlphaMask() const;
protected:
U32 updateWearableCache() const;
LLTexLayer* getLayer(U32 i) const;
private:
U32 updateWearableCache();
LLTexLayer* getLayer(U32 i);
typedef std::vector<LLWearable*> wearable_cache_t;
wearable_cache_t mWearableCache;
mutable wearable_cache_t mWearableCache; // mutable b/c most get- require updating this cache
};
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayer
// A single texture layer
// Only exists for llvoavatarself
//
// A single texture layer. Only exists for llvoavatarself.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayer : public LLTexLayerInterface
{
public:
@ -165,79 +150,37 @@ public:
LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable);
/*virtual*/ ~LLTexLayer();
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
/*virtual*/ void deleteCaches();
U8* getAlphaData();
const U8* getAlphaData() const;
BOOL findNetColor(LLColor4* color) const;
/*virtual*/ BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color);
void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
/*virtual*/ BOOL isInvisibleAlphaMask();
/*virtual*/ BOOL isInvisibleAlphaMask() const;
void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; }
LLLocalTextureObject* getLTO() { return mLocalTextureObject; }
static void calculateTexLayerColor(const param_color_list_t &param_list, LLColor4 &net_color);
void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; }
LLLocalTextureObject* getLTO() { return mLocalTextureObject; }
static void calculateTexLayerColor(const param_color_list_t &param_list, LLColor4 &net_color);
protected:
LLUUID getUUID() const;
private:
LLUUID getUUID();
typedef std::map<U32, U8*> alpha_cache_t;
alpha_cache_t mAlphaCache;
LLLocalTextureObject *mLocalTextureObject;
LLLocalTextureObject* mLocalTextureObject;
};
// Make private
class LLTexLayerInfo
{
friend class LLTexLayer;
friend class LLTexLayerTemplate;
friend class LLTexLayerInterface;
public:
LLTexLayerInfo();
~LLTexLayerInfo();
BOOL parseXml(LLXmlTreeNode* node);
BOOL createVisualParams(LLVOAvatar *avatar);
BOOL isUserSettable() { return mLocalTexture != -1; }
S32 getLocalTexture() const { return mLocalTexture; }
BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; }
std::string getName() const { return mName; }
private:
std::string mName;
BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer,
LLTexLayer::ERenderPass mRenderPass;
std::string mGlobalColor;
LLColor4 mFixedColor;
S32 mLocalTexture;
std::string mStaticImageFileName;
BOOL mStaticImageIsMask;
BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask
BOOL mIsVisibilityMask;
typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t;
morph_name_list_t mMorphNameList;
param_color_info_list_t mParamColorInfoList;
param_alpha_info_list_t mParamAlphaInfoList;
};
//
// LLTexLayer
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerSet
// An ordered set of texture layers that get composited into a single texture.
// Only exists for llvoavatarself
//
// An ordered set of texture layers that gets composited into a single texture.
// Only exists for llvoavatarself.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerSet
{
friend class LLTexLayerSetBuffer;
@ -245,186 +188,171 @@ public:
LLTexLayerSet(LLVOAvatarSelf* const avatar);
~LLTexLayerSet();
const LLTexLayerSetInfo* getInfo() const { return mInfo; }
BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
const LLTexLayerSetInfo* getInfo() const { return mInfo; }
BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
BOOL render(S32 x, S32 y, S32 width, S32 height);
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false);
BOOL render(S32 x, S32 y, S32 width, S32 height);
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false);
BOOL isBodyRegion(const std::string& region) const;
LLTexLayerSetBuffer* getComposite();
const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist.
void requestUpdate();
void requestUpload();
void cancelUpload();
void updateComposite();
BOOL isLocalTextureDataAvailable() const;
BOOL isLocalTextureDataFinal() const;
void createComposite();
void destroyComposite();
void setUpdatesEnabled(BOOL b);
BOOL getUpdatesEnabled() const { return mUpdatesEnabled; }
void deleteCaches();
void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height);
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
BOOL isMorphValid();
void invalidateMorphMasks();
LLTexLayerInterface* findLayerByName(const std::string& name);
void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable);
BOOL isBodyRegion(const std::string& region) const;
LLTexLayerSetBuffer* getComposite();
const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist.
void requestUpdate();
void requestUpload();
void cancelUpload();
void updateComposite();
BOOL isLocalTextureDataAvailable() const;
BOOL isLocalTextureDataFinal() const;
void createComposite();
void destroyComposite();
void setUpdatesEnabled(BOOL b);
BOOL getUpdatesEnabled() const { return mUpdatesEnabled; }
void deleteCaches();
void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height);
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
BOOL isMorphValid() const;
void invalidateMorphMasks();
LLTexLayerInterface* findLayerByName(const std::string& name);
void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable);
LLVOAvatarSelf* getAvatar() const { return mAvatar; }
const std::string getBodyRegionName() const;
BOOL hasComposite() const { return (mComposite.notNull()); }
LLVOAvatarSelf* getAvatar() const { return mAvatar; }
const std::string getBodyRegionName() const;
BOOL hasComposite() const { return (mComposite.notNull()); }
LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; }
void setBakedTexIndex( LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
BOOL isVisible() const { return mIsVisible; }
void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
BOOL isVisible() const { return mIsVisible; }
public:
static BOOL sHasCaches;
typedef std::vector<LLTexLayerInterface *> layer_list_t;
static BOOL sHasCaches;
private:
layer_list_t mLayerList;
layer_list_t mMaskLayerList;
typedef std::vector<LLTexLayerInterface *> layer_list_t;
layer_list_t mLayerList;
layer_list_t mMaskLayerList;
LLPointer<LLTexLayerSetBuffer> mComposite;
LLVOAvatarSelf* const mAvatar; // Backlink only; don't make this an LLPointer.
BOOL mUpdatesEnabled;
BOOL mIsVisible;
LLVOAvatarSelf* const mAvatar; // note: backlink only; don't make this an LLPointer.
BOOL mUpdatesEnabled;
BOOL mIsVisible;
LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex;
const LLTexLayerSetInfo *mInfo;
const LLTexLayerSetInfo* mInfo;
};
// Contains shared layer set data
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerSetInfo
//
// Contains shared layer set data.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerSetInfo
{
friend class LLTexLayerSet;
public:
LLTexLayerSetInfo();
~LLTexLayerSetInfo();
BOOL parseXml(LLXmlTreeNode* node);
void createVisualParams(LLVOAvatar *avatar);
private:
std::string mBodyRegion;
S32 mWidth;
S32 mHeight;
std::string mStaticAlphaFileName;
BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName)
typedef std::vector<LLTexLayerInfo*> layer_info_list_t;
layer_info_list_t mLayerInfoList;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerSetBuffer
//
// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerSetBuffer : public LLViewerDynamicTexture
{
public:
LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);
virtual ~LLTexLayerSetBuffer();
/*virtual*/ S8 getType() const ;
/*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 needsRender();
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 uploadPending() { return mUploadPending; }
BOOL render( S32 x, S32 y, S32 width, S32 height );
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();
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
BOOL mNeedsLowResUpload; // Whether we have sent a lowres version of our baked textures to the server
BOOL mUploadPending; // Whether we have received back the new baked textures
LLUUID mUploadID; // Identifies the current upload process (null if none). Used to avoid overlaps (eg, when the user rapidly makes two changes outside of Face Edit)
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
};
//
// LLTexLayerSet
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerStaticImageList
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerStaticImageList : public LLSingleton<LLTexLayerStaticImageList>
{
public:
LLTexLayerStaticImageList();
~LLTexLayerStaticImageList();
LLViewerTexture* getTexture(const std::string& file_name, BOOL is_mask);
LLImageTGA* getImageTGA(const std::string& file_name);
void deleteCachedImages();
void dumpByteCount();
LLImageTGA* getImageTGA(const std::string& file_name);
void deleteCachedImages();
void dumpByteCount() const;
protected:
BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw);
private:
BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw);
private:
LLStringTable mImageNames;
typedef std::map< const char*, LLPointer<LLViewerTexture> > texture_map_t;
texture_map_t mStaticImageList;
typedef std::map< const char*, LLPointer<LLImageTGA> > image_tga_map_t;
image_tga_map_t mStaticImageListTGA;
S32 mGLBytes;
S32 mTGABytes;
LLStringTable mImageNames;
typedef std::map<const char*, LLPointer<LLViewerTexture> > texture_map_t;
texture_map_t mStaticImageList;
typedef std::map<const char*, LLPointer<LLImageTGA> > image_tga_map_t;
image_tga_map_t mStaticImageListTGA;
S32 mGLBytes;
S32 mTGABytes;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLBakedUploadData
//
// Used by LLTexLayerSetBuffer for a callback.
// Note to anyone merging branches - this supercedes the previous fix
// for DEV-31590 "Heap corruption and crash after outfit changes",
// here and in lltexlayer.cpp. Equally correct and a bit simpler.
class LLBakedUploadData
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct LLBakedUploadData
{
public:
LLBakedUploadData(const LLVOAvatarSelf* avatar,
LLTexLayerSet* layerset,
const LLUUID& id,
BOOL highest_lod);
const LLUUID& id);
~LLBakedUploadData() {}
const LLUUID mID;
const LLVOAvatarSelf* mAvatar; // just backlink, don't LLPointer
const LLVOAvatarSelf* mAvatar; // note: backlink only; don't LLPointer
LLTexLayerSet* mTexLayerSet;
const U64 mStartTime; // Used to measure time baked texture upload requires
BOOL mHighestLOD;
const U64 mStartTime; // for measuring baked texture upload time
};
#endif // LL_LLTEXLAYER_H

View File

@ -42,6 +42,10 @@ class LLViewerTexture;
class LLVOAvatar;
class LLWearable;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerParam
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerParam : public LLViewerVisualParam
{
public:
@ -55,9 +59,10 @@ protected:
LLVOAvatar* mAvatar;
};
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerParamAlpha
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerParamAlpha : public LLTexLayerParam
{
public:
@ -124,9 +129,10 @@ private:
// LLTexLayerParamAlpha
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLTexLayerParamColor
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerParamColor : public LLTexLayerParam
{
public:
@ -184,8 +190,9 @@ private:
S32 mNumColors;
};
//
// LLTexLayerParamColor
//-----------------------------------------------------------------------------
typedef std::vector<LLTexLayerParamColor *> param_color_list_t;
typedef std::vector<LLTexLayerParamAlpha *> param_alpha_list_t;
typedef std::vector<LLTexLayerParamColorInfo *> param_color_info_list_t;
typedef std::vector<LLTexLayerParamAlphaInfo *> param_alpha_info_list_t;
#endif

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