diff options
49 files changed, 1071 insertions, 722 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 0206ced949..4fb1de87eb 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -143,7 +143,9 @@ Gigs Taggart VWR-1434 VWR-1987 VWR-2065 + VWR-2491 VWR-2502 + VWR-2331 Ginko Bayliss VWR-4 Grazer Kline @@ -154,6 +156,7 @@ Gudmund Shepherd Hamncheese Omlet VWR-333 Henri Beauchamp + VWR-1320 VWR-1406 VWR-4157 Hikkoshi Sakai @@ -262,6 +265,7 @@ Nicholaz Beresford VWR-1721 VWR-1723 VWR-1732 + VWR-1754 VWR-1769 VWR-1808 VWR-1861 diff --git a/etc/message.xml b/etc/message.xml index 701d049678..f6f43bd0ff 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -360,6 +360,14 @@ <boolean>true</boolean> </map> + <key>ParcelObjectOwnersReply</key> + <map> + <key>flavor</key> + <string>llsd</string> + <key>trusted-sender</key> + <boolean>true</boolean> + </map> + <key>ParcelProperties</key> <map> <key>flavor</key> @@ -368,6 +376,14 @@ <boolean>true</boolean> </map> + <key>LandStatReply</key> + <map> + <key>flavor</key> + <string>llsd</string> + <key>trusted-sender</key> + <boolean>true</boolean> + </map> + <key>avatarnotesrequest</key> <map> <key>service_name</key> diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 1c8fb4234f..d7ae9611fc 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -40,9 +40,7 @@ #include "llimagebmp.h" #include "llimagetga.h" #include "llimagej2c.h" -#if JPEG_SUPPORT #include "llimagejpeg.h" -#endif #include "llimagepng.h" #include "llimagedxt.h" @@ -1192,11 +1190,9 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip case IMG_CODEC_TGA: image = new LLImageTGA(); break; -#if JPEG_SUPPORT case IMG_CODEC_JPEG: image = new LLImageJPEG(); break; -#endif case IMG_CODEC_J2C: image = new LLImageJ2C(); break; @@ -1280,20 +1276,18 @@ LLImageFormatted* LLImageFormatted::createFromType(S8 codec) case IMG_CODEC_TGA: image = new LLImageTGA(); break; -#if JPEG_SUPPORT case IMG_CODEC_JPEG: image = new LLImageJPEG(); break; -#endif + case IMG_CODEC_PNG: + image = new LLImagePNG(); + break; case IMG_CODEC_J2C: image = new LLImageJ2C(); break; case IMG_CODEC_DXT: image = new LLImageDXT(); break; - case IMG_CODEC_PNG: - image = new LLImagePNG(); - break; default: image = NULL; break; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 98a86ad755..c4fd661976 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -255,6 +255,8 @@ public: // New methods public: + // subclasses must return a prefered file extension (lowercase without a leading dot) + virtual std::string getExtension() = 0; // calcHeaderSize() returns the maximum size of header; // 0 indicates we don't know have a header and have to lead the entire file virtual S32 calcHeaderSize() { return 0; }; diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp index f8423000a8..b6b1d695d1 100644 --- a/indra/llimage/llimagebmp.cpp +++ b/indra/llimage/llimagebmp.cpp @@ -644,10 +644,10 @@ BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time) break; } - for( S32 i = 0; i < alignment_bytes; i++ ) - { - *dst++ = 0; - } + } + for( S32 i = 0; i < alignment_bytes; i++ ) + { + *dst++ = 0; } } diff --git a/indra/llimage/llimagebmp.h b/indra/llimage/llimagebmp.h index 00d3e957e4..6ad1fac4ae 100644 --- a/indra/llimage/llimagebmp.h +++ b/indra/llimage/llimagebmp.h @@ -44,6 +44,7 @@ protected: public: LLImageBMP(); + /*virtual*/ std::string getExtension() { return std::string("bmp"); } /*virtual*/ BOOL updateData(); /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time); /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time); diff --git a/indra/llimage/llimagedxt.h b/indra/llimage/llimagedxt.h index b6df098456..c994a8578b 100644 --- a/indra/llimage/llimagedxt.h +++ b/indra/llimage/llimagedxt.h @@ -102,6 +102,7 @@ private: public: LLImageDXT(); + /*virtual*/ std::string getExtension() { return std::string("dxt"); } /*virtual*/ BOOL updateData(); /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time); diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h index 8d01eceb54..03172d344f 100644 --- a/indra/llimage/llimagej2c.h +++ b/indra/llimage/llimagej2c.h @@ -45,6 +45,7 @@ public: LLImageJ2C(); // Base class overrides + /*virtual*/ std::string getExtension() { return std::string("j2c"); } /*virtual*/ BOOL updateData(); /*virtual*/ BOOL decode(LLImageRaw *raw_imagep, F32 decode_time); /*virtual*/ BOOL decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count); diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp index aebe87d626..1bddd7a051 100644 --- a/indra/llimage/llimagejpeg.cpp +++ b/indra/llimage/llimagejpeg.cpp @@ -35,13 +35,15 @@ #include "llerror.h" -LLImageJPEG::LLImageJPEG() +LLImageJPEG::LLImageJPEG(S32 quality) : LLImageFormatted(IMG_CODEC_JPEG), mOutputBuffer( NULL ), mOutputBufferSize( 0 ), - mEncodeQuality( 75 ) // on a scale from 1 to 100 + mEncodeQuality( quality ) // on a scale from 1 to 100 { + // Including in initializer list above generates warning on VC2005 + memset(mSetjmpBuffer, 0, sizeof(mSetjmpBuffer)); } LLImageJPEG::~LLImageJPEG() diff --git a/indra/llimage/llimagejpeg.h b/indra/llimage/llimagejpeg.h index 054ddad9bc..36d3454d4b 100644 --- a/indra/llimage/llimagejpeg.h +++ b/indra/llimage/llimagejpeg.h @@ -52,8 +52,9 @@ protected: virtual ~LLImageJPEG(); public: - LLImageJPEG(); + LLImageJPEG(S32 quality = 75); + /*virtual*/ std::string getExtension() { return std::string("jpg"); } /*virtual*/ BOOL updateData(); /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time); /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time); diff --git a/indra/llimage/llimagepng.h b/indra/llimage/llimagepng.h index 027caf9780..38af80f2dd 100644 --- a/indra/llimage/llimagepng.h +++ b/indra/llimage/llimagepng.h @@ -42,9 +42,10 @@ protected: public: LLImagePNG(); - BOOL updateData(); - BOOL decode(LLImageRaw* raw_image, F32 decode_time); - BOOL encode(const LLImageRaw* raw_image, F32 encode_time); + /*virtual*/ std::string getExtension() { return std::string("png"); } + /*virtual*/ BOOL updateData(); + /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time); + /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time); private: U8* mTmpWriteBuffer; diff --git a/indra/llimage/llimagetga.h b/indra/llimage/llimagetga.h index d1178ffb73..e8f9672778 100644 --- a/indra/llimage/llimagetga.h +++ b/indra/llimage/llimagetga.h @@ -45,6 +45,7 @@ public: LLImageTGA(); LLImageTGA(const std::string& file_name); + /*virtual*/ std::string getExtension() { return std::string("tga"); } /*virtual*/ BOOL updateData(); /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time=0.0); /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time=0.0); diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index fde210ef50..0372bae106 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -477,8 +477,8 @@ inline F32 llsimple_angle(F32 angle) return angle; } -//calculate the nearesr power of two number for val, bounded by max_power_two -inline U32 get_nearest_power_two(U32 val, U32 max_power_two) +//SDK - Renamed this to get_lower_power_two, since this is what this actually does. +inline U32 get_lower_power_two(U32 val, U32 max_power_two) { if(!max_power_two) { @@ -493,4 +493,34 @@ inline U32 get_nearest_power_two(U32 val, U32 max_power_two) return max_power_two ; } + +// calculate next highest power of two, limited by max_power_two +// This is taken from a brilliant little code snipped on http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html +// Basically we convert the binary to a solid string of 1's with the same +// number of digits, then add one. We subtract 1 initially to handle +// the case where the number passed in is actually a power of two. +// WARNING: this only works with 32 bit ints. +inline U32 get_next_power_two(U32 val, U32 max_power_two) +{ + if(!max_power_two) + { + max_power_two = 1 << 31 ; + } + + if(val >= max_power_two) + { + return max_power_two; + } + + val--; + val = (val >> 1) | val; + val = (val >> 2) | val; + val = (val >> 4) | val; + val = (val >> 8) | val; + val = (val >> 16) | val; + val++; + + return val; +} + #endif diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 18ffbdfbcd..838f6fa193 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1082,38 +1082,37 @@ void LLFloater::removeDependentFloater(LLFloater* floaterp) floaterp->mDependeeHandle = LLHandle<LLFloater>(); } -// virtual -BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index) { - if( mMinimized ) + if( mButtonsEnabled[index] ) { - // Offer the click to the close button. - if( mButtonsEnabled[BUTTON_CLOSE] ) - { - S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft; - S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom; + LLButton* my_butt = mButtons[index]; + S32 local_x = x - my_butt->getRect().mLeft; + S32 local_y = y - my_butt->getRect().mBottom; - if (mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y) - && mButtons[BUTTON_CLOSE]->handleMouseDown(local_x, local_y, mask)) - { - // close button handled it, return - return TRUE; - } - } - - // Offer the click to the restore button. - if( mButtonsEnabled[BUTTON_RESTORE] ) + if ( + my_butt->pointInView(local_x, local_y) && + my_butt->handleMouseDown(local_x, local_y, mask)) { - S32 local_x = x - mButtons[BUTTON_RESTORE]->getRect().mLeft; - S32 local_y = y - mButtons[BUTTON_RESTORE]->getRect().mBottom; - - if (mButtons[BUTTON_RESTORE]->pointInView(local_x, local_y) - && mButtons[BUTTON_RESTORE]->handleMouseDown(local_x, local_y, mask)) - { - // restore button handled it, return - return TRUE; - } + // the button handled it + return TRUE; } + } + return FALSE; +} + +// virtual +BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if( mMinimized ) + { + // Offer the click to titlebar buttons. + // Note: this block and the offerClickToButton helper method can be removed + // because the parent container will handle it for us but we'll keep it here + // for safety until after reworking the panel code to manage hidden children. + if(offerClickToButton(x, y, mask, BUTTON_CLOSE)) return TRUE; + if(offerClickToButton(x, y, mask, BUTTON_RESTORE)) return TRUE; + if(offerClickToButton(x, y, mask, BUTTON_TEAR_OFF)) return TRUE; // Otherwise pass to drag handle for movement return mDragHandle->handleMouseDown(x, y, mask); @@ -1248,6 +1247,7 @@ void LLFloater::onClickTearOff(void *userdata) LLMultiFloater* new_host = (LLMultiFloater*)self->mLastHostHandle.get(); if (new_host) { + self->setMinimized(FALSE); // to reenable minimize button if it was minimized new_host->showFloater(self); // make sure host is visible new_host->open(); @@ -1420,31 +1420,15 @@ void LLFloater::draw() void LLFloater::setCanMinimize(BOOL can_minimize) { - // removing minimize/restore button programmatically, - // go ahead and uniminimize floater + // if removing minimize/restore button programmatically, + // go ahead and unminimize floater if (!can_minimize) { setMinimized(FALSE); } - if (can_minimize) - { - if (isMinimized()) - { - mButtonsEnabled[BUTTON_MINIMIZE] = FALSE; - mButtonsEnabled[BUTTON_RESTORE] = TRUE; - } - else - { - mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; - mButtonsEnabled[BUTTON_RESTORE] = FALSE; - } - } - else - { - mButtonsEnabled[BUTTON_MINIMIZE] = FALSE; - mButtonsEnabled[BUTTON_RESTORE] = FALSE; - } + mButtonsEnabled[BUTTON_MINIMIZE] = can_minimize && !isMinimized(); + mButtonsEnabled[BUTTON_RESTORE] = can_minimize && isMinimized(); updateButtons(); } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index cb21036ef4..e467d6f921 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -151,8 +151,8 @@ public: void moveResizeHandlesToFront(); void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE); void addDependentFloater(LLHandle<LLFloater> dependent_handle, BOOL reposition = TRUE); - LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); } - void removeDependentFloater(LLFloater* dependent); + LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); } + void removeDependentFloater(LLFloater* dependent); BOOL isMinimized() { return mMinimized; } BOOL isFrontmost(); BOOL isDependent() { return !mDependeeHandle.isDead(); } @@ -221,8 +221,8 @@ protected: virtual void bringToFront(S32 x, S32 y); virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE); - void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized - const LLRect& getExpandedRect() const { return mExpandedRect; } + void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized + const LLRect& getExpandedRect() const { return mExpandedRect; } void setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened LLDragHandle* getDragHandle() const { return mDragHandle; } @@ -236,11 +236,12 @@ private: void createMinimizeButton(); void updateButtons(); void buildButtons(); + BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); LLRect mExpandedRect; LLDragHandle* mDragHandle; LLResizeBar* mResizeBar[4]; - LLResizeHandle* mResizeHandle[4]; + LLResizeHandle* mResizeHandle[4]; LLButton *mMinimizeButton; BOOL mCanTearOff; BOOL mMinimized; @@ -259,7 +260,7 @@ private: typedef std::set<LLHandle<LLFloater> > handle_set_t; typedef std::set<LLHandle<LLFloater> >::iterator handle_set_iter_t; handle_set_t mDependents; - bool mDragOnLeft; + bool mDragOnLeft; BOOL mButtonsEnabled[BUTTON_COUNT]; LLButton* mButtons[BUTTON_COUNT]; @@ -387,8 +388,8 @@ public: virtual void selectNextFloater(); virtual void selectPrevFloater(); - virtual LLFloater* getActiveFloater(); - virtual BOOL isFloaterFlashing(LLFloater* floaterp); + virtual LLFloater* getActiveFloater(); + virtual BOOL isFloaterFlashing(LLFloater* floaterp); virtual S32 getFloaterCount(); virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 0bc5bc60de..3c29795cb4 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3242,11 +3242,19 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p S32 index = columnp->mIndex; S32 width = columnp->mWidth; LLFontGL::HAlign font_alignment = columnp->mFontAlignment; - + LLColor4 fcolor = LLColor4::black; + LLSD value = (*itor)["value"]; std::string fontname = (*itor)["font"].asString(); std::string fontstyle = (*itor)["font-style"].asString(); std::string type = (*itor)["type"].asString(); + + if ((*itor).has("font-color")) + { + LLSD sd_color = (*itor)["font-color"]; + fcolor.setValue(sd_color); + } + BOOL has_color = (*itor).has("color"); LLColor4 color = ((*itor)["color"]); BOOL enabled = !(*itor).has("enabled") || (*itor)["enabled"].asBoolean() == true; @@ -3291,7 +3299,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p } else { - LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment); + LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment, fcolor, TRUE); if (has_color) { cell->setColor(color); diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index e7fc10912e..505202c48e 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -396,6 +396,12 @@ void LLSpinCtrl::setLabel(const LLStringExplicit& label) } } +void LLSpinCtrl::setAllowEdit(BOOL allow_edit) +{ + mEditor->setEnabled(allow_edit); + mAllowEdit = allow_edit; +} + void LLSpinCtrl::onTabInto() { mEditor->onTabInto(); @@ -520,6 +526,9 @@ LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * S32 label_width = llmin(40, rect.getWidth() - 40); node->getAttributeS32("label_width", label_width); + BOOL allow_text_entry = TRUE; + node->getAttributeBOOL("allow_text_entry", allow_text_entry); + LLUICtrlCallback callback = NULL; if(label.empty()) @@ -543,6 +552,7 @@ LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * spinner->setPrecision(precision); spinner->initFromXML(node, parent); + spinner->setAllowEdit(allow_text_entry); return spinner; } diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h index 1ed9462f00..a9a9ef5073 100644 --- a/indra/llui/llspinctrl.h +++ b/indra/llui/llspinctrl.h @@ -93,6 +93,7 @@ public: void setLabel(const LLStringExplicit& label); void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; } void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; } + void setAllowEdit(BOOL allow_edit); virtual void onTabInto(); @@ -134,6 +135,7 @@ private: class LLButton* mDownBtn; BOOL mbHasBeenSet; + BOOL mAllowEdit; }; #endif // LL_LLSPINCTRL_H diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index a2063358bd..b70ad4c53c 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -257,6 +257,7 @@ LLTextEditor::LLTextEditor( mIsSelecting( FALSE ), mSelectionStart( 0 ), mSelectionEnd( 0 ), + mScrolledToBottom( FALSE ), mOnScrollEndCallback( NULL ), mOnScrollEndData( NULL ), mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ), @@ -3361,20 +3362,26 @@ void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent) { LLView::reshape( width, height, called_from_parent ); - // if scrolled to bottom, stay at bottom - // unless user is editing text - if (mScrolledToBottom && mTrackBottom && !hasFocus()) - { - endOfDoc(); - } - + // do this first after reshape, because other things depend on + // up-to-date mTextRect updateTextRect(); + + updateLineStartList(); + + // propagate shape information to scrollbar + mScrollbar->setDocSize( getLineCount() ); S32 line_height = llround( mGLFont->getLineHeight() ); S32 page_lines = mTextRect.getHeight() / line_height; mScrollbar->setPageSize( page_lines ); - updateLineStartList(); + // if scrolled to bottom, stay at bottom + // unless user is editing text + // do this after updating page size + if (mScrolledToBottom && mTrackBottom && !hasFocus()) + { + endOfDoc(); + } } void LLTextEditor::autoIndent() @@ -3540,6 +3547,10 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool { mSelectionStart = selection_start; mSelectionEnd = selection_end; + + + + mIsSelecting = was_selecting; setCursorPos(cursor_pos); } @@ -3556,6 +3567,14 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool { blockUndo(); } + + // if scrolled to bottom, stay at bottom + // unless user is editing text + // do this after updating page size + if (mScrolledToBottom && mTrackBottom && !hasFocus()) + { + endOfDoc(); + } } void LLTextEditor::removeTextFromEnd(S32 num_chars) diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 23030b559d..42a9144d58 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -64,7 +64,10 @@ extern "C" { extern BOOL gDebugWindowProc; -const S32 MAX_NUM_RESOLUTIONS = 32; +const S32 MAX_NUM_RESOLUTIONS = 200; + +// static variable for ATI mouse cursor crash work-around: +static bool ATIbug = false; // // LLWindowSDL @@ -1735,7 +1738,7 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso if ( (modes != NULL) && (modes != ((SDL_Rect **) -1)) ) { int count = 0; - while (*modes) // they're sorted biggest to smallest, so find end... + while (*modes && count<MAX_NUM_RESOLUTIONS) // they're sorted biggest to smallest, so find end... { modes++; count++; @@ -2275,6 +2278,12 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty void LLWindowSDL::setCursor(ECursorType cursor) { + if (ATIbug) { + // cursor-updating is very flaky when this bug is + // present; do nothing. + return; + } + if (mCurrentCursor != cursor) { if (cursor < UI_CURSOR_COUNT) @@ -2347,6 +2356,11 @@ void LLWindowSDL::initCursors() mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0); mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromBMP("toolmediaopen.BMP",0,0); mSDLCursors[UI_CURSOR_PIPETTE] = makeSDLCursorFromBMP("lltoolpipette.BMP",2,28); + + if (getenv("LL_ATI_MOUSE_CURSOR_BUG") != NULL) { + llinfos << "Disabling cursor updating due to LL_ATI_MOUSE_CURSOR_BUG" << llendl; + ATIbug = true; + } } void LLWindowSDL::quitCursors() diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e185d96c98..0269e25658 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1079,16 +1079,16 @@ <real>0.5</real> </map> <key>ChatFontSize</key> - <map> - <key>Comment</key> - <string>Size of chat text in chat console (0 = small, 1 = big)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>1</integer> - </map> + <map> + <key>Comment</key> + <string>Size of chat text in chat console (0 = small, 1 = medium, 2 = big)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>1</integer> + </map> <key>ChatFullWidth</key> <map> <key>Comment</key> @@ -1123,16 +1123,16 @@ <integer>1</integer> </map> <key>ChatPersistTime</key> - <map> - <key>Comment</key> - <string>Time for which chat stays visible in console (seconds)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>15.0</real> - </map> + <map> + <key>Comment</key> + <string>Time for which chat stays visible in console (seconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>20</real> + </map> <key>ChatShowTimestamps</key> <map> <key>Comment</key> @@ -1856,16 +1856,16 @@ <integer>0</integer> </map> <key>ConsoleBackgroundOpacity</key> - <map> - <key>Comment</key> - <string>Opacity of chat console (0.0 = completely transparent, 1.0 = completely opaque)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.40000000596</real> - </map> + <map> + <key>Comment</key> + <string>Opacity of chat console (0.0 = completely transparent, 1.0 = completely opaque)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.700</real> + </map> <key>ConsoleBufferSize</key> <map> <key>Comment</key> @@ -5046,21 +5046,21 @@ <integer>0</integer> </map> <key>ObjectChatColor</key> - <map> - <key>Comment</key> - <string>Color of chat messages from objects</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Color4</string> - <key>Value</key> - <array> - <real>0.699999988079</real> - <real>0.899999976158</real> - <real>0.699999988079</real> - <real>1.0</real> - </array> - </map> + <map> + <key>Comment</key> + <string>Color of chat messages from objects</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Color4</string> + <key>Value</key> + <array> + <real>1</real> + <real>0.5</real> + <real>0.0</real> + <real>1</real> + </array> + </map> <key>OpenDebugStatAdvanced</key> <map> <key>Comment</key> @@ -5599,6 +5599,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>LandBrushForce</key> + <map> + <key>Comment</key> + <string>Multiplier for land modification brush force.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> <key>RecentItemsSortOrder</key> <map> <key>Comment</key> @@ -6999,16 +7010,16 @@ <integer>1</integer> </map> <key>ShowObjectUpdates</key> - <map> - <key>Comment</key> - <string>Show when update messages are received for individual objects</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> + <map> + <key>Comment</key> + <string>Show when update messages are received for individual objects</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>ShowOverlayTitle</key> <map> <key>Comment</key> @@ -7346,6 +7357,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>SnapshotFormat</key> + <map> + <key>Comment</key> + <string>Save snapshots in this format (0 = PNG, 1 = JPEG, 2 = BMP)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>SnapshotPostcardLastResolution</key> <map> <key>Comment</key> diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index eaa2f61dce..9d2e06b31e 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -33,6 +33,11 @@ ## LL_GL_BLACKLIST which solves your problems. #export LL_GL_BLACKLIST=abcdefghijklmno +## - Some ATI/Radeon users report random X server crashes when the mouse +## cursor changes shape. If you suspect that you are a victim of this +## driver bug, try enabling this option and report whether it helps: +#export LL_ATI_MOUSE_CURSOR_BUG=x + ## Everything below this line is just for advanced troubleshooters. ##------------------------------------------------------------------- @@ -56,6 +61,12 @@ if [ "$GTK_IM_MODULE" = "scim" ]; then export GTK_IM_MODULE=xim fi +## - Automatically work around the ATI mouse cursor crash bug: +## (this workaround is disabled as most fglrx users do not see the bug) +#if lsmod | grep fglrx &>/dev/null ; then +# export LL_ATI_MOUSE_CURSOR_BUG=x +#fi + ## Nothing worth editing below this line. ##------------------------------------------------------------------- diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e926e97f76..7fb9e57507 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -6438,20 +6438,9 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void { // We should only receive this message a single time. Ignore subsequent AgentWearablesUpdates // that may result from AgentWearablesRequest having been sent more than once. - static BOOL first = TRUE; - if( first ) - { - first = FALSE; - } - else - { - return; - } - - if (gNoRender) - { - return; - } + static bool first = true; + if (!first) return; + first = false; LLUUID agent_id; gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); @@ -6467,16 +6456,6 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void // Transitional state. Avatars should always have at least their body parts (hair, eyes, shape and skin). // The fact that they don't have any here (only a dummy is sent) implies that this account existed // before we had wearables, or that the database has gotten messed up. - // Deal with this by creating new body parts. - //avatar->createStandardWearables(); - - // no, deal with it by noting that we need to choose a - // gender, but only if an initial outfit load isn't happening. - // This whole check (num_wearables < 4) can probably be deleted. JC - if (gInitialOutfit.empty()) - { - gAgent.setGenderChosen(FALSE); - } return; } diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp index dc160a29ac..ebd708736e 100644 --- a/indra/newview/lldebugview.cpp +++ b/indra/newview/lldebugview.cpp @@ -60,7 +60,7 @@ LLDebugView::LLDebugView(const std::string& name, const LLRect &rect) { LLRect r; - r.set(0, rect.getHeight() - 100, rect.getWidth()/2, 100); + r.set(10, rect.getHeight() - 100, rect.getWidth()/2, 100); mDebugConsolep = new LLConsole("debug console", 20, r, -1, 0.f ); mDebugConsolep->setFollowsBottom(); mDebugConsolep->setFollowsLeft(); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 344917150f..0f180472fd 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -357,6 +357,26 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename) L"Bitmap Images (*.bmp)\0*.bmp\0" \ L"\0"; break; + case FFSAVE_PNG: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"png"; + mOFN.lpstrFilter = + L"PNG Images (*.png)\0*.png\0" \ + L"\0"; + break; + case FFSAVE_JPEG: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.jpeg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"jpeg"; + mOFN.lpstrFilter = + L"JPEG Images (*.jpeg)\0*.jpeg\0" \ + L"\0"; + break; case FFSAVE_AVI: if (filename.empty()) { @@ -642,7 +662,16 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& fi creator = 'prvw'; extension = CFSTR(".bmp"); break; - + case FFSAVE_JPEG: + type = 'JPEG'; + creator = 'prvw'; + extension = CFSTR(".jpeg"); + break; + case FFSAVE_PNG: + type = 'PNG '; + creator = 'prvw'; + extension = CFSTR(".png"); + break; case FFSAVE_AVI: type = '\?\?\?\?'; creator = '\?\?\?\?'; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 012524a541..83a9357523 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -107,6 +107,8 @@ public: FFSAVE_COLLADA = 10, FFSAVE_RAW = 11, FFSAVE_J2C = 12, + FFSAVE_PNG = 13, + FFSAVE_JPEG = 14, }; // open the dialog. This is a modal operation diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 58ad07c5bb..5dfbee73a4 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -434,7 +434,7 @@ void LLPanelLandGeneral::refresh() mEditName->setText(LLStringUtil::null); mEditDesc->setEnabled(FALSE); - mEditDesc->setText(LLStringUtil::null); + mEditDesc->setText(getString("no_selection_text")); mTextSalePending->setText(LLStringUtil::null); mTextSalePending->setEnabled(FALSE); @@ -1430,6 +1430,7 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo LLUUID owner_id; BOOL is_group_owned; S32 object_count; + U32 most_recent_time = 0; BOOL is_online; std::string object_count_str; //BOOL b_need_refresh = FALSE; @@ -1447,7 +1448,10 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo msg->getBOOLFast(_PREHASH_Data, _PREHASH_IsGroupOwned, is_group_owned, i); msg->getS32Fast (_PREHASH_Data, _PREHASH_Count, object_count, i); msg->getBOOLFast(_PREHASH_Data, _PREHASH_OnlineStatus, is_online, i); - + if(msg->getNumberOfBlocks("DataExtended")) + { + msg->getU32("DataExtended", "TimeStamp", most_recent_time, i); + } if (owner_id.isNull()) { continue; @@ -1474,6 +1478,9 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo object_count_str = llformat("%d", object_count); row->addColumn(object_count_str, FONT); + + row->addColumn(formatted_time((time_t)most_recent_time), FONT); + if (is_group_owned) { @@ -2165,7 +2172,6 @@ LLPanelLandAccess::LLPanelLandAccess(LLParcelSelectionHandle& parcel) } - BOOL LLPanelLandAccess::postBuild() { childSetCommitCallback("public_access", onCommitPublicAccess, this); @@ -2427,12 +2433,14 @@ void LLPanelLandAccess::refresh_ui() childSetEnabled("AccessList", can_manage_allowed); S32 allowed_list_count = parcel->mAccessList.size(); childSetEnabled("add_allowed", can_manage_allowed && allowed_list_count < PARCEL_MAX_ACCESS_LIST); - childSetEnabled("remove_allowed", can_manage_allowed && allowed_list_count > 0); + BOOL has_selected = mListAccess->getSelectionInterface()->getFirstSelectedIndex() >= 0; + childSetEnabled("remove_allowed", can_manage_allowed && has_selected); childSetEnabled("BannedList", can_manage_banned); S32 banned_list_count = parcel->mBanList.size(); childSetEnabled("add_banned", can_manage_banned && banned_list_count < PARCEL_MAX_ACCESS_LIST); - childSetEnabled("remove_banned", can_manage_banned && banned_list_count > 0); + has_selected = mListBanned->getSelectionInterface()->getFirstSelectedIndex() >= 0; + childSetEnabled("remove_banned", can_manage_banned && has_selected); } } diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index fc3c0952cb..3b2fb43f61 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -816,8 +816,7 @@ BOOL LLPanelRegionDebugInfo::postBuild() initHelpBtn("restart_help", "HelpRegionRestart"); childSetAction("choose_avatar_btn", onClickChooseAvatar, this); - childSetAction("return_scripted_other_land_btn", onClickReturnScriptedOtherLand, this); - childSetAction("return_scripted_all_btn", onClickReturnScriptedAll, this); + childSetAction("return_btn", onClickReturn, this); childSetAction("top_colliders_btn", onClickTopColliders, this); childSetAction("top_scripts_btn", onClickTopScripts, this); childSetAction("restart_btn", onClickRestart, this); @@ -832,10 +831,13 @@ bool LLPanelRegionDebugInfo::refreshFromRegion(LLViewerRegion* region) BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); setCtrlsEnabled(allow_modify); childDisable("apply_btn"); - + childDisable("target_avatar_name"); + childSetEnabled("choose_avatar_btn", allow_modify); - childSetEnabled("return_scripted_other_land_btn", allow_modify && !mTargetAvatar.isNull()); - childSetEnabled("return_scripted_all_btn", allow_modify && !mTargetAvatar.isNull()); + childSetEnabled("return_scripts", allow_modify && !mTargetAvatar.isNull()); + childSetEnabled("return_other_land", allow_modify && !mTargetAvatar.isNull()); + childSetEnabled("return_estate_wide", allow_modify && !mTargetAvatar.isNull()); + childSetEnabled("return_btn", allow_modify && !mTargetAvatar.isNull()); childSetEnabled("top_colliders_btn", allow_modify); childSetEnabled("top_scripts_btn", allow_modify); childSetEnabled("restart_btn", allow_modify); @@ -881,61 +883,56 @@ void LLPanelRegionDebugInfo::callbackAvatarID(const std::vector<std::string>& na } // static -void LLPanelRegionDebugInfo::onClickReturnScriptedOtherLand(void* data) +void LLPanelRegionDebugInfo::onClickReturn(void* data) { LLPanelRegionDebugInfo* panelp = (LLPanelRegionDebugInfo*) data; if (panelp->mTargetAvatar.isNull()) return; LLStringUtil::format_map_t args; args["[USER_NAME]"] = panelp->childGetValue("target_avatar_name").asString(); - gViewerWindow->alertXml("ReturnScriptedOnOthersLand", args, callbackReturnScriptedOtherLand, data); + gViewerWindow->alertXml("EstateObjectReturn", args, callbackReturn, data); } // static -void LLPanelRegionDebugInfo::callbackReturnScriptedOtherLand( S32 option, void* userdata ) +void LLPanelRegionDebugInfo::callbackReturn( S32 option, void* userdata ) { if (option != 0) return; LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*) userdata; if (!self->mTargetAvatar.isNull()) { - U32 flags = 0; - flags = flags | SWD_OTHERS_LAND_ONLY; - flags = flags | SWD_ALWAYS_RETURN_OBJECTS; - flags |= SWD_SCRIPTED_ONLY; - - send_sim_wide_deletes(self->mTargetAvatar, flags); - } -} + U32 flags = SWD_ALWAYS_RETURN_OBJECTS; -// static -void LLPanelRegionDebugInfo::onClickReturnScriptedAll(void* data) -{ - LLPanelRegionDebugInfo* panelp = (LLPanelRegionDebugInfo*) data; - if (panelp->mTargetAvatar.isNull()) return; - - - LLStringUtil::format_map_t args; - args["[USER_NAME]"] = panelp->childGetValue("target_avatar_name").asString(); - gViewerWindow->alertXml("ReturnScriptedOnAllLand", args, callbackReturnScriptedAll, data); -} - -// static -void LLPanelRegionDebugInfo::callbackReturnScriptedAll( S32 option, void* userdata ) -{ - if (option != 0) return; + if (self->childGetValue("return_scripts").asBoolean()) + { + flags |= SWD_SCRIPTED_ONLY; + } + + if (self->childGetValue("return_other_land").asBoolean()) + { + flags |= SWD_OTHERS_LAND_ONLY; + } - LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*) userdata; - if (!self->mTargetAvatar.isNull()) - { - U32 flags = 0; - flags |= SWD_ALWAYS_RETURN_OBJECTS; - flags |= SWD_SCRIPTED_ONLY; + if (self->childGetValue("return_estate_wide").asBoolean()) + { + // send as estate message - routed by spaceserver to all regions in estate + strings_t strings; + strings.push_back(llformat("%d", flags)); + strings.push_back(self->mTargetAvatar.asString()); - send_sim_wide_deletes(self->mTargetAvatar, flags); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + + self->sendEstateOwnerMessage(gMessageSystem, "estateobjectreturn", invoice, strings); + } + else + { + // send to this simulator only + send_sim_wide_deletes(self->mTargetAvatar, flags); + } } } + // static void LLPanelRegionDebugInfo::onClickTopColliders(void* data) { diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 7d05ffa5bc..8bcab111b5 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -186,10 +186,8 @@ protected: static void onClickChooseAvatar(void*); static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data); - static void onClickReturnScriptedOtherLand(void*); - static void callbackReturnScriptedOtherLand(S32 option, void*); - static void onClickReturnScriptedAll(void*); - static void callbackReturnScriptedAll(S32 option, void*); + static void onClickReturn(void *); + static void callbackReturn(S32 option, void*); static void onClickTopColliders(void*); static void onClickTopScripts(void*); static void onClickRestart(void* data); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 1f601e6dc1..811fc4eb03 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -68,6 +68,8 @@ #include "llgl.h" #include "llglheaders.h" #include "llimagejpeg.h" +#include "llimagepng.h" +#include "llimagebmp.h" #include "llimagej2c.h" #include "llvfile.h" #include "llvfs.h" @@ -83,7 +85,7 @@ LLSnapshotFloaterView* gSnapshotFloaterView = NULL; LLFloaterSnapshot* LLFloaterSnapshot::sInstance = NULL; -const F32 SNAPSHOT_TIME_DELAY = 1.f; +const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; F32 SHINE_TIME = 0.5f; F32 SHINE_WIDTH = 0.6f; @@ -93,6 +95,7 @@ S32 BORDER_WIDTH = 6; const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512 + ///---------------------------------------------------------------------------- /// Class LLSnapshotLivePreview ///---------------------------------------------------------------------------- @@ -103,9 +106,10 @@ public: { SNAPSHOT_POSTCARD, SNAPSHOT_TEXTURE, - SNAPSHOT_BITMAP + SNAPSHOT_LOCAL }; + LLSnapshotLivePreview(const LLRect& rect); ~LLSnapshotLivePreview(); @@ -119,6 +123,7 @@ public: S32 getMaxImageSize() {return mMaxImageSize ;} ESnapshotType getSnapshotType() const { return mSnapshotType; } + LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; } BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; } BOOL isSnapshotActive() { return mSnapshotActive; } LLImageGL* getThumbnailImage() const { return mThumbnailImage ; } @@ -133,9 +138,10 @@ public: BOOL isImageScaled(); void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } + void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } void setSnapshotQuality(S32 quality); void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } - void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE); + void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); LLFloaterPostcard* savePostcard(); void saveTexture(); BOOL saveLocal(); @@ -147,7 +153,7 @@ public: static void onIdle( void* snapshot_preview ); -protected: +private: LLColor4 mColor; LLPointer<LLImageGL> mViewerImage[2]; LLRect mImageRect[2]; @@ -165,9 +171,9 @@ protected: BOOL mThumbnailUpToDate ; S32 mCurImageIndex; - LLPointer<LLImageRaw> mRawImage; - LLPointer<LLImageRaw> mRawImageEncoded; - LLPointer<LLImageJPEG> mJPEGImage; + LLPointer<LLImageRaw> mPreviewImage; + LLPointer<LLImageRaw> mPreviewImageEncoded; + LLPointer<LLImageFormatted> mFormattedImage; LLFrameTimer mSnapshotDelayTimer; S32 mShineCountdown; LLFrameTimer mShineAnimTimer; @@ -177,6 +183,7 @@ protected: S32 mSnapshotQuality; S32 mDataSize; ESnapshotType mSnapshotType; + LLFloaterSnapshot::ESnapshotFormat mSnapshotFormat; BOOL mSnapshotUpToDate; LLFrameTimer mFallAnimTimer; LLVector3 mCameraPos; @@ -195,16 +202,17 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : LLView(std::string("snapshot_live_preview"), rect, FALSE), mColor(1.f, 0.f, 0.f, 0.5f), mCurImageIndex(0), - mRawImage(NULL), + mPreviewImage(NULL), mThumbnailImage(NULL) , - mRawImageEncoded(NULL), - mJPEGImage(NULL), + mPreviewImageEncoded(NULL), + mFormattedImage(NULL), mShineCountdown(0), mFlashAlpha(0.f), mNeedsFlash(TRUE), mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")), mDataSize(0), mSnapshotType(SNAPSHOT_POSTCARD), + mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))), mSnapshotUpToDate(FALSE), mCameraPos(LLViewerCamera::getInstance()->getOrigin()), mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), @@ -212,6 +220,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), mSnapshotSoundPlayed(false) { + setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); mSnapshotDelayTimer.setTimerExpirySec(0.0f); mSnapshotDelayTimer.start(); // gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); @@ -233,9 +242,9 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : LLSnapshotLivePreview::~LLSnapshotLivePreview() { // delete images - mRawImage = NULL; - mRawImageEncoded = NULL; - mJPEGImage = NULL; + mPreviewImage = NULL; + mPreviewImageEncoded = NULL; + mFormattedImage = NULL; // gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); sList.erase(this); @@ -293,7 +302,7 @@ BOOL LLSnapshotLivePreview::isImageScaled() return mImageScaled[mCurImageIndex]; } -void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail) +void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) { if (mSnapshotUpToDate) { @@ -333,7 +342,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail if (new_snapshot) { mSnapshotDelayTimer.start(); - mSnapshotDelayTimer.setTimerExpirySec(SNAPSHOT_TIME_DELAY); + mSnapshotDelayTimer.setTimerExpirySec(delay); } else if(new_thumbnail) { @@ -347,6 +356,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail void LLSnapshotLivePreview::setSnapshotQuality(S32 quality) { + llclamp(quality, 0, 100); if (quality != mSnapshotQuality) { mSnapshotQuality = quality; @@ -396,7 +406,7 @@ void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) void LLSnapshotLivePreview::draw() { if (mViewerImage[mCurImageIndex].notNull() && - mRawImageEncoded.notNull() && + mPreviewImageEncoded.notNull() && mSnapshotUpToDate) { LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f); @@ -685,8 +695,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) LLPointer<LLImageRaw> raw = NULL ; S32 w , h ; - w = get_nearest_power_two(mThumbnailWidth, 512) * 2 ; - h = get_nearest_power_two(mThumbnailHeight, 512) * 2 ; + w = get_lower_power_two(mThumbnailWidth, 512) * 2 ; + h = get_lower_power_two(mThumbnailHeight, 512) * 2 ; { raw = new LLImageRaw ; @@ -723,131 +733,155 @@ void LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->mCameraPos = new_camera_pos; previewp->mCameraRot = new_camera_rot; // request a new snapshot whenever the camera moves, with a time delay - previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot")); + BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot"); + previewp->updateSnapshot(autosnap, FALSE, autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); + } + + // see if it's time yet to snap the shot and bomb out otherwise. + previewp->mSnapshotActive = + (previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired()) + && !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active + if ( ! previewp->mSnapshotActive) + { + return; } - previewp->mSnapshotActive = (previewp->mSnapshotDelayTimer.getStarted() && - previewp->mSnapshotDelayTimer.hasExpired()); + // time to produce a snapshot - // don't take snapshots while ALT-zoom active - if (LLToolCamera::getInstance()->hasMouseCapture()) + if (!previewp->mPreviewImage) { - previewp->mSnapshotActive = FALSE; + previewp->mPreviewImage = new LLImageRaw; } - if (previewp->mSnapshotActive) + if (!previewp->mPreviewImageEncoded) { - if (!previewp->mRawImage) - { - previewp->mRawImage = new LLImageRaw; - } + previewp->mPreviewImageEncoded = new LLImageRaw; + } - if (!previewp->mRawImageEncoded) + previewp->setVisible(FALSE); + previewp->setEnabled(FALSE); + + previewp->getWindow()->incBusyCount(); + previewp->mImageScaled[previewp->mCurImageIndex] = FALSE; + + // grab the raw image and encode it into desired format + if(gViewerWindow->rawSnapshot( + previewp->mPreviewImage, + previewp->mWidth[previewp->mCurImageIndex], + previewp->mHeight[previewp->mCurImageIndex], + previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), + previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, + gSavedSettings.getBOOL("RenderUIInSnapshot"), + FALSE, + previewp->mSnapshotBufferType, + previewp->getMaxImageSize())) + { + previewp->mPreviewImageEncoded->resize( + previewp->mPreviewImage->getWidth(), + previewp->mPreviewImage->getHeight(), + previewp->mPreviewImage->getComponents()); + + if (!gSavedSettings.getBOOL("QuietSnapshotsToDisk")) { - previewp->mRawImageEncoded = new LLImageRaw; + // Always play the sound once, on window open. + // Don't keep playing if automatic + // updates are enabled. It's too invasive. JC + if (!previewp->mSnapshotSoundPlayed + || !gSavedSettings.getBOOL("AutoSnapshot") ) + { + gViewerWindow->playSnapshotAnimAndSound(); + previewp->mSnapshotSoundPlayed = true; + } } - - previewp->setVisible(FALSE); - previewp->setEnabled(FALSE); - previewp->getWindow()->incBusyCount(); - previewp->mImageScaled[previewp->mCurImageIndex] = FALSE; - - // do update - if(gViewerWindow->rawSnapshot(previewp->mRawImage, - previewp->mWidth[previewp->mCurImageIndex], - previewp->mHeight[previewp->mCurImageIndex], - previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), - previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, - gSavedSettings.getBOOL("RenderUIInSnapshot"), - FALSE, - previewp->mSnapshotBufferType, - previewp->getMaxImageSize())) + if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE) { - previewp->mRawImageEncoded->resize(previewp->mRawImage->getWidth(), previewp->mRawImage->getHeight(), previewp->mRawImage->getComponents()); - - if (!gSavedSettings.getBOOL("QuietSnapshotsToDisk")) + LLPointer<LLImageJ2C> formatted = new LLImageJ2C; + LLPointer<LLImageRaw> scaled = new LLImageRaw( + previewp->mPreviewImage->getData(), + previewp->mPreviewImage->getWidth(), + previewp->mPreviewImage->getHeight(), + previewp->mPreviewImage->getComponents()); + + scaled->biasedScaleToPowerOfTwo(512); + previewp->mImageScaled[previewp->mCurImageIndex] = TRUE; + if (formatted->encode(scaled, 0.f)) { - // Always play the sound once, on window open. - // Don't keep playing if automatic - // updates are enabled. It's too invasive. JC - if (!previewp->mSnapshotSoundPlayed - || !gSavedSettings.getBOOL("AutoSnapshot") ) - { - gViewerWindow->playSnapshotAnimAndSound(); - previewp->mSnapshotSoundPlayed = true; - } + previewp->mDataSize = formatted->getDataSize(); + formatted->decode(previewp->mPreviewImageEncoded, 0); } - - if (previewp->getSnapshotType() == SNAPSHOT_POSTCARD) + } + else + { + // delete any existing image + previewp->mFormattedImage = NULL; + // now create the new one of the appropriate format. + // note: postcards hardcoded to use jpeg always. + LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotType() == SNAPSHOT_POSTCARD + ? LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG : previewp->getSnapshotFormat(); + switch(format) { - // *FIX: just resize and reuse existing jpeg? - previewp->mJPEGImage = NULL; // deletes image - previewp->mJPEGImage = new LLImageJPEG(); - previewp->mJPEGImage->setEncodeQuality(llclamp(previewp->mSnapshotQuality, 0, 100)); - if (previewp->mJPEGImage->encode(previewp->mRawImage, 0.0f)) - { - previewp->mDataSize = previewp->mJPEGImage->getDataSize(); - previewp->mJPEGImage->decode(previewp->mRawImageEncoded, 0.0f); - } + case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + previewp->mFormattedImage = new LLImagePNG(); + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality); + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + previewp->mFormattedImage = new LLImageBMP(); + break; } - else if (previewp->getSnapshotType() == SNAPSHOT_TEXTURE) + if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0)) { - LLPointer<LLImageJ2C> formatted = new LLImageJ2C; - LLPointer<LLImageRaw> scaled = new LLImageRaw(previewp->mRawImage->getData(), - previewp->mRawImage->getWidth(), - previewp->mRawImage->getHeight(), - previewp->mRawImage->getComponents()); - - scaled->biasedScaleToPowerOfTwo(512); - previewp->mImageScaled[previewp->mCurImageIndex] = TRUE; - if (formatted->encode(scaled, 0.0f)) + // special case BMP to copy instead of decode otherwise decode will crash. + if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP) { - previewp->mDataSize = formatted->getDataSize(); - formatted->decode(previewp->mRawImageEncoded, 0.0f); + previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage); + } + else + { + previewp->mDataSize = previewp->mFormattedImage->getDataSize(); + previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0); } } - else - { - previewp->mRawImageEncoded->copy(previewp->mRawImage); - previewp->mDataSize = previewp->mRawImage->getDataSize(); - } + } - LLPointer<LLImageRaw> scaled = new LLImageRaw(previewp->mRawImageEncoded->getData(), - previewp->mRawImageEncoded->getWidth(), - previewp->mRawImageEncoded->getHeight(), - previewp->mRawImageEncoded->getComponents()); - - // leave original image dimensions, just scale up texture buffer - if (previewp->mRawImageEncoded->getWidth() > 1024 || previewp->mRawImageEncoded->getHeight() > 1024) - { - // go ahead and shrink image to appropriate power of 2 for display - scaled->biasedScaleToPowerOfTwo(1024); - previewp->mImageScaled[previewp->mCurImageIndex] = TRUE; - } - else - { - // expand image but keep original image data intact - scaled->expandToPowerOfTwo(1024, FALSE); - } + LLPointer<LLImageRaw> scaled = new LLImageRaw( + previewp->mPreviewImageEncoded->getData(), + previewp->mPreviewImageEncoded->getWidth(), + previewp->mPreviewImageEncoded->getHeight(), + previewp->mPreviewImageEncoded->getComponents()); + + // leave original image dimensions, just scale up texture buffer + if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) + { + // go ahead and shrink image to appropriate power of 2 for display + scaled->biasedScaleToPowerOfTwo(1024); + previewp->mImageScaled[previewp->mCurImageIndex] = TRUE; + } + else + { + // expand image but keep original image data intact + scaled->expandToPowerOfTwo(1024, FALSE); + } - previewp->mViewerImage[previewp->mCurImageIndex] = new LLImageGL(scaled, FALSE); - previewp->mViewerImage[previewp->mCurImageIndex]->setMipFilterNearest(previewp->getSnapshotType() != SNAPSHOT_TEXTURE); - LLViewerImage::bindTexture(previewp->mViewerImage[previewp->mCurImageIndex]); - previewp->mViewerImage[previewp->mCurImageIndex]->setClamp(TRUE, TRUE); + previewp->mViewerImage[previewp->mCurImageIndex] = new LLImageGL(scaled, FALSE); + previewp->mViewerImage[previewp->mCurImageIndex]->setMipFilterNearest(previewp->getSnapshotType() != SNAPSHOT_TEXTURE); + LLViewerImage::bindTexture(previewp->mViewerImage[previewp->mCurImageIndex]); + previewp->mViewerImage[previewp->mCurImageIndex]->setClamp(TRUE, TRUE); - previewp->mSnapshotUpToDate = TRUE; - previewp->generateThumbnailImage(TRUE) ; + previewp->mSnapshotUpToDate = TRUE; + previewp->generateThumbnailImage(TRUE) ; - previewp->mPosTakenGlobal = gAgent.getCameraPositionGlobal(); - previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame - } - previewp->getWindow()->decBusyCount(); - // only show fullscreen preview when in freeze frame mode - previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); - previewp->mSnapshotDelayTimer.stop(); - previewp->mSnapshotActive = FALSE; + previewp->mPosTakenGlobal = gAgent.getCameraPositionGlobal(); + previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame } + previewp->getWindow()->decBusyCount(); + // only show fullscreen preview when in freeze frame mode + previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); + previewp->mSnapshotDelayTimer.stop(); + previewp->mSnapshotActive = FALSE; + if(!previewp->getThumbnailUpToDate()) { previewp->generateThumbnailImage() ; @@ -876,11 +910,16 @@ LLFloaterPostcard* LLSnapshotLivePreview::savePostcard() image_scale.setVec(llmin(1.f, (F32)mWidth[mCurImageIndex] / (F32)getCurrentImage()->getWidth()), llmin(1.f, (F32)mHeight[mCurImageIndex] / (F32)getCurrentImage()->getHeight())); } - - LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(mJPEGImage, mViewerImage[mCurImageIndex], image_scale, mPosTakenGlobal); + LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get()); + if(!jpg) + { + llwarns << "Formatted image not a JPEG" << llendl; + return NULL; + } + LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(jpg, mViewerImage[mCurImageIndex], image_scale, mPosTakenGlobal); // relinquish lifetime of viewerimage and jpeg image to postcard floater mViewerImage[mCurImageIndex] = NULL; - mJPEGImage = NULL; + mFormattedImage = NULL; return floater; } @@ -893,10 +932,10 @@ void LLSnapshotLivePreview::saveTexture() LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); LLPointer<LLImageJ2C> formatted = new LLImageJ2C; - LLPointer<LLImageRaw> scaled = new LLImageRaw(mRawImage->getData(), - mRawImage->getWidth(), - mRawImage->getHeight(), - mRawImage->getComponents()); + LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(), + mPreviewImage->getWidth(), + mPreviewImage->getHeight(), + mPreviewImage->getComponents()); scaled->biasedScaleToPowerOfTwo(512); @@ -928,7 +967,7 @@ void LLSnapshotLivePreview::saveTexture() BOOL LLSnapshotLivePreview::saveLocal() { - return gViewerWindow->saveImageNumbered(mRawImage); + return gViewerWindow->saveImageNumbered(mFormattedImage); } ///---------------------------------------------------------------------------- @@ -951,6 +990,7 @@ public: } static void onClickDiscard(void* data); static void onClickKeep(void* data); + static void onCommitSave(LLUICtrl* ctrl, void* data); static void onClickNewSnapshot(void* data); static void onClickAutoSnap(LLUICtrl *ctrl, void* data); //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); @@ -965,6 +1005,7 @@ public: static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data); static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); static void onCommitSnapshotType(LLUICtrl* ctrl, void* data); + static void onCommitSnapshotFormat(LLUICtrl* ctrl, void* data); static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ; static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); @@ -973,12 +1014,14 @@ public: static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname); static void updateControls(LLFloaterSnapshot* floater); static void updateLayout(LLFloaterSnapshot* floater); + static void updateResolutionTextEntry(LLFloaterSnapshot* floater); static LLHandle<LLView> sPreviewHandle; static BOOL sAspectRatioCheckOff ; private: static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater); + static ESnapshotFormat getFormatIndex(LLFloaterSnapshot* floater); static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater); static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname); static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); @@ -995,6 +1038,7 @@ LLHandle<LLView> LLFloaterSnapshot::Impl::sPreviewHandle; //static BOOL LLFloaterSnapshot::Impl::sAspectRatioCheckOff = FALSE ; + // static LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater) { @@ -1013,10 +1057,28 @@ LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(LLFlo else if (id == "texture") index = LLSnapshotLivePreview::SNAPSHOT_TEXTURE; else if (id == "local") - index = LLSnapshotLivePreview::SNAPSHOT_BITMAP; + index = LLSnapshotLivePreview::SNAPSHOT_LOCAL; + return index; +} + + +// static +LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getFormatIndex(LLFloaterSnapshot* floater) +{ + ESnapshotFormat index = SNAPSHOT_FORMAT_PNG; + LLSD value = floater->childGetValue("local_format_combo"); + const std::string id = value.asString(); + if (id == "PNG") + index = SNAPSHOT_FORMAT_PNG; + else if (id == "JPEG") + index = SNAPSHOT_FORMAT_JPEG; + else if (id == "BMP") + index = SNAPSHOT_FORMAT_BMP; return index; } + + // static LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater) { @@ -1141,10 +1203,10 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) // static void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) { - BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot") ; LLRadioGroup* snapshot_type_radio = floater->getChild<LLRadioGroup>("snapshot_type_radio"); snapshot_type_radio->setSelectedIndex(gSavedSettings.getS32("LastSnapshotType")); LLSnapshotLivePreview::ESnapshotType shot_type = getTypeIndex(floater); + ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); //getFormatIndex(floater); LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); floater->childSetVisible("postcard_size_combo", FALSE); @@ -1158,114 +1220,102 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution")); combo = floater->getChild<LLComboBox>("local_size_combo"); if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution")); - - floater->childSetVisible("upload_btn", FALSE); - floater->childSetVisible("send_btn", FALSE); - floater->childSetVisible("save_btn", FALSE); - floater->childSetEnabled("keep_aspect_check", FALSE) ; + combo = floater->getChild<LLComboBox>("local_format_combo"); + if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotFormat")); + + floater->childSetVisible("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE); + floater->childSetVisible("send_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + floater->childSetVisible("save_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); + floater->childSetEnabled("keep_aspect_check", shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE && !sAspectRatioCheckOff); + floater->childSetEnabled("layer_types", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); + + BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot"); + BOOL is_local = shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL; + BOOL show_slider = + shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD + || (is_local && shot_format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + + floater->childSetVisible("more_btn", !is_advance); // the only item hidden in advanced mode + floater->childSetVisible("less_btn", is_advance); + floater->childSetVisible("type_label2", is_advance); + floater->childSetVisible("format_label", is_advance && is_local); + floater->childSetVisible("local_format_combo", is_advance && is_local); + floater->childSetVisible("layer_types", is_advance); + floater->childSetVisible("layer_type_label", is_advance); + floater->childSetVisible("snapshot_width", is_advance); + floater->childSetVisible("snapshot_height", is_advance); + floater->childSetVisible("keep_aspect_check", is_advance); + floater->childSetVisible("ui_check", is_advance); + floater->childSetVisible("hud_check", is_advance); + floater->childSetVisible("keep_open_check", is_advance); + floater->childSetVisible("freeze_frame_check", is_advance); + floater->childSetVisible("auto_snapshot_check", is_advance); + floater->childSetVisible("image_quality_slider", is_advance && show_slider); switch(shot_type) { case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; floater->childSetValue("layer_types", "colors"); - floater->childSetEnabled("layer_types", FALSE); - if(is_advance) { - floater->childSetEnabled("image_quality_slider", TRUE); setResolution(floater, "postcard_size_combo"); - - if(!sAspectRatioCheckOff) - { - floater->childSetEnabled("keep_aspect_check", TRUE) ; - } } - - floater->childSetVisible("send_btn", TRUE); break; case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; floater->childSetValue("layer_types", "colors"); - floater->childSetEnabled("layer_types", FALSE); - floater->childSetEnabled("image_quality_slider", FALSE); - if(is_advance) { setResolution(floater, "texture_size_combo"); } - - floater->childSetVisible("upload_btn", TRUE); break; - case LLSnapshotLivePreview::SNAPSHOT_BITMAP: - floater->childSetEnabled("layer_types", TRUE); - floater->childSetEnabled("image_quality_slider", FALSE); - + case LLSnapshotLivePreview::SNAPSHOT_LOCAL: if(is_advance) { setResolution(floater, "local_size_combo"); - - if(!sAspectRatioCheckOff) - { - floater->childSetEnabled("keep_aspect_check", TRUE) ; - } } - - floater->childSetVisible("save_btn", TRUE); break; default: break; } - if(is_advance) - { - floater->childSetVisible("type_label2", TRUE) ; - floater->childSetVisible("layer_types", TRUE) ; - floater->childSetVisible("layer_type_label", TRUE) ; - floater->childSetVisible("snapshot_width", TRUE) ; - floater->childSetVisible("snapshot_height", TRUE) ; - floater->childSetVisible("keep_aspect_check", TRUE) ; - floater->childSetVisible("ui_check", TRUE) ; - floater->childSetVisible("hud_check", TRUE) ; - floater->childSetVisible("keep_open_check", TRUE) ; - floater->childSetVisible("freeze_frame_check", TRUE) ; - floater->childSetVisible("auto_snapshot_check", TRUE) ; - floater->childSetVisible("image_quality_slider", TRUE); - floater->childSetVisible("more_btn", FALSE); - floater->childSetVisible("less_btn", TRUE); - } - else - { - floater->childSetVisible("type_label2", FALSE) ; - floater->childSetVisible("layer_types", FALSE) ; - floater->childSetVisible("layer_type_label", FALSE) ; - floater->childSetVisible("snapshot_width", FALSE) ; - floater->childSetVisible("snapshot_height", FALSE) ; - floater->childSetVisible("keep_aspect_check", FALSE) ; - floater->childSetVisible("ui_check", FALSE) ; - floater->childSetVisible("hud_check", FALSE) ; - floater->childSetVisible("keep_open_check", FALSE) ; - floater->childSetVisible("freeze_frame_check", FALSE) ; - floater->childSetVisible("auto_snapshot_check", FALSE) ; - floater->childSetVisible("image_quality_slider", FALSE); - floater->childSetVisible("more_btn", TRUE); - floater->childSetVisible("less_btn", FALSE); - } + updateResolutionTextEntry(floater); LLSnapshotLivePreview* previewp = getPreviewView(floater); if (previewp) { previewp->setSnapshotType(shot_type); + previewp->setSnapshotFormat(shot_format); previewp->setSnapshotBufferType(layer_type); } } // static +void LLFloaterSnapshot::Impl::updateResolutionTextEntry(LLFloaterSnapshot* floater) +{ + LLSpinCtrl* width_spinner = floater->getChild<LLSpinCtrl>("snapshot_width"); + LLSpinCtrl* height_spinner = floater->getChild<LLSpinCtrl>("snapshot_height"); + + if(getTypeIndex(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + { + width_spinner->setAllowEdit(FALSE); + height_spinner->setAllowEdit(FALSE); + } + else + { + width_spinner->setAllowEdit(TRUE); + height_spinner->setAllowEdit(TRUE); + } +} + +// static void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail) { if (previewp) - { - previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"), update_thumbnail); + { + BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot"); + previewp->updateSnapshot(autosnap, update_thumbnail, autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); } } @@ -1279,6 +1329,17 @@ void LLFloaterSnapshot::Impl::onClickDiscard(void* data) } } + +// static +void LLFloaterSnapshot::Impl::onCommitSave(LLUICtrl* ctrl, void* data) +{ + if (ctrl->getValue().asString() == "save as") + { + gViewerWindow->resetSnapshotLoc(); + } + onClickKeep(data); +} + // static void LLFloaterSnapshot::Impl::onClickKeep(void* data) { @@ -1294,7 +1355,7 @@ void LLFloaterSnapshot::Impl::onClickKeep(void* data) LLFloaterPostcard* floater = previewp->savePostcard(); // if still in snapshot mode, put postcard floater in snapshot floaterview // and link it to snapshot floater - if (!gSavedSettings.getBOOL("CloseSnapshotOnKeep")) + if (floater && !gSavedSettings.getBOOL("CloseSnapshotOnKeep")) { gFloaterView->removeChild(floater); gSnapshotFloaterView->addChild(floater); @@ -1610,6 +1671,22 @@ void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data) } } + +//static +void LLFloaterSnapshot::Impl::onCommitSnapshotFormat(LLUICtrl* ctrl, void* data) +{ + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) + { + gSavedSettings.setS32("SnapshotFormat", getFormatIndex(view)); + getPreviewView(view)->updateSnapshot(TRUE); + updateControls(view); + } +} + + + + // static void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname) { @@ -1642,9 +1719,21 @@ BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3 height = max_value ; } - //round to nearest power of 2 - width = get_nearest_power_two(width, MAX_TEXTURE_SIZE) ; - height = get_nearest_power_two(height, MAX_TEXTURE_SIZE) ; + //round to nearest power of 2 based on the direction of movement + // i.e. higher power of two if increasing texture resolution + if(gSavedSettings.getS32("LastSnapshotWidth") < width || + gSavedSettings.getS32("LastSnapshotHeight") < height) + { + // Up arrow pressed + width = get_next_power_two(width, MAX_TEXTURE_SIZE) ; + height = get_next_power_two(height, MAX_TEXTURE_SIZE) ; + } + else + { + // Down or no change + width = get_lower_power_two(width, MAX_TEXTURE_SIZE) ; + height = get_lower_power_two(height, MAX_TEXTURE_SIZE) ; + } } else if(previewp && previewp->mKeepAspectRatio) { @@ -1716,9 +1805,6 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat S32 w = llfloor((F32)view->childGetValue("snapshot_width").asReal()); S32 h = llfloor((F32)view->childGetValue("snapshot_height").asReal()); - gSavedSettings.setS32("LastSnapshotWidth", w); - gSavedSettings.setS32("LastSnapshotHeight", h); - LLSnapshotLivePreview* previewp = getPreviewView(view); if (previewp) { @@ -1750,7 +1836,10 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat } previewp->setMaxImageSize((S32)((LLSpinCtrl *)ctrl)->getMaxValue()) ; - if(checkImageSize(previewp, w, h, w != curw, previewp->getMaxImageSize()) || update_) + + // Check image size changes the value of height and width + if(checkImageSize(previewp, w, h, w != curw, previewp->getMaxImageSize()) + || update_) { resetSnapshotSizeOnUI(view, w, h) ; } @@ -1762,6 +1851,10 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat comboSetCustom(view, "local_size_combo"); } } + + gSavedSettings.setS32("LastSnapshotWidth", w); + gSavedSettings.setS32("LastSnapshotHeight", h); + } } @@ -1800,6 +1893,7 @@ LLFloaterSnapshot::~LLFloaterSnapshot() BOOL LLFloaterSnapshot::postBuild() { childSetCommitCallback("snapshot_type_radio", Impl::onCommitSnapshotType, this); + childSetCommitCallback("local_format_combo", Impl::onCommitSnapshotFormat, this); childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); @@ -1813,7 +1907,7 @@ BOOL LLFloaterSnapshot::postBuild() childSetAction("upload_btn", Impl::onClickKeep, this); childSetAction("send_btn", Impl::onClickKeep, this); - childSetAction("save_btn", Impl::onClickKeep, this); + childSetCommitCallback("save_btn", Impl::onCommitSave, this); childSetAction("discard_btn", Impl::onClickDiscard, this); childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this); @@ -1860,7 +1954,7 @@ BOOL LLFloaterSnapshot::postBuild() impl.updateControls(this); - return TRUE; + return TRUE; } void LLFloaterSnapshot::draw() @@ -1922,45 +2016,6 @@ void LLFloaterSnapshot::draw() LLFloater::draw(); - // draw snapshot thumbnail if not in fullscreen preview mode - /*if (previewp && previewp->getCurrentImage() && previewp->getSnapshotUpToDate()) - { - F32 aspect = previewp->getImageAspect(); - // UI size for thumbnail - S32 max_width = getRect().getWidth() - 20; - S32 max_height = 90; - - S32 img_render_width = 0; - S32 img_render_height = 0; - if (aspect > max_width / max_height) - { - // image too wide, shrink to width - img_render_width = max_width; - img_render_height = llround((F32)max_width / aspect); - } - else - { - // image too tall, shrink to height - img_render_height = max_height; - img_render_width = llround((F32)max_height * aspect); - } - S32 image_width, image_height; - previewp->getSize(image_width, image_height); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - { - // handle case where image is only a portion of image buffer - if (!previewp->isImageScaled()) - { - glScalef(llmin(1.f, (F32)image_width / (F32)previewp->getCurrentImage()->getWidth()), llmin(1.f, (F32)image_height / (F32)previewp->getCurrentImage()->getHeight()), 1.f); - } - glMatrixMode(GL_MODELVIEW); - gl_draw_scaled_image((getRect().getWidth() - img_render_width) / 2, getRect().getHeight() - 205 + (max_height - img_render_height) / 2, img_render_width, img_render_height, previewp->getCurrentImage(), LLColor4::white); - } - glMatrixMode(GL_TEXTURE); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - }*/ if (previewp) { if(previewp->getThumbnailImage()) @@ -1990,7 +2045,6 @@ void LLFloaterSnapshot::show(void*) if (!sInstance) { sInstance = new LLFloaterSnapshot(); - LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_snapshot.xml", NULL, FALSE); //move snapshot floater to special purpose snapshotfloaterview gFloaterView->removeChild(sInstance); @@ -1998,6 +2052,14 @@ void LLFloaterSnapshot::show(void*) sInstance->impl.updateLayout(sInstance); } + else // just refresh the snapshot in the existing floater instance (DEV-12255) + { + LLSnapshotLivePreview* preview = LLFloaterSnapshot::Impl::getPreviewView(sInstance); + if(preview) + { + preview->updateSnapshot(TRUE); + } + } sInstance->open(); /* Flawfinder: ignore */ sInstance->focusFirstItem(FALSE); @@ -2023,7 +2085,10 @@ void LLFloaterSnapshot::update() } } -//============================================================================ + +///---------------------------------------------------------------------------- +/// Class LLSnapshotFloaterView +///---------------------------------------------------------------------------- LLSnapshotFloaterView::LLSnapshotFloaterView( const std::string& name, const LLRect& rect ) : LLFloaterView(name, rect) { diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index a7aee1143c..bbf5c9e40b 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -38,15 +38,23 @@ #include "llimagegl.h" #include "llcharacter.h" + class LLFloaterSnapshot : public LLFloater { public: + typedef enum e_snapshot_format + { + SNAPSHOT_FORMAT_PNG, + SNAPSHOT_FORMAT_JPEG, + SNAPSHOT_FORMAT_BMP + } ESnapshotFormat; + LLFloaterSnapshot(); virtual ~LLFloaterSnapshot(); - virtual BOOL postBuild(); - virtual void draw(); - virtual void onClose(bool app_quitting); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + /*virtual*/ void onClose(bool app_quitting); static void show(void*); static void hide(void*); @@ -79,4 +87,5 @@ public: }; extern LLSnapshotFloaterView* gSnapshotFloaterView; + #endif // LL_LLFLOATERSNAPSHOT_H diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index a8192e544c..d193685432 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -54,6 +54,7 @@ #include "llpanelvolume.h" #include "llpanelpermissions.h" #include "llselectmgr.h" +#include "llslider.h" #include "llstatusbar.h" #include "lltabcontainer.h" #include "lltextbox.h" @@ -106,6 +107,7 @@ void click_popup_rotate_reset(void*); void click_popup_rotate_right(void*); void click_popup_dozer_mode(LLUICtrl *, void *user); void click_popup_dozer_size(LLUICtrl *, void *user); +void commit_slider_dozer_force(LLUICtrl *, void*); void click_dozer_size(LLUICtrl *, void*); void click_apply_to_selection(void*); void commit_radio_zoom(LLUICtrl *, void*); @@ -308,6 +310,12 @@ BOOL LLFloaterTools::postBuild() childSetAction("button apply to selection",click_apply_to_selection, (void*)0); mCheckShowOwners = getChild<LLCheckBoxCtrl>("checkbox show owners"); childSetValue("checkbox show owners",gSavedSettings.getBOOL("ShowParcelOwners")); + + mSliderDozerForce = getChild<LLSlider>("slider force"); + childSetCommitCallback("slider force",commit_slider_dozer_force, (void*)0); + // the setting stores the actual force multiplier, but the slider is logarithmic, so we convert here + childSetValue( "slider force", log10(gSavedSettings.getF32("LandBrushForce"))); + childSetAction("button more", click_show_more, this); childSetAction("button less", click_show_more, this); mTab = getChild<LLTabContainer>("Object Info Tabs"); @@ -741,6 +749,11 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) { mCheckShowOwners ->setVisible( land_visible ); } + if (mSliderDozerForce) + { + mSliderDozerForce ->setVisible( land_visible ); + childSetVisible("Strength:", land_visible); + } // // More panel visibility @@ -939,6 +952,16 @@ void click_dozer_size(LLUICtrl *ctrl, void *user) gSavedSettings.setS32("RadioLandBrushSize", size); } +void commit_slider_dozer_force(LLUICtrl *ctrl, void*) +{ + // the slider is logarithmic, so we exponentiate to get the actual force multiplier + F32 dozer_force = pow(10.f, (F32)ctrl->getValue().asReal()); + gSavedSettings.setF32("LandBrushForce", dozer_force); +} + + + + void click_apply_to_selection(void* user) { LLToolBrushLand::getInstance()->modifyLandInSelectionGlobal(); diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index a6fdc76d9f..81e40c0408 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -48,6 +48,7 @@ class LLPanelContents; class LLPanelFace; class LLPanelLandInfo; class LLComboBox; +class LLSlider; class LLParcelSelection; class LLObjectSelection; @@ -167,6 +168,7 @@ public: LLCheckBoxCtrl *mRadioDozerSmooth; LLCheckBoxCtrl *mRadioDozerNoise; LLCheckBoxCtrl *mRadioDozerRevert; + LLSlider *mSliderDozerForce; LLComboBox *mComboDozerSize; LLButton *mBtnApplyToSelection; diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 93622ed94e..3c1b89d04b 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -44,6 +44,7 @@ #include "lllineeditor.h" #include "lltextbox.h" #include "lltracker.h" +#include "llviewermessage.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "lluictrlfactory.h" @@ -51,6 +52,8 @@ LLFloaterTopObjects* LLFloaterTopObjects::sInstance = NULL; +// Globals +// const U32 TIME_STR_LENGTH = 30; // static void LLFloaterTopObjects::show() @@ -161,6 +164,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) for (S32 block = 0; block < block_count; ++block) { U32 task_local_id; + U32 time_stamp = 0; LLUUID task_id; F32 location_x, location_y, location_z; F32 score; @@ -175,7 +179,11 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) msg->getF32Fast(_PREHASH_ReportData, _PREHASH_Score, score, block); msg->getStringFast(_PREHASH_ReportData, _PREHASH_TaskName, name_buf, block); msg->getStringFast(_PREHASH_ReportData, _PREHASH_OwnerName, owner_buf, block); - + if(msg->getNumberOfBlocks("DataExtended")) + { + msg->getU32("DataExtended", "TimeStamp", time_stamp, block); + } + LLSD element; element["id"] = task_id; @@ -193,7 +201,10 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) element["columns"][3]["column"] = "location"; element["columns"][3]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z); element["columns"][3]["font"] = "SANSSERIF"; - + element["columns"][3]["column"] = "time"; + element["columns"][3]["value"] = formatted_time((time_t)time_stamp); + element["columns"][3]["font"] = "SANSSERIF"; + list->addElement(element); mObjectListData.append(element); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 9d8641eb2f..a88a6bbffe 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1644,12 +1644,13 @@ BOOL LLFloaterIMPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if(drop) { LLToolDragAndDrop::giveInventory(mOtherParticipantUUID, inv_item); + LLStringUtil::format_map_t args; + gIMMgr->addSystemMessage(mSessionUUID, "inventory_item_offered", args); } } } break; } - default: break; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index ada8ab5fdc..60e6197bf7 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -209,8 +209,8 @@ static LLHost gAgentSimHost; static BOOL gSkipOptionalUpdate = FALSE; static bool gGotUseCircuitCodeAck = false; -std::string gInitialOutfit; -std::string gInitialOutfitGender; // "male" or "female" +static std::string sInitialOutfit; +static std::string sInitialOutfitGender; // "male" or "female" static bool gUseCircuitCallbackCalled = false; @@ -348,8 +348,6 @@ BOOL idle_startup() static BOOL samename = FALSE; - BOOL do_normal_idle = FALSE; - // HACK: These are things from the main loop that usually aren't done // until initialization is complete, but need to be done here for things // to work. @@ -634,34 +632,26 @@ BOOL idle_startup() // Go to the next startup state - LLStartUp::setStartupState( STATE_MEDIA_INIT ); - return do_normal_idle; + LLStartUp::setStartupState( STATE_BROWSER_INIT ); + return FALSE; } - //--------------------------------------------------------------------- - // LLMediaEngine Init - //--------------------------------------------------------------------- - if (STATE_MEDIA_INIT == LLStartUp::getStartupState()) + if (STATE_BROWSER_INIT == LLStartUp::getStartupState()) { - LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL; - set_startup_status(0.03f, "Initializing Multimedia...", gAgent.mMOTD); + LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL; + std::string msg = LLTrans::getString("LoginInitializingBrowser"); + set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); display_startup(); - LLViewerMedia::initClass(); - LLViewerParcelMedia::initClass(); - - if (gViewerWindow) - { - audio_update_volume(true); - } + LLViewerMedia::initBrowser(); LLStartUp::setStartupState( STATE_LOGIN_SHOW ); - return do_normal_idle; + return FALSE; } - if (STATE_LOGIN_SHOW == LLStartUp::getStartupState()) - { + if (STATE_LOGIN_SHOW == LLStartUp::getStartupState()) + { LL_DEBUGS("AppInit") << "Initializing Window" << LL_ENDL; gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); @@ -723,7 +713,7 @@ BOOL idle_startup() gLoginMenuBarView->setEnabled( TRUE ); timeout.reset(); - return do_normal_idle; + return FALSE; } if (STATE_LOGIN_WAIT == LLStartUp::getStartupState()) @@ -733,7 +723,7 @@ BOOL idle_startup() // Sleep so we don't spin the CPU ms_sleep(1); - return do_normal_idle; + return FALSE; } if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) @@ -894,13 +884,13 @@ BOOL idle_startup() // skipping over STATE_UPDATE_CHECK because that just waits for input LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); - return do_normal_idle; + return FALSE; } if (STATE_UPDATE_CHECK == LLStartUp::getStartupState()) { // wait for user to give input via dialog box - return do_normal_idle; + return FALSE; } if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState()) @@ -1015,7 +1005,7 @@ BOOL idle_startup() gAcceptTOS = FALSE; gAcceptCriticalMessage = FALSE; LLStartUp::setStartupState( STATE_LOGIN_NO_DATA_YET ); - return do_normal_idle; + return FALSE; } if(STATE_LOGIN_NO_DATA_YET == LLStartUp::getStartupState()) @@ -1035,12 +1025,12 @@ BOOL idle_startup() if(LLUserAuth::E_NO_RESPONSE_YET == error) { LL_DEBUGS("AppInit") << "waiting..." << LL_ENDL; - return do_normal_idle; + return FALSE; } LLStartUp::setStartupState( STATE_LOGIN_DOWNLOADING ); progress += 0.01f; set_startup_status(progress, auth_desc, auth_message); - return do_normal_idle; + return FALSE; } if(STATE_LOGIN_DOWNLOADING == LLStartUp::getStartupState()) @@ -1056,12 +1046,12 @@ BOOL idle_startup() if(LLUserAuth::E_DOWNLOADING == error) { LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL; - return do_normal_idle; + return FALSE; } LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); progress += 0.01f; set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message); - return do_normal_idle; + return FALSE; } if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) @@ -1104,7 +1094,7 @@ BOOL idle_startup() // ignoring the duration & options array for now. // Go back to authenticate. LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE ); - return do_normal_idle; + return FALSE; } else { @@ -1216,7 +1206,7 @@ BOOL idle_startup() args["[NUMBER]"] = llformat("%d", sAuthUriNum + 1); auth_desc = LLTrans::getString("LoginAttempt", args); LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE ); - return do_normal_idle; + return FALSE; } break; } @@ -1391,12 +1381,14 @@ BOOL idle_startup() it = options[0].find("folder_name"); if(it != it_end) { - gInitialOutfit = (*it).second; + // Initial outfit is a folder in your inventory, + // must be an exact folder-name match. + sInitialOutfit = (*it).second; } it = options[0].find("gender"); if (it != it_end) { - gInitialOutfitGender = (*it).second; + sInitialOutfitGender = (*it).second; } } @@ -1475,7 +1467,7 @@ BOOL idle_startup() // Don't save an incorrect password to disk. save_password_to_disk(NULL); } - return do_normal_idle; + return FALSE; } //--------------------------------------------------------------------- @@ -1533,7 +1525,6 @@ BOOL idle_startup() LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(first_sim_handle); LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; - LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT ); regionp->setSeedCapability(first_sim_seed_cap); LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; @@ -1545,16 +1536,28 @@ BOOL idle_startup() gAgent.setPositionAgent(agent_start_position_region); display_startup(); - return do_normal_idle; + LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); + return FALSE; } //--------------------------------------------------------------------- + // Load QuickTime/GStreamer and other multimedia engines, can be slow. + // Do it while we're waiting on the network for our seed capability. JC + //--------------------------------------------------------------------- + if (STATE_MULTIMEDIA_INIT == LLStartUp::getStartupState()) + { + LLStartUp::multimediaInit(); + LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT ); + return FALSE; + } + + //--------------------------------------------------------------------- // Wait for Seed Cap Grant //--------------------------------------------------------------------- if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) { - return do_normal_idle; + return FALSE; } @@ -1733,7 +1736,7 @@ BOOL idle_startup() timeout.reset(); - return do_normal_idle; + return FALSE; } //--------------------------------------------------------------------- @@ -1752,7 +1755,7 @@ BOOL idle_startup() { } msg->processAcks(); - return do_normal_idle; + return FALSE; } //--------------------------------------------------------------------- @@ -1791,7 +1794,7 @@ BOOL idle_startup() LLStartUp::setStartupState( STATE_AGENT_WAIT ); // Go to STATE_AGENT_WAIT timeout.reset(); - return do_normal_idle; + return FALSE; } //--------------------------------------------------------------------- @@ -1823,7 +1826,7 @@ BOOL idle_startup() LLStartUp::setStartupState( STATE_INVENTORY_SEND ); } - return do_normal_idle; + return FALSE; } //--------------------------------------------------------------------- @@ -2011,7 +2014,7 @@ BOOL idle_startup() } LLStartUp::setStartupState( STATE_MISC ); - return do_normal_idle; + return FALSE; } @@ -2202,26 +2205,27 @@ BOOL idle_startup() LLStartUp::setStartupState( STATE_PRECACHE ); timeout.reset(); - return do_normal_idle; + return FALSE; } if (STATE_PRECACHE == LLStartUp::getStartupState()) { - do_normal_idle = TRUE; - - // Avoid generic Ruth avatar in Orientation Island by starting - // our outfit load as soon as possible. This will be replaced - // with a more definitive patch from featurettes-4 later. JC + F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY; + + // We now have an inventory skeleton, so if this is a user's first + // login, we can start setting up their clothing and avatar + // appearance. This helps to avoid the generic "Ruth" avatar in + // the orientation island tutorial experience. JC if (gAgent.isFirstLogin() - && !gInitialOutfit.empty() // registration set up an outfit - && gAgent.getAvatarObject() // can't wear clothes until have obj - && !gAgent.isGenderChosen() ) // nothing already loaded + && !sInitialOutfit.empty() // registration set up an outfit + && !sInitialOutfitGender.empty() // and a gender + && gAgent.getAvatarObject() // can't wear clothes without object + && !gAgent.isGenderChosen() ) // nothing already loading { - llinfos << "Wearing initial outfit " << gInitialOutfit << llendl; - callback_choose_gender(-1, NULL); + // Start loading the wearables, textures, gestures + LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender ); } - F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY; // wait precache-delay and for agent's avatar or a lot longer. if(((timeout_frac > 1.f) && gAgent.getAvatarObject()) || (timeout_frac > 3.f)) @@ -2231,49 +2235,80 @@ BOOL idle_startup() else { update_texture_fetch(); - set_startup_status(0.60f + 0.20f * timeout_frac, + set_startup_status(0.60f + 0.30f * timeout_frac, "Loading world...", gAgent.mMOTD); } - return do_normal_idle; + return TRUE; } if (STATE_WEARABLES_WAIT == LLStartUp::getStartupState()) { - do_normal_idle = TRUE; - static LLFrameTimer wearables_timer; const F32 wearables_time = wearables_timer.getElapsedTimeF32(); const F32 MAX_WEARABLES_TIME = 10.f; - if(gAgent.getWearablesLoaded() || !gAgent.isGenderChosen()) + if (!gAgent.isGenderChosen()) { + // No point in waiting for clothing, we don't even + // know what gender we are. Pop a dialog to ask and + // proceed to draw the world. JC + // + // *NOTE: We might hit this case even if we have an + // initial outfit, but if the load hasn't started + // already then something is wrong so fall back + // to generic outfits. JC + gViewerWindow->alertXml("WelcomeChooseSex", + callback_choose_gender, NULL); LLStartUp::setStartupState( STATE_CLEANUP ); + return TRUE; } - else if (wearables_time > MAX_WEARABLES_TIME) + + if (wearables_time > MAX_WEARABLES_TIME) { + // It's taken too long to load, show the world gViewerWindow->alertXml("ClothingLoading"); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG); LLStartUp::setStartupState( STATE_CLEANUP ); + return TRUE; + } + + if (gAgent.isFirstLogin()) + { + // wait for avatar to be completely loaded + if (gAgent.getAvatarObject() + && gAgent.getAvatarObject()->isFullyLoaded()) + { + //llinfos << "avatar fully loaded" << llendl; + LLStartUp::setStartupState( STATE_CLEANUP ); + return TRUE; + } } else { - update_texture_fetch(); - set_startup_status(0.80f + 0.20f * wearables_time / MAX_WEARABLES_TIME, - LLTrans::getString("LoginDownloadingClothing"), - gAgent.mMOTD); + // OK to just get the wearables + if ( gAgent.getWearablesLoaded() ) + { + // We have our clothing, proceed. + //llinfos << "wearables loaded" << llendl; + LLStartUp::setStartupState( STATE_CLEANUP ); + return TRUE; + } } - return do_normal_idle; + + update_texture_fetch(); + set_startup_status(0.9f + 0.1f * wearables_time / MAX_WEARABLES_TIME, + LLTrans::getString("LoginDownloadingClothing").c_str(), + gAgent.mMOTD.c_str()); + return TRUE; } if (STATE_CLEANUP == LLStartUp::getStartupState()) { set_startup_status(1.0, "", ""); - do_normal_idle = TRUE; - // Let the map know about the inventory. if(gFloaterWorldMap) { @@ -2299,9 +2334,6 @@ BOOL idle_startup() gAgent.requestEnterGodMode(); } - // On first start, ask user for gender - dialog_choose_gender_first_start(); - // Start automatic replay if the flag is set. if (gSavedSettings.getBOOL("StatsAutoRun")) { @@ -2335,11 +2367,11 @@ BOOL idle_startup() LLAppViewer::instance()->initMainloopTimeout("Mainloop Init"); - return do_normal_idle; + return TRUE; } LL_WARNS("AppInit") << "Reached end of idle_startup for state " << LLStartUp::getStartupState() << LL_ENDL; - return do_normal_idle; + return TRUE; } // @@ -3548,55 +3580,47 @@ const std::string MALE_GESTURES_FOLDER = "Male Gestures"; const std::string FEMALE_GESTURES_FOLDER = "Female Gestures"; const std::string MALE_OUTFIT_FOLDER = "Male Shape & Outfit"; const std::string FEMALE_OUTFIT_FOLDER = "Female Shape & Outfit"; -const S32 OPT_USE_INITIAL_OUTFIT = -2; const S32 OPT_CLOSED_WINDOW = -1; const S32 OPT_MALE = 0; const S32 OPT_FEMALE = 1; void callback_choose_gender(S32 option, void* userdata) { - S32 gender = OPT_FEMALE; - std::string outfit; + switch(option) + { + case OPT_MALE: + LLStartUp::loadInitialOutfit( MALE_OUTFIT_FOLDER, "male" ); + break; + + case OPT_FEMALE: + case OPT_CLOSED_WINDOW: + default: + LLStartUp::loadInitialOutfit( FEMALE_OUTFIT_FOLDER, "female" ); + break; + } +} + +void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, + const std::string& gender_name ) +{ + S32 gender = 0; std::string gestures; - if (!gInitialOutfit.empty()) + if (gender_name == "male") { - outfit = gInitialOutfit; - if (gInitialOutfitGender == "male") - { - gender = OPT_MALE; - gestures = MALE_GESTURES_FOLDER; - } - else - { - gender = OPT_FEMALE; - gestures = FEMALE_GESTURES_FOLDER; - } + gender = OPT_MALE; + gestures = MALE_GESTURES_FOLDER; } else { - switch(option) - { - case OPT_MALE: - gender = OPT_MALE; - outfit = MALE_OUTFIT_FOLDER; - gestures = MALE_GESTURES_FOLDER; - break; - - case OPT_FEMALE: - case OPT_CLOSED_WINDOW: - default: - gender = OPT_FEMALE; - outfit = FEMALE_OUTFIT_FOLDER; - gestures = FEMALE_GESTURES_FOLDER; - break; - } + gender = OPT_FEMALE; + gestures = FEMALE_GESTURES_FOLDER; } // try to find the outfit - if not there, create some default // wearables. LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; - LLNameCategoryCollector has_name(outfit); + LLNameCategoryCollector has_name(outfit_folder_name); gInventory.collectDescendentsIf(LLUUID::null, cat_array, item_array, @@ -3608,36 +3632,16 @@ void callback_choose_gender(S32 option, void* userdata) } else { - wear_outfit_by_name(outfit); + wear_outfit_by_name(outfit_folder_name); } wear_outfit_by_name(gestures); wear_outfit_by_name(COMMON_GESTURES_FOLDER); - typedef std::map<LLUUID, LLMultiGesture*> item_map_t; - item_map_t::iterator gestureIterator; - - // Must be here so they aren't invisible if they close the window. + // This is really misnamed -- it means we have started loading + // an outfit/shape that will give the avatar a gender eventually. JC gAgent.setGenderChosen(TRUE); } - -void dialog_choose_gender_first_start() -{ - if (!gNoRender - && (!gAgent.isGenderChosen())) - { - if (!gInitialOutfit.empty()) - { - gViewerWindow->alertXml("WelcomeNoClothes", - callback_choose_gender, NULL); - } - else - { - gViewerWindow->alertXml("WelcomeChooseSex", - callback_choose_gender, NULL); - } - } -} // Loads a bitmap to display during load // location_id = 0 => last position @@ -3736,6 +3740,19 @@ bool LLStartUp::canGoFullscreen() return gStartupState >= STATE_WORLD_INIT; } +// Initialize all plug-ins except the web browser (which was initialized +// early, before the login screen). JC +void LLStartUp::multimediaInit() +{ + LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL; + std::string msg = LLTrans::getString("LoginInitializingMultimedia"); + set_startup_status(0.50f, msg.c_str(), gAgent.mMOTD.c_str()); + display_startup(); + + LLViewerMedia::initClass(); + LLViewerParcelMedia::initClass(); +} + bool LLStartUp::dispatchURL() { // ok, if we've gotten this far and have a startup URL diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 38319c8d8a..ea568395d4 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -46,7 +46,7 @@ extern std::string SCREEN_LAST_FILENAME; enum EStartupState{ STATE_FIRST, // Initial startup - STATE_MEDIA_INIT, // Initialzie media library + STATE_BROWSER_INIT, // Initialize web browser for login screen STATE_LOGIN_SHOW, // Show login screen STATE_LOGIN_WAIT, // Wait for user input at login screen STATE_LOGIN_CLEANUP, // Get rid of login screen and start login @@ -57,6 +57,7 @@ enum EStartupState{ STATE_LOGIN_DOWNLOADING, // Waiting for authentication replies to download STATE_LOGIN_PROCESS_RESPONSE, // Check authentication reply STATE_WORLD_INIT, // Start building the world + STATE_MULTIMEDIA_INIT, // Init the rest of multimedia library STATE_SEED_GRANTED_WAIT, // Wait for seed cap grant STATE_SEED_CAP_GRANTED, // Have seed cap grant STATE_WORLD_WAIT, // Waiting for simulator @@ -87,6 +88,15 @@ public: static void setStartupState( S32 state ); static S32 getStartupState() { return gStartupState; }; + static void multimediaInit(); + // Initialize LLViewerMedia multimedia engine. + + // outfit_folder_name can be a folder anywhere in your inventory, + // but the name must be a case-sensitive exact match. + // gender_name is either "male" or "female" + static void loadInitialOutfit( const std::string& outfit_folder_name, + const std::string& gender_name ); + static bool dispatchURL(); // if we have a SLURL or sim string ("Ahern/123/45") that started // the viewer, dispatch it diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 421f0196e3..c522bd0697 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -910,7 +910,7 @@ LLTextureCtrl::LLTextureCtrl( mNeedsRawImageData( FALSE ), mValid( TRUE ), mDirty( FALSE ), - mShowLoadingPlaceholder( FALSE ) + mShowLoadingPlaceholder( TRUE ) { mCaption = new LLTextBox( label, LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ), @@ -1327,6 +1327,10 @@ void LLTextureCtrl::draw() mTentativeLabel->setVisible( !mTexturep.isNull() && getTentative() ); + + // Show "Loading..." string on the top left corner while this texture is loading. + // Using the discard level, do not show the string if the texture is almost but not + // fully loaded. if ( mTexturep.notNull() && (mShowLoadingPlaceholder == TRUE) && (mTexturep->getDiscardLevel() != 1) && diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp index 1b006822c1..b644e43a64 100644 --- a/indra/newview/lltoolbrush.cpp +++ b/indra/newview/lltoolbrush.cpp @@ -154,7 +154,7 @@ void LLToolBrushLand::modifyLandAtPointGlobal(const LLVector3d &pos_global, regionp->forceUpdate(); // tell the simulator what we've done - F32 seconds = 1.0f / gFPSClamped; + F32 seconds = (1.0f / gFPSClamped) * gSavedSettings.getF32("LandBrushForce"); F32 x_pos = (F32)pos_region.mV[VX]; F32 y_pos = (F32)pos_region.mV[VY]; U8 brush_size = (U8)mBrushIndex; @@ -242,7 +242,7 @@ void LLToolBrushLand::modifyLandInSelectionGlobal() min_region.clamp(0.f, regionp->getWidth()); max_region.clamp(0.f, regionp->getWidth()); - F32 seconds = 1.0f; + F32 seconds = gSavedSettings.getF32("LandBrushForce"); LLSurface &land = regionp->getLand(); char action = E_LAND_LEVEL; @@ -251,21 +251,23 @@ void LLToolBrushLand::modifyLandInSelectionGlobal() case 0: // // average toward mStartingZ action = E_LAND_LEVEL; - seconds = 1.f; + seconds *= 0.25f; break; case 1: action = E_LAND_RAISE; + seconds *= 0.25f; break; case 2: action = E_LAND_LOWER; + seconds *= 0.25f; break; case 3: action = E_LAND_SMOOTH; - seconds = 10.f; + seconds *= 5.0f; break; case 4: action = E_LAND_NOISE; - seconds = 0.5f; + seconds *= 0.5f; break; case 5: action = E_LAND_REVERT; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index f803ef3a3e..f80eb6e486 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -415,12 +415,44 @@ LLUUID LLViewerMediaImpl::getMediaTextureID() // Wrapper class ////////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////////////////// +// The viewer takes a long time to load the start screen. Part of the problem +// is media initialization -- in particular, QuickTime loads many DLLs and +// hits the disk heavily. So we initialize only the browser component before +// the login screen, then do the rest later when we have a progress bar. JC +// static +void LLViewerMedia::initBrowser() +{ + LLMediaManagerData* init_data = new LLMediaManagerData; + buildMediaManagerData( init_data ); + LLMediaManager::initBrowser( init_data ); + delete init_data; +} + ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerMedia::initClass() { LLMediaManagerData* init_data = new LLMediaManagerData; + buildMediaManagerData( init_data ); + LLMediaManager::initClass( init_data ); + delete init_data; + + LLMediaManager* mm = LLMediaManager::getInstance(); + LLMIMETypes::mime_info_map_t::const_iterator it; + for (it = LLMIMETypes::sMap.begin(); it != LLMIMETypes::sMap.end(); ++it) + { + const std::string& mime_type = it->first; + const LLMIMETypes::LLMIMEInfo& info = it->second; + mm->addMimeTypeImplNameMap( mime_type, info.mImpl ); + } +} +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::buildMediaManagerData( LLMediaManagerData* init_data ) +{ // std::string executable_dir = std::string( arg0 ).substr( 0, std::string( arg0 ).find_last_of("\\/") ); // std::string component_dir = std::string( executable_dir ).substr( 0, std::string( executable_dir ).find_last_of("\\/") ); // component_dir = std::string( component_dir ).substr( 0, std::string( component_dir ).find_last_of("\\/") ); @@ -467,17 +499,6 @@ void LLViewerMedia::initClass() std::string profile_name("Second Life"); init_data->setBrowserProfileName( profile_name ); init_data->setBrowserParentWindow( gViewerWindow->getPlatformWindow() ); - - LLMediaManager::initClass( init_data ); - - LLMediaManager* mm = LLMediaManager::getInstance(); - LLMIMETypes::mime_info_map_t::const_iterator it; - for (it = LLMIMETypes::sMap.begin(); it != LLMIMETypes::sMap.end(); ++it) - { - const std::string& mime_type = it->first; - const LLMIMETypes::LLMIMEInfo& info = it->second; - mm->addMimeTypeImplNameMap( mime_type, info.mImpl ); - } } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 67a75c7b0f..3f012fef76 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -34,11 +34,16 @@ #include "llmediabase.h" // for status codes +class LLMediaManagerData; class LLUUID; class LLViewerMedia { public: + // Special case early init for just web browser component + // so we can show login screen. See .cpp file for details. JC + static void initBrowser(); + static void initClass(); static void cleanupClass(); @@ -67,6 +72,10 @@ class LLViewerMedia static void setMimeType(std::string mime_type); static void updateImagesMediaStreams(); + + private: + // Fill in initialization data for LLMediaManager::initClass() + static void buildMediaManagerData( LLMediaManagerData* init_data ); }; #endif // LLVIEWERMEDIA_H diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 00cc94c3d3..7db03c9db4 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -436,9 +436,29 @@ class LLFileTakeSnapshotToDisk : public view_listener_t { gViewerWindow->playSnapshotAnimAndSound(); } + LLImageBase::setSizeOverride(TRUE); - gViewerWindow->saveImageNumbered(raw); + LLPointer<LLImageFormatted> formatted; + switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) + { + case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + formatted = new LLImagePNG; + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + formatted = new LLImageBMP; + break; + default: + llwarns << "Unknown Local Snapshot format" << llendl; + LLImageBase::setSizeOverride(FALSE); + return true; + } + + formatted->encode(raw, 0); LLImageBase::setSizeOverride(FALSE); + gViewerWindow->saveImageNumbered(formatted); } return true; } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 114707791b..a082d6f1b5 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1175,8 +1175,17 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) return; } + // Strip any SLURL from the message display. (DEV-2754) + std::string msg = info->mDesc; + int indx = msg.find(" ( http://slurl.com/secondlife/"); + if(indx >= 0) + { + LLStringUtil::truncate(msg, indx); + } + LLStringUtil::format_map_t args; - args["[OBJECTNAME]"] = info->mDesc; + args["[OBJECTNAME]"] = msg; + // must protect against a NULL return from lookupHumanReadable() std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType)); if (!typestr.empty()) diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index ce0fe2c836..4ab0508fba 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -122,6 +122,7 @@ //#include "llblockencoder.h" #include "llimage.h" #include "llimagebmp.h" +#include "llimagepng.h" #include "llimagej2c.h" #include "llimagejpeg.h" #include "llimagetga.h" diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b37b66effa..be9e9d4d68 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1517,7 +1517,6 @@ LLViewerWindow::LLViewerWindow( LLViewerWindow::sMovieBaseName = "SLmovie"; LLViewerWindow::sSnapshotDir.clear(); - // create window mWindow = LLWindowManager::createWindow( title, name, x, y, width, height, 0, @@ -4049,14 +4048,14 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d } // Saves an image to the harddrive as "SnapshotX" where X >= 1. -BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const std::string& extension_in) +BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) { - if (! raw) + if (!image) { return FALSE; } - std::string extension(extension_in); + std::string extension("." + image->getExtension()); if (extension.empty()) { extension = (gSavedSettings.getBOOL("CompressSnapshotsToDisk")) ? ".j2c" : ".bmp"; @@ -4067,6 +4066,10 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const std::string& exten pick_type = LLFilePicker::FFSAVE_J2C; else if (extension == ".bmp") pick_type = LLFilePicker::FFSAVE_BMP; + else if (extension == ".jpg") + pick_type = LLFilePicker::FFSAVE_JPEG; + else if (extension == ".png") + pick_type = LLFilePicker::FFSAVE_PNG; else if (extension == ".tga") pick_type = LLFilePicker::FFSAVE_TGA; else @@ -4112,22 +4115,13 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const std::string& exten } while( -1 != err ); // search until the file is not found (i.e., stat() gives an error). - LLPointer<LLImageFormatted> formatted_image = LLImageFormatted::createFromExtension(extension); - LLImageBase::setSizeOverride(TRUE); - BOOL success = formatted_image->encode(raw, 0.0f); - if( success ) - { - success = formatted_image->save(filepath); - } - else - { - llwarns << "Unable to encode bmp snapshot" << llendl; - } - LLImageBase::setSizeOverride(FALSE); - - return success; + return image->save(filepath); } +void LLViewerWindow::resetSnapshotLoc() +{ + sSnapshotDir.clear(); +} static S32 BORDERHEIGHT = 0; static S32 BORDERWIDTH = 0; @@ -4430,7 +4424,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei image_buffer_x = llfloor(snapshot_width*scale_factor) ; image_buffer_y = llfloor(snapshot_height *scale_factor) ; } - raw->resize(image_buffer_x, image_buffer_y, type == SNAPSHOT_TYPE_DEPTH ? 4 : 3); + raw->resize(image_buffer_x, image_buffer_y, 3); if(raw->isBufferInvalid()) { return FALSE ; @@ -4476,7 +4470,9 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei } else { - display(do_rebuild, scale_factor, subimage_x+(subimage_y*llceil(scale_factor)), use_fbo); + display(do_rebuild, scale_factor, subimage_x+(subimage_y*llceil(scale_factor)), TRUE); + // Required for showing the GUI in snapshots? See DEV-16350 for details. JC + render_ui_and_swap(); } S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); @@ -4485,49 +4481,43 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth()))); for(U32 out_y = 0; out_y < read_height ; out_y++) { + S32 output_buffer_offset = ( + (out_y * (raw->getWidth())) // ...plus iterated y... + + (window_width * subimage_x) // ...plus subimage start in x... + + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... + - output_buffer_offset_x // ...minus buffer padding x... + - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... + ) * raw->getComponents(); if (type == SNAPSHOT_TYPE_OBJECT_ID || type == SNAPSHOT_TYPE_COLOR) { glReadPixels( subimage_x_offset, out_y + subimage_y_offset, read_width, 1, GL_RGB, GL_UNSIGNED_BYTE, - raw->getData() + // current output pixel is beginning of buffer... - ( - (out_y * (raw->getWidth())) // ...plus iterated y... - + (window_width * subimage_x) // ...plus subimage start in x... - + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... - - output_buffer_offset_x // ...minus buffer padding x... - - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... - ) * 3 // times 3 bytes per pixel + raw->getData() + output_buffer_offset ); } else // SNAPSHOT_TYPE_DEPTH { - S32 output_buffer_offset = ( - (out_y * (raw->getWidth())) // ...plus iterated y... - + (window_width * subimage_x) // ...plus subimage start in x... - + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... - - output_buffer_offset_x // ...minus buffer padding x... - - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... - ) * 4; // times 4 bytes per pixel - + LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values glReadPixels( subimage_x_offset, out_y + subimage_y_offset, read_width, 1, GL_DEPTH_COMPONENT, GL_FLOAT, - raw->getData() + output_buffer_offset// current output pixel is beginning of buffer... + depth_line_buffer->getData()// current output pixel is beginning of buffer... ); - for (S32 i = output_buffer_offset; i < output_buffer_offset + (S32)read_width * 4; i += 4) + for (S32 i = 0; i < (S32)read_width; i++) { - F32 depth_float = *(F32*)(raw->getData() + i); + F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32))); F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); - *(raw->getData() + i + 0) = depth_byte; - *(raw->getData() + i + 1) = depth_byte; - *(raw->getData() + i + 2) = depth_byte; - *(raw->getData() + i + 3) = 255; + //write converted scanline out to result image + for(S32 j = 0; j < raw->getComponents(); j++) + { + *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte; + } } } } @@ -4565,7 +4555,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding) // Note: this formula depends on the number of components being 3. Not obvious, but it's correct. - image_width += (image_width * (type == SNAPSHOT_TYPE_DEPTH ? 4 : 3)) % 4 ; + image_width += (image_width * 3) % 4; // Resize image if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4) diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 997ac21dfd..5c0eae61be 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -192,7 +192,7 @@ public: // Hide normal UI when a logon fails, re-show everything when logon is attempted again void setNormalControlsVisible( BOOL visible ); - void setMenuBackgroundColor(bool god_mode = false, bool dev_grid = false); + void setMenuBackgroundColor(bool god_mode = false, bool dev_grid = false); // Handle the application becoming active (frontmost) or inactive //BOOL handleActivate(BOOL activate); @@ -219,18 +219,24 @@ public: static void movieSize(S32 new_width, S32 new_height); + // snapshot functionality. + // perhaps some of this should move to llfloatershapshot? -MG typedef enum e_snapshot_type { SNAPSHOT_TYPE_COLOR, SNAPSHOT_TYPE_DEPTH, SNAPSHOT_TYPE_OBJECT_ID } ESnapshotType; - BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR); BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_IMAGE_SIZE ); - BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ; - BOOL saveImageNumbered(LLImageRaw *raw, const std::string& extension = std::string()); + + BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ; + BOOL saveImageNumbered(LLImageFormatted *image); + + // Reset the directory where snapshots are saved. + // Client will open directory picker on next snapshot save. + void resetSnapshotLoc(); void playSnapshotAnimAndSound(); diff --git a/install.xml b/install.xml index 4b377d90b7..2475a2a5e4 100644 --- a/install.xml +++ b/install.xml @@ -503,16 +503,16 @@ <key>darwin</key> <map> <key>md5sum</key> - <string>4db422310f3b35710e44f69ecda19195</string> + <string>9a91ecd80203a24fb347b1436155b013</string> <key>url</key> - <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-5.2.1-darwin-20080613.tar.bz2</uri> + <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-5.2.1-darwin-20080716.tar.bz2</uri> </map> <key>linux</key> <map> <key>md5sum</key> - <string>5a70296632fa973e6484f60de067088c</string> + <string>daadd8c268e16f8c5f6145be8596b8b8</string> <key>url</key> - <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-5.2.1-linux-20080613.tar.bz2</uri> + <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-5.2.1-linux-20080716.tar.bz2</uri> </map> <key>windows</key> <map> diff --git a/scripts/install.py b/scripts/install.py index adb1b24e25..dd8ffa8401 100755 --- a/scripts/install.py +++ b/scripts/install.py @@ -560,6 +560,62 @@ windows/i686/vs/2003 -- specify a windows visual studio 2003 package""" ifile.fetch_local() self._install(to_install, install_dir) + def do_install(self, installables, platform, install_dir, cache_dir=None, + check_license=True, scp=None): + """Determine what installables should be installed. If they were + passed in on the command line, use them, otherwise install + all known installables. + """ + if not cache_dir: + cache_dir = _default_installable_cache() + all_installables = self.list_installables() + if not len(installables): + install_installables = all_installables + else: + # passed in on the command line. We'll need to verify we + # know about them here. + install_installables = installables + for installable in install_installables: + if installable not in all_installables: + raise RuntimeError('Unknown installable: %s' % + (installable,)) + if check_license: + # *TODO: check against a list of 'known good' licenses. + # *TODO: check for urls which conflict -- will lead to + # problems. + for installable in install_installables: + if not self.is_valid_license(installable): + return 1 + + # Set up the 'scp' handler + opener = urllib2.build_opener() + scp_or_http = SCPOrHTTPHandler(scp) + opener.add_handler(scp_or_http) + urllib2.install_opener(opener) + + # Do the work of installing the requested installables. + self.install( + install_installables, + platform, + install_dir, + cache_dir) + scp_or_http.cleanup() + + def do_uninstall(self, installables, install_dir): + # Do not bother to check license if we're uninstalling. + all_installed = self.list_installed() + if not len(installables): + uninstall_installables = all_installed + else: + # passed in on the command line. We'll need to verify we + # know about them here. + uninstall_installables = installables + for installable in uninstall_installables: + if installable not in all_installed: + raise RuntimeError('Installable not installed: %s' % + (installable,)) + self.uninstall(uninstall_installables, install_dir) + class SCPOrHTTPHandler(urllib2.BaseHandler): """Evil hack to allow both the build system and developers consume proprietary binaries. @@ -696,7 +752,6 @@ def _default_installable_cache(): 'install.cache.%s' % user) return cache_dir - def parse_args(): parser = optparse.OptionParser( usage="usage: %prog [options] [installable1 [installable2...]]", @@ -954,7 +1009,7 @@ def main(): print "Detail on installable",options.detail_installable+":" pprint.pprint(detail) except KeyError: - print "Binary '"+options.detail_installable+"' not found in", + print "Installable '"+options.detail_installable+"' not found in", print "install file." return 0 if options.list_licenses: @@ -1016,55 +1071,11 @@ def main(): md5sum=options.package_md5): return 1 elif options.uninstall: - # Do not bother to check license if we're uninstalling. - all_installed = installer.list_installed() - if not len(args): - uninstall_installables = all_installed - else: - # passed in on the command line. We'll need to verify we - # know about them here. - uninstall_installables = args - for installable in uninstall_installables: - if installable not in all_installed: - raise RuntimeError('Binary not installed: %s' % - (installable,)) - installer.uninstall(uninstall_installables, options.install_dir) + installer.do_uninstall(args, options.install_dir) else: - # Determine what installables should be installed. If they were - # passed in on the command line, use them, otherwise install - # all known installables. - all_installables = installer.list_installables() - if not len(args): - install_installables = all_installables - else: - # passed in on the command line. We'll need to verify we - # know about them here. - install_installables = args - for installable in install_installables: - if installable not in all_installables: - raise RuntimeError('Unknown installable: %s' % - (installable,)) - if options.check_license: - # *TODO: check against a list of 'known good' licenses. - # *TODO: check for urls which conflict -- will lead to - # problems. - for installable in install_installables: - if not installer.is_valid_license(installable): - return 1 - - # Set up the 'scp' handler - opener = urllib2.build_opener() - scp_or_http = SCPOrHTTPHandler(options.scp) - opener.add_handler(scp_or_http) - urllib2.install_opener(opener) - - # Do the work of installing the requested installables. - installer.install( - install_installables, - options.platform, - options.install_dir, - options.cache_dir) - scp_or_http.cleanup() + installer.do_install(args, options.platform, options.install_dir, + options.cache_dir, options.check_license, + options.scp) # save out any changes installer.save() diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index abd25bfb29..7761283239 100644 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -1179,7 +1179,7 @@ version 2.0 // simulator -> viewer // reliable { - ParcelObjectOwnersReply Low 57 Trusted Zerocoded + ParcelObjectOwnersReply Low 57 Trusted Zerocoded UDPDeprecated { Data Variable { OwnerID LLUUID } @@ -8767,7 +8767,7 @@ version 2.0 // LandStatReply // Sent by the simulator in response to LandStatRequest { - LandStatReply Low 422 Trusted Unencoded + LandStatReply Low 422 Trusted Unencoded UDPDeprecated { RequestData Single { ReportType U32 } |