diff options
348 files changed, 7828 insertions, 2923 deletions
diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h index 7e8c84488c..50d9d05046 100644 --- a/indra/llcharacter/llkeyframemotion.h +++ b/indra/llcharacter/llkeyframemotion.h @@ -47,7 +47,6 @@ #include "llquaternion.h" #include "v3dmath.h" #include "v3math.h" -#include "llapr.h" #include "llbvhconsts.h" class LLKeyframeDataCache; diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 1a052ce62d..27a52cdd99 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -34,14 +34,18 @@ #define LL_LLAPP_H #include <map> -#include "llapr.h" #include "llrun.h" #include "llsd.h" #include "lloptioninterface.h" // Forward declarations +template <typename Type> class LLAtomic32; +typedef LLAtomic32<U32> LLAtomicU32; class LLErrorThread; class LLLiveFile; +#if LL_LINUX +typedef struct siginfo siginfo_t; +#endif typedef void (*LLAppErrorHandler)(); typedef void (*LLAppChildCallback)(int pid, bool exited, int status); @@ -202,8 +206,6 @@ public: #if !LL_WINDOWS static U32 getSigChildCount(); static void incSigChildCount(); -#else -#define getpid GetCurrentProcessId #endif static int getPid(); diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index b08bb617c5..b05a222b33 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -38,6 +38,14 @@ #if LL_LINUX || LL_SOLARIS #include <sys/param.h> // Need PATH_MAX in APR headers... #endif +#if LL_WINDOWS + // Limit Windows API to small and manageable set. + // If you get undefined symbols, find the appropriate + // Windows header file and include that in your .cpp file. + #define WIN32_LEAN_AND_MEAN + #include <winsock2.h> + #include <windows.h> +#endif #include <boost/noncopyable.hpp> diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h index b36471f9f8..05eef25b21 100644 --- a/indra/llcommon/llcommon.h +++ b/indra/llcommon/llcommon.h @@ -33,7 +33,6 @@ #define LL_COMMON_H // *TODO: remove these? -#include "llapr.h" #include "lltimer.h" #include "llfile.h" diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 77c0c2294a..bd334a6654 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -45,9 +45,6 @@ # include <syslog.h> # include <unistd.h> #endif // !LL_WINDOWS -#if LL_WINDOWS -# include <windows.h> -#endif // LL_WINDOWS #include <vector> #include "llapp.h" diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index d8aa90de2e..adef1a9192 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -34,6 +34,7 @@ #define LL_LLTHREAD_H #include "llapp.h" +#include "llapr.h" #include "apr_thread_cond.h" class LLThread; diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h index d1c9bdde85..e8e390f296 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -34,7 +34,6 @@ #ifndef LL_LLIOHTTPSERVER_H #define LL_LLIOHTTPSERVER_H -#include "llapr.h" #include "llchainio.h" #include "llhttpnode.h" diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index 232478577c..40e4a4268d 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -92,7 +92,7 @@ const U32 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23); const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26); -const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); +// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28); diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index f60838b1e7..dab6d645dd 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -79,8 +79,10 @@ LLPluginProcessParent::~LLPluginProcessParent() // and remove it from our map mSharedMemoryRegions.erase(iter); } - - mProcess.kill(); + + // orphaning the process means it won't be killed when the LLProcessLauncher is destructed. + // This is what we want -- it should exit cleanly once it notices the sockets have been closed. + mProcess.orphan(); killSockets(); } @@ -414,7 +416,8 @@ void LLPluginProcessParent::idle(void) break; case STATE_CLEANUP: - mProcess.kill(); + // Don't do a kill here anymore -- closing the sockets is the new 'kill'. + mProcess.orphan(); killSockets(); setState(STATE_DONE); break; diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index 6d661a6960..03ce10f86c 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -34,6 +34,7 @@ #ifndef LL_LLPLUGINPROCESSPARENT_H #define LL_LLPLUGINPROCESSPARENT_H +#include "llapr.h" #include "llprocesslauncher.h" #include "llpluginmessage.h" #include "llpluginmessagepipe.h" diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp index 3c69a69d28..9c18b410c7 100644 --- a/indra/llplugin/llpluginsharedmemory.cpp +++ b/indra/llplugin/llpluginsharedmemory.cpp @@ -1,6 +1,6 @@ /** * @file llpluginsharedmemory.cpp - * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. + * LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. * * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ @@ -96,6 +96,10 @@ std::string LLPluginSharedMemory::createName(void) return newname.str(); } +/** + * @brief LLPluginSharedMemoryImpl is the platform-dependent implementation of LLPluginSharedMemory. TODO:DOC is this necessary/sufficient? kinda obvious. + * + */ class LLPluginSharedMemoryPlatformImpl { public: @@ -112,6 +116,9 @@ public: }; +/** + * Constructor. Creates a shared memory segment. + */ LLPluginSharedMemory::LLPluginSharedMemory() { mSize = 0; @@ -121,6 +128,9 @@ LLPluginSharedMemory::LLPluginSharedMemory() mImpl = new LLPluginSharedMemoryPlatformImpl; } +/** + * Destructor. Uses destroy() and detach() to ensure shared memory segment is cleaned up. + */ LLPluginSharedMemory::~LLPluginSharedMemory() { if(mNeedsDestroy) diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h index 4014620c52..00c54ef08c 100644 --- a/indra/llplugin/llpluginsharedmemory.h +++ b/indra/llplugin/llpluginsharedmemory.h @@ -1,6 +1,5 @@ /** * @file llpluginsharedmemory.h - * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. * * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ @@ -36,6 +35,10 @@ class LLPluginSharedMemoryPlatformImpl; +/** + * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. + * + */ class LLPluginSharedMemory { LOG_CLASS(LLPluginSharedMemory); @@ -46,16 +49,62 @@ public: // Parent will use create/destroy, child will use attach/detach. // Message transactions will ensure child attaches after parent creates and detaches before parent destroys. - // create() implicitly creates a name for the segment which is guaranteed to be unique on the host at the current time. + /** + * Creates a shared memory segment, with a name which is guaranteed to be unique on the host at the current time. Used by parent. + * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys. + * + * @param[in] size Shared memory size in TODO:DOC units = bytes?. + * + * @return False for failure, true for success. + */ bool create(size_t size); + /** + * Destroys a shared memory segment. Used by parent. + * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys. + * + * @return True. TODO:DOC - always returns true. Is this the intended behavior? + */ bool destroy(void); + /** + * Creates and attaches a name to a shared memory segment. TODO:DOC what's the difference between attach() and create()? + * + * @param[in] name Name to attach to memory segment + * @param[in] size Size of memory segment TODO:DOC in bytes? + * + * @return False on failure, true otherwise. + */ bool attach(const std::string &name, size_t size); + /** + * Detaches shared memory segment. + * + * @return False on failure, true otherwise. + */ bool detach(void); + /** + * Checks if shared memory is mapped to a non-null address. + * + * @return True if memory address is non-null, false otherwise. + */ bool isMapped(void) const { return (mMappedAddress != NULL); }; + /** + * Get pointer to shared memory. + * + * @return Pointer to shared memory. + */ void *getMappedAddress(void) const { return mMappedAddress; }; + /** + * Get size of shared memory. + * + * @return Size of shared memory in bytes. TODO:DOC are bytes the correct unit? + */ size_t getSize(void) const { return mSize; }; + /** + * Get name of shared memory. + * + * @return Name of shared memory. + */ std::string getName() const { return mName; }; private: diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 1325b4995b..7a5d029038 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -58,9 +58,8 @@ private: ~LLFontManager(); }; -class LLFontGlyphInfo +struct LLFontGlyphInfo { -public: LLFontGlyphInfo(U32 index); U32 mGlyphIndex; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index a28ffbfdc0..db1f019a81 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -195,7 +195,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_y += mFontFreetype->getDescenderHeight(); break; case VCENTER: - cur_y -= ((mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight())/2.f); + cur_y -= (mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight()) / 2.f; break; case BASELINE: // Baseline, do nothing. @@ -221,7 +221,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_render_y = cur_y; cur_render_x = cur_x; - F32 start_x = cur_x; + F32 start_x = llround(cur_x); const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); @@ -235,7 +235,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (use_ellipses) { // check for too long of a string - if (getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX > scaled_max_pixels) + S32 string_width = llround(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX); + if (string_width > scaled_max_pixels) { // use four dots for ellipsis width to generate padding const LLWString dots(utf8str_to_wstring(std::string("...."))); @@ -301,8 +302,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons // Must do this to cur_x, not just to cur_render_x, otherwise you // will squish sub-pixel kerned characters too close together. // For example, "CCCCC" looks bad. - cur_x = (F32)llfloor(cur_x + 0.5f); - //cur_y = (F32)llfloor(cur_y + 0.5f); + cur_x = (F32)llround(cur_x); + //cur_y = (F32)llround(cur_y); cur_render_x = cur_x; cur_render_y = cur_y; @@ -461,7 +462,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars cur_x += mFontFreetype->getXKerning(wch, next_char); } // Round after kerning. - cur_x = (F32)llfloor(cur_x + 0.5f); + cur_x = (F32)llround(cur_x); } // add in extra pixels for last character's width past its xadvance @@ -490,6 +491,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch // avoid S32 overflow when max_pixels == S32_MAX by staying in floating point F32 scaled_max_pixels = ceil(max_pixels * sScaleX); + F32 width_padding = 0.f; S32 i; for (i=0; (i < max_chars); i++) @@ -533,9 +535,17 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch } } - cur_x += mFontFreetype->getXAdvance(wch); + LLFontGlyphInfo* fgi = mFontFreetype->getGlyphInfo(wch); + + // account for glyphs that run beyond the starting point for the next glyphs + width_padding = llmax( 0.f, // always use positive padding amount + width_padding - fgi->mXAdvance, // previous padding left over after advance of current character + (F32)(fgi->mWidth + fgi->mXBearing) - fgi->mXAdvance); // difference between width of this character and advance to next character + + cur_x += fgi->mXAdvance; - if (scaled_max_pixels < cur_x) + // clip if current character runs past scaled_max_pixels (using width_padding) + if (scaled_max_pixels < cur_x + width_padding) { clip = TRUE; break; @@ -548,7 +558,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch } // Round after kerning. - cur_x = (F32)llfloor(cur_x + 0.5f); + cur_x = llround(cur_x); drawn_x = cur_x; } @@ -660,7 +670,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t } // Round after kerning. - cur_x = (F32)llfloor(cur_x + 0.5f); + cur_x = llround(cur_x); } return llmin(max_chars, pos - begin_offset); diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 74b49b846e..82ec02d2eb 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -26,7 +26,6 @@ include_directories( ) set(llui_SOURCE_FILES - llalertdialog.cpp llbutton.cpp llcheckboxctrl.cpp llclipboard.cpp @@ -112,7 +111,6 @@ set(llui_SOURCE_FILES set(llui_HEADER_FILES CMakeLists.txt - llalertdialog.h llbutton.h llcallbackmap.h llcheckboxctrl.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 7721137e29..e9f6288f44 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -63,7 +63,6 @@ template class LLButton* LLView::getChild<class LLButton>( // globals loaded from settings.xml S32 LLBUTTON_H_PAD = 0; -S32 LLBUTTON_V_PAD = 0; S32 BTN_HEIGHT_SMALL= 0; S32 BTN_HEIGHT = 0; @@ -93,6 +92,7 @@ LLButton::Params::Params() flash_color("flash_color"), pad_right("pad_right", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")), pad_left("pad_left", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")), + pad_bottom("pad_bottom"), click_callback("click_callback"), mouse_down_callback("mouse_down_callback"), mouse_up_callback("mouse_up_callback"), @@ -148,6 +148,7 @@ LLButton::LLButton(const LLButton::Params& p) mHAlign(p.font_halign), mLeftHPad(p.pad_left), mRightHPad(p.pad_right), + mBottomVPad(p.pad_bottom), mHoverGlowStrength(p.hover_glow_amount), mCommitOnReturn(p.commit_on_return), mFadeWhenDisabled(FALSE), @@ -839,7 +840,9 @@ void LLButton::draw() // LLFontGL::render expects S32 max_chars variable but process in a separate way -1 value. // Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode. // Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars. - mLastDrawCharsCount = mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset), + mLastDrawCharsCount = mGLFont->render(label, 0, + (F32)x, + (F32)(mBottomVPad + y_offset), label_color % alpha, mHAlign, LLFontGL::BOTTOM, LLFontGL::NORMAL, diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 4c7400220d..5e28b8cdff 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -49,7 +49,6 @@ // PLEASE please use these "constants" when building your own buttons. // They are loaded from settings.xml at run time. extern S32 LLBUTTON_H_PAD; -extern S32 LLBUTTON_V_PAD; extern S32 BTN_HEIGHT_SMALL; extern S32 BTN_HEIGHT; @@ -105,6 +104,7 @@ public: // layout Optional<S32> pad_right; Optional<S32> pad_left; + Optional<S32> pad_bottom; // under text label // callbacks Optional<CommitCallbackParam> click_callback, // alias -> commit_callback @@ -310,6 +310,7 @@ private: LLFontGL::HAlign mHAlign; S32 mLeftHPad; S32 mRightHPad; + S32 mBottomVPad; // under text label F32 mHoverGlowStrength; F32 mCurGlowStrength; diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 9c69e4f2b6..9dc7861992 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -38,6 +38,8 @@ //static LLHandle<LLFloater> LLDockableFloater::sInstanceHandle; +static const std::string VOICE_FLOATER("floater_voice_controls"), IM_FLOATER("panel_im"); + //static void LLDockableFloater::init(LLDockableFloater* thiz) { @@ -98,8 +100,15 @@ void LLDockableFloater::toggleInstance(const LLSD& sdname) else if (instance != NULL) { instance->setMinimized(FALSE); - instance->setVisible(TRUE); - gFloaterView->bringToFront(instance); + if (instance->getVisible()) + { + instance->setVisible(FALSE); + } + else + { + instance->setVisible(TRUE); + gFloaterView->bringToFront(instance); + } } } @@ -107,9 +116,11 @@ void LLDockableFloater::resetInstance() { if (mUniqueDocking && sInstanceHandle.get() != this) { - if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked()) + if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked() + && (getName() != VOICE_FLOATER || sInstanceHandle.get()->getName() != IM_FLOATER) + && (getName() != IM_FLOATER || sInstanceHandle.get()->getName() != VOICE_FLOATER)) { - sInstanceHandle.get()->setVisible(FALSE); + sInstanceHandle.get()->setVisible(FALSE); } sInstanceHandle = getHandle(); } diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 46491d8a29..2c339f4a3f 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -83,6 +83,8 @@ public: virtual void onDockHidden(); virtual void onDockShown(); + LLDockControl* getDockControl(); + private: /** * Provides unique of dockable floater. @@ -92,7 +94,6 @@ private: protected: void setDockControl(LLDockControl* dockControl); - LLDockControl* getDockControl(); const LLUIImagePtr& getDockTongue(); private: diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index 30a45bedc7..550955c4c5 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -76,6 +76,9 @@ public: // gets a rect that bounds possible positions for a dockable control (EXT-1111) void getAllowedRect(LLRect& rect); + S32 getTongueWidth() { return mDockTongue->getWidth(); } + S32 getTongueHeight() { return mDockTongue->getHeight(); } + private: virtual void moveDockable(); private: diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index d9b98b1c28..a93c666648 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -112,6 +112,7 @@ void LLDragHandleTop::setTitle(const std::string& title) params.font(font); params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT); params.font_shadow(LLFontGL::DROP_SHADOW_SOFT); + params.use_ellipses = true; mTitleBox = LLUICtrlFactory::create<LLTextBox> (params); addChild( mTitleBox ); } diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 831ac66d06..64a4824a17 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -891,7 +891,13 @@ void LLFlatListView::setNoItemsCommentVisible(bool visible) const // We have to update child rect here because of issues with rect after reshaping while creating LLTextbox // It is possible to have invalid LLRect if Flat List is in LLAccordionTab LLRect comment_rect = getLocalRect(); - comment_rect.stretch(-getBorderWidth()); + + // To see comment correctly (EXT - 3244) in mNoItemsCommentTextbox we must get border width + // of LLFlatListView (@see getBorderWidth()) and stretch mNoItemsCommentTextbox to this width + // But getBorderWidth() returns 0 if LLFlatListView not visible. So we have to get border width + // from 'scroll_border' + LLViewBorder* scroll_border = getChild<LLViewBorder>("scroll border"); + comment_rect.stretch(-scroll_border->getBorderWidth()); mNoItemsCommentTextbox->setRect(comment_rect); } mNoItemsCommentTextbox->setVisible(visible); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index fd7b64af02..5fd707fea3 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1649,6 +1649,7 @@ void LLFloater::draw() } else { + //FIXME: get rid of this hack // draw children LLView* focused_child = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus()); BOOL focused_child_visible = FALSE; @@ -2703,6 +2704,18 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o output_node, output_params, &default_params); } + // Default floater position to top-left corner of screen + // However, some legacy floaters have explicit top or bottom + // coordinates set, so respect their wishes. + if (!params.rect.top.isProvided() && !params.rect.bottom.isProvided()) + { + params.rect.top.set(0); + } + if (!params.rect.left.isProvided() && !params.rect.right.isProvided()) + { + params.rect.left.set(0); + } + setupParams(params, parent); initFromParams(params); diff --git a/indra/llui/llhelp.h b/indra/llui/llhelp.h index 82c3bc385f..938419d374 100644 --- a/indra/llui/llhelp.h +++ b/indra/llui/llhelp.h @@ -42,6 +42,8 @@ class LLHelp virtual std::string defaultTopic() = 0; // return topic to use before the user logs in virtual std::string preLoginTopic() = 0; + // return topic to use for the top-level help, invoked by F1 + virtual std::string f1HelpTopic() = 0; }; #endif // headerguard diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 750b190953..de2b43bf13 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -37,7 +37,6 @@ #define LLPANEL_CPP #include "llpanel.h" -#include "llalertdialog.h" #include "llfocusmgr.h" #include "llfontgl.h" #include "llrect.h" diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index d7d61cf6cb..2d9106923e 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -906,7 +906,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) if (placeholder) { - btn_rect.translate(0, -LLBUTTON_V_PAD-2); + btn_rect.translate(0, -3); // *TODO: make configurable LLTextBox::Params params; params.name(trimmed_label); params.rect(btn_rect); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index e0503a0844..1f120a1483 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -312,7 +312,7 @@ void LLTextBase::drawSelectionBackground() S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); S32 selection_right = llmax( mSelectionStart, mSelectionEnd ); - LLRect selection_rect = mTextRect; + LLRect selection_rect = mVisibleTextRect; // Skip through the lines we aren't drawing. LLRect content_display_rect = getVisibleDocumentRect(); @@ -391,7 +391,7 @@ void LLTextBase::drawSelectionBackground() ++rect_it) { LLRect selection_rect = *rect_it; - selection_rect.translate(mTextRect.mLeft - content_display_rect.mLeft, mTextRect.mBottom - content_display_rect.mBottom); + selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom); gl_rect_2d(selection_rect, selection_color); } } @@ -538,10 +538,10 @@ void LLTextBase::drawText() line_end = next_start; } - LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft, - line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom, + LLRect text_rect(line.mRect.mLeft + mVisibleTextRect.mLeft - scrolled_view_rect.mLeft, + line.mRect.mTop - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom, llmin(mDocumentView->getRect().getWidth(), line.mRect.mRight) - scrolled_view_rect.mLeft, - line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom); + line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom); // draw a single line of text S32 seg_start = line_start; @@ -561,14 +561,14 @@ void LLTextBase::drawText() S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart(); - if (mUseEllipses - && clipped_end == line_end - && next_line == last_line - && last_line < (S32)mLineInfoList.size()) + if (mUseEllipses // using ellipses + && clipped_end == line_end // last segment on line + && next_line == last_line // this is the last visible line + && last_line < (S32)mLineInfoList.size()) // and there is more text to display { - // more text to go, but we can't fit it - // so attempt to draw one extra character to force ellipses - clipped_end++; + // more lines of text to go, but we can't fit them + // so shrink text rect to force ellipses + text_rect.mRight -= 2; } text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect)); @@ -949,7 +949,7 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent) LLUICtrl::reshape( width, height, called_from_parent ); // do this first after reshape, because other things depend on - // up-to-date mTextRect + // up-to-date mVisibleTextRect updateRects(); needsReflow(); @@ -984,7 +984,7 @@ void LLTextBase::draw() : hasFocus() ? mFocusBgColor.get() : mWriteableBgColor.get(); - gl_rect_2d(mTextRect, bg_color, TRUE); + gl_rect_2d(mVisibleTextRect, bg_color, TRUE); } // draw document view @@ -1053,9 +1053,9 @@ S32 LLTextBase::getLeftOffset(S32 width) case LLFontGL::LEFT: return mHPad; case LLFontGL::HCENTER: - return mHPad + (mTextRect.getWidth() - width - mHPad) / 2; + return mHPad + (mVisibleTextRect.getWidth() - width - mHPad) / 2; case LLFontGL::RIGHT: - return mTextRect.getWidth() - width; + return mVisibleTextRect.getWidth() - width; default: return mHPad; } @@ -1071,17 +1071,17 @@ void LLTextBase::reflow(S32 start_index) while(mReflowNeeded) { - mReflowNeeded = FALSE; + mReflowNeeded = false; // shrink document to minimum size (visible portion of text widget) // to force inlined widgets with follows set to shrink - mDocumentView->setShape(mTextRect); + mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight()); bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false; LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos); - bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible - old_cursor_rect.translate(-mTextRect.mLeft, -mTextRect.mBottom); + bool follow_selection = mVisibleTextRect.overlaps(old_cursor_rect); // cursor is visible + old_cursor_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom); S32 first_line = getFirstVisibleLine(); @@ -1094,15 +1094,15 @@ void LLTextBase::reflow(S32 start_index) } LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex); // subtract off effect of horizontal scrollbar from local position of first char - first_char_rect.translate(-mTextRect.mLeft, -mTextRect.mBottom); + first_char_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom); S32 cur_top = 0; segment_set_t::iterator seg_iter = mSegments.begin(); S32 seg_offset = 0; S32 line_start_index = 0; - const S32 text_width = mTextRect.getWidth() - mHPad; // reserve room for margin - S32 remaining_pixels = text_width; + const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin + S32 remaining_pixels = text_available_width; LLWString text(getWText()); S32 line_count = 0; @@ -1142,10 +1142,11 @@ void LLTextBase::reflow(S32 start_index) S32 last_segment_char_on_line = segment->getStart() + seg_offset; - S32 text_left = getLeftOffset(text_width - remaining_pixels); + S32 text_actual_width = text_available_width - remaining_pixels; + S32 text_left = getLeftOffset(text_actual_width); LLRect line_rect(text_left, cur_top, - text_left + (text_width - remaining_pixels), + text_left + text_actual_width, cur_top - line_height); // if we didn't finish the current segment... @@ -1160,7 +1161,7 @@ void LLTextBase::reflow(S32 start_index) line_start_index = segment->getStart() + seg_offset; cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels; - remaining_pixels = text_width; + remaining_pixels = text_available_width; line_height = 0; } // ...just consumed last segment.. @@ -1188,7 +1189,7 @@ void LLTextBase::reflow(S32 start_index) line_start_index = segment->getStart() + seg_offset; cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels; line_height = 0; - remaining_pixels = text_width; + remaining_pixels = text_available_width; } ++seg_iter; seg_offset = 0; @@ -1238,10 +1239,10 @@ void LLTextBase::reflow(S32 start_index) } } -LLRect LLTextBase::getContentsRect() +LLRect LLTextBase::getTextBoundingRect() { reflow(); - return mContentsRect; + return mTextBoundingRect; } @@ -1760,7 +1761,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round LLRect visible_region = getVisibleDocumentRect(); // binary search for line that starts before local_y - line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mTextRect.mBottom + visible_region.mBottom, compare_bottom()); + line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mVisibleTextRect.mBottom + visible_region.mBottom, compare_bottom()); if (line_iter == mLineInfoList.end()) { @@ -1768,7 +1769,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round } S32 pos = getLength(); - S32 start_x = mTextRect.mLeft + line_iter->mRect.mLeft; + S32 start_x = mVisibleTextRect.mLeft + line_iter->mRect.mLeft; segment_set_t::iterator line_seg_iter; S32 line_seg_offset; @@ -1879,7 +1880,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const if (mLineInfoList.empty()) { // return default height rect in upper left - local_rect = mTextRect; + local_rect = mVisibleTextRect; local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight()); return local_rect; } @@ -1890,8 +1891,8 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const // compensate for scrolled, inset view of doc LLRect scrolled_view_rect = getVisibleDocumentRect(); local_rect = doc_rect; - local_rect.translate(mTextRect.mLeft - scrolled_view_rect.mLeft, - mTextRect.mBottom - scrolled_view_rect.mBottom); + local_rect.translate(mVisibleTextRect.mLeft - scrolled_view_rect.mLeft, + mVisibleTextRect.mBottom - scrolled_view_rect.mBottom); return local_rect; } @@ -1991,7 +1992,7 @@ void LLTextBase::changeLine( S32 delta ) LLRect visible_region = getVisibleDocumentRect(); - S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mTextRect.mBottom - visible_region.mBottom, TRUE); + S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE); setCursorPos(new_cursor_pos, true); } @@ -2067,56 +2068,64 @@ void LLTextBase::updateRects() { if (mLineInfoList.empty()) { - mContentsRect = LLRect(0, mVPad, mHPad, 0); + mTextBoundingRect = LLRect(0, mVPad, mHPad, 0); } else { - mContentsRect = mLineInfoList.begin()->mRect; + mTextBoundingRect = mLineInfoList.begin()->mRect; for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin(); line_iter != mLineInfoList.end(); ++line_iter) { - mContentsRect.unionWith(line_iter->mRect); + mTextBoundingRect.unionWith(line_iter->mRect); } - mContentsRect.mTop += mVPad; + mTextBoundingRect.mTop += mVPad; // subtract a pixel off the bottom to deal with rounding errors in measuring font height - mContentsRect.mBottom -= 1; + mTextBoundingRect.mBottom -= 1; - S32 delta_pos = -mContentsRect.mBottom; + S32 delta_pos = -mTextBoundingRect.mBottom; // move line segments to fit new document rect for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it) { it->mRect.translate(0, delta_pos); } - mContentsRect.translate(0, delta_pos); + mTextBoundingRect.translate(0, delta_pos); } // update document container dimensions according to text contents - LLRect doc_rect = mContentsRect; - // use old mTextRect constraint document to width of viewable region + LLRect doc_rect = mTextBoundingRect; + // use old mVisibleTextRect constraint document to width of viewable region doc_rect.mLeft = 0; - doc_rect.mRight = llmax(mTextRect.getWidth(), mContentsRect.mRight); + + // allow horizontal scrolling? + // if so, use entire width of text contents + // otherwise, stop at width of mVisibleTextRect + doc_rect.mRight = mScroller + ? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight) + : mVisibleTextRect.getWidth(); mDocumentView->setShape(doc_rect); - //update mTextRect *after* mDocumentView has been resized + //update mVisibleTextRect *after* mDocumentView has been resized // so that scrollbars are added if document needs to scroll - // since mTextRect does not include scrollbars - LLRect old_text_rect = mTextRect; - mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect(); + // since mVisibleTextRect does not include scrollbars + LLRect old_text_rect = mVisibleTextRect; + mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect(); //FIXME: replace border with image? if (mBorderVisible) { - mTextRect.stretch(-1); + mVisibleTextRect.stretch(-1); } - if (mTextRect != old_text_rect) + if (mVisibleTextRect != old_text_rect) { needsReflow(); } - // update document container again, using new mTextRect - doc_rect.mRight = llmax(mTextRect.getWidth(), mContentsRect.mRight); + // update document container again, using new mVisibleTextRect (that has scrollbars enabled as needed) + doc_rect.mRight = mScroller + ? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight) + : mVisibleTextRect.getWidth(); mDocumentView->setShape(doc_rect); } @@ -2154,7 +2163,7 @@ LLRect LLTextBase::getVisibleDocumentRect() const LLRect doc_rect = mDocumentView->getLocalRect(); doc_rect.mLeft -= mDocumentView->getRect().mLeft; // adjust for height of text above widget baseline - doc_rect.mBottom = doc_rect.getHeight() - mTextRect.getHeight(); + doc_rect.mBottom = doc_rect.getHeight() - mVisibleTextRect.getHeight(); return doc_rect; } } @@ -2413,10 +2422,18 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt if (num_chars > 0) { LLWString text = mEditor.getWText(); - width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); // if last character is a newline, then return true, forcing line break llwchar last_char = text[mStart + first_char + num_chars - 1]; - force_newline = (last_char == '\n'); + if (last_char == '\n') + { + force_newline = true; + // don't count newline in font width + width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars - 1); + } + else + { + width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); + } } else { diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 0138ca3704..a1f8ba39ae 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -156,8 +156,8 @@ public: void addDocumentChild(LLView* view); void removeDocumentChild(LLView* view); const LLView* getDocumentView() const { return mDocumentView; } - LLRect getTextRect() { return mTextRect; } - LLRect getContentsRect(); + LLRect getVisibleTextRect() { return mVisibleTextRect; } + LLRect getTextBoundingRect(); LLRect getVisibleDocumentRect() const; S32 getVPad() { return mVPad; } @@ -311,8 +311,8 @@ protected: // text segmentation and flow segment_set_t mSegments; line_list_t mLineInfoList; - LLRect mTextRect; // The rect in which text is drawn. Excludes borders. - LLRect mContentsRect; + LLRect mVisibleTextRect; // The rect in which text is drawn. Excludes borders. + LLRect mTextBoundingRect; // colors LLUIColor mCursorColor; diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 0bd0ab59fb..a1f5b5726b 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -134,12 +134,12 @@ void LLTextBox::setClickedCallback( boost::function<void (void*)> cb, void* user S32 LLTextBox::getTextPixelWidth() { - return getContentsRect().getWidth(); + return getTextBoundingRect().getWidth(); } S32 LLTextBox::getTextPixelHeight() { - return getContentsRect().getHeight(); + return getTextBoundingRect().getHeight(); } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index e68affc36c..e8fc9475a5 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -758,8 +758,8 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) { mScroller->autoScroll(x, y); } - S32 clamped_x = llclamp(x, mTextRect.mLeft, mTextRect.mRight); - S32 clamped_y = llclamp(y, mTextRect.mBottom, mTextRect.mTop); + S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight); + S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop); setCursorAtLocalPos( clamped_x, clamped_y, true ); mSelectionEnd = mCursorPos; } @@ -809,8 +809,8 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask) { mScroller->autoScroll(x, y); } - S32 clamped_x = llclamp(x, mTextRect.mLeft, mTextRect.mRight); - S32 clamped_y = llclamp(y, mTextRect.mBottom, mTextRect.mTop); + S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight); + S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop); setCursorAtLocalPos( clamped_x, clamped_y, true ); endSelection(); } @@ -1887,9 +1887,10 @@ void LLTextEditor::doDelete() removeChar(); } - onKeyStroke(); } + onKeyStroke(); + needsReflow(); } @@ -2074,8 +2075,8 @@ void LLTextEditor::drawPreeditMarker() const S32 line_height = llround( mDefaultFont->getLineHeight() ); S32 line_start = getLineStart(cur_line); - S32 line_y = mTextRect.mTop - line_height; - while((mTextRect.mBottom <= line_y) && (num_lines > cur_line)) + S32 line_y = mVisibleTextRect.mTop - line_height; + while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line)) { S32 next_start = -1; S32 line_end = text_len; @@ -2107,12 +2108,12 @@ void LLTextEditor::drawPreeditMarker() continue; } - S32 preedit_left = mTextRect.mLeft; + S32 preedit_left = mVisibleTextRect.mLeft; if (left > line_start) { preedit_left += mDefaultFont->getWidth(text, line_start, left - line_start); } - S32 preedit_right = mTextRect.mLeft; + S32 preedit_right = mVisibleTextRect.mLeft; if (right < line_end) { preedit_right += mDefaultFont->getWidth(text, line_start, right - line_start); @@ -2153,7 +2154,7 @@ void LLTextEditor::drawLineNumbers() { LLGLSUIDefault gls_ui; LLRect scrolled_view_rect = getVisibleDocumentRect(); - LLRect content_rect = getTextRect(); + LLRect content_rect = getVisibleTextRect(); LLLocalClipRect clip(content_rect); S32 first_line = getFirstVisibleLine(); S32 num_lines = getLineCount(); @@ -2179,12 +2180,12 @@ void LLTextEditor::drawLineNumbers() { line_info& line = mLineInfoList[cur_line]; - if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom) + if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mVisibleTextRect.mBottom) { break; } - S32 line_bottom = line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom; + S32 line_bottom = line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom; // draw the line numbers if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop) { @@ -2215,8 +2216,8 @@ void LLTextEditor::draw() { { // pad clipping rectangle so that cursor can draw at full width - // when at left edge of mTextRect - LLRect clip_rect(mTextRect); + // when at left edge of mVisibleTextRect + LLRect clip_rect(mVisibleTextRect); clip_rect.stretch(1); LLLocalClipRect clip(clip_rect); drawPreeditMarker(); @@ -2780,7 +2781,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect if (control) { LLRect control_rect_screen; - localRectToScreen(mTextRect, &control_rect_screen); + localRectToScreen(mVisibleTextRect, &control_rect_screen); LLUI::screenRectToGL(control_rect_screen, control); } @@ -2831,8 +2832,8 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect if (coord) { - const S32 query_x = mTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start); - const S32 query_y = mTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2; + const S32 query_x = mVisibleTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start); + const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2; S32 query_screen_x, query_screen_y; localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y); LLUI::screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY); @@ -2840,13 +2841,13 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect if (bounds) { - S32 preedit_left = mTextRect.mLeft; + S32 preedit_left = mVisibleTextRect.mLeft; if (preedit_left_position > current_line_start) { preedit_left += mDefaultFont->getWidth(text, current_line_start, preedit_left_position - current_line_start); } - S32 preedit_right = mTextRect.mLeft; + S32 preedit_right = mVisibleTextRect.mLeft; if (preedit_right_position < current_line_end) { preedit_right += mDefaultFont->getWidth(text, current_line_start, preedit_right_position - current_line_start); @@ -2856,7 +2857,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect preedit_right += mDefaultFont->getWidth(text, current_line_start, current_line_end - current_line_start); } - const S32 preedit_top = mTextRect.mTop - (current_line - first_visible_line) * line_height; + const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height; const S32 preedit_bottom = preedit_top - line_height; const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom); diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index 3a1e656364..f7a53e87de 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -39,22 +39,23 @@ LLFastTimer::DeclareTimer FTM_UI_STRING("UI String"); LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args) - : mOrig(instring), - mArgs(args) +: mOrig(instring), + mArgs(args) { - format(); + dirty(); } void LLUIString::assign(const std::string& s) { mOrig = s; - format(); + dirty(); } void LLUIString::setArgList(const LLStringUtil::format_map_t& args) + { mArgs = args; - format(); + dirty(); } void LLUIString::setArgs(const LLSD& sd) @@ -68,40 +69,40 @@ void LLUIString::setArgs(const LLSD& sd) { setArg(sd_it->first, sd_it->second.asString()); } - format(); + dirty(); } void LLUIString::setArg(const std::string& key, const std::string& replacement) { mArgs[key] = replacement; - format(); + dirty(); } void LLUIString::truncate(S32 maxchars) { - if (mWResult.size() > (size_t)maxchars) + if (getUpdatedWResult().size() > (size_t)maxchars) { - LLWStringUtil::truncate(mWResult, maxchars); - mResult = wstring_to_utf8str(mWResult); + LLWStringUtil::truncate(getUpdatedWResult(), maxchars); + mResult = wstring_to_utf8str(getUpdatedWResult()); } } void LLUIString::erase(S32 charidx, S32 len) { - mWResult.erase(charidx, len); - mResult = wstring_to_utf8str(mWResult); + getUpdatedWResult().erase(charidx, len); + mResult = wstring_to_utf8str(getUpdatedWResult()); } void LLUIString::insert(S32 charidx, const LLWString& wchars) { - mWResult.insert(charidx, wchars); - mResult = wstring_to_utf8str(mWResult); + getUpdatedWResult().insert(charidx, wchars); + mResult = wstring_to_utf8str(getUpdatedWResult()); } void LLUIString::replace(S32 charidx, llwchar wc) { - mWResult[charidx] = wc; - mResult = wstring_to_utf8str(mWResult); + getUpdatedWResult()[charidx] = wc; + mResult = wstring_to_utf8str(getUpdatedWResult()); } void LLUIString::clear() @@ -112,8 +113,16 @@ void LLUIString::clear() mWResult.clear(); } -void LLUIString::format() +void LLUIString::dirty() { + mNeedsResult = true; + mNeedsWResult = true; +} + +void LLUIString::updateResult() const +{ + mNeedsResult = false; + LLFastTimer timer(FTM_UI_STRING); // optimize for empty strings (don't attempt string replacement) @@ -129,5 +138,11 @@ void LLUIString::format() LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs(); combined_args.insert(mArgs.begin(), mArgs.end()); LLStringUtil::format(mResult, combined_args); - mWResult = utf8str_to_wstring(mResult); +} + +void LLUIString::updateWResult() const +{ + mNeedsWResult = false; + + mWResult = utf8str_to_wstring(getUpdatedResult()); } diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index 763de4d6a3..7ec0fd603a 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -76,19 +76,19 @@ public: void setArgs(const class LLSD& sd); void setArg(const std::string& key, const std::string& replacement); - const std::string& getString() const { return mResult; } - operator std::string() const { return mResult; } + const std::string& getString() const { return getUpdatedResult(); } + operator std::string() const { return getUpdatedResult(); } - const LLWString& getWString() const { return mWResult; } - operator LLWString() const { return mWResult; } + const LLWString& getWString() const { return getUpdatedWResult(); } + operator LLWString() const { return getUpdatedWResult(); } - bool empty() const { return mWResult.empty(); } - S32 length() const { return mWResult.size(); } + bool empty() const { return getUpdatedResult().empty(); } + S32 length() const { return getUpdatedWResult().size(); } void clear(); void clearArgs() { mArgs.clear(); } - // These utuilty functions are included for text editing. + // These utility functions are included for text editing. // They do not affect mOrig and do not perform argument substitution void truncate(S32 maxchars); void erase(S32 charidx, S32 len); @@ -96,12 +96,24 @@ public: void replace(S32 charidx, llwchar wc); private: - void format(); + // something changed, requiring reformatting of strings + void dirty(); + + std::string& getUpdatedResult() const { if (mNeedsResult) { updateResult(); } return mResult; } + LLWString& getUpdatedWResult() const{ if (mNeedsWResult) { updateWResult(); } return mWResult; } + + // do actual work of updating strings (non-inlined) + void updateResult() const; + void updateWResult() const; std::string mOrig; - std::string mResult; - LLWString mWResult; // for displaying + mutable std::string mResult; + mutable LLWString mWResult; // for displaying LLStringUtil::format_map_t mArgs; + + // controls lazy evaluation + mutable bool mNeedsResult; + mutable bool mNeedsWResult; }; #endif // LL_LLUISTRING_H diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 7694d02837..7350457274 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -197,6 +197,31 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) } // +// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com +// +LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol() +{ + mPattern = boost::regex("(\\bwww\\.\\S+\\.\\S+|\\S+.com\\S*|\\S+.net\\S*|\\S+.edu\\S*|\\S+.org\\S*)", + boost::regex::perl|boost::regex::icase); + mMenuName = "menu_url_http.xml"; + mTooltip = LLTrans::getString("TooltipHttpUrl"); +} + +std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + return unescapeUrl(url); +} + +std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) +{ + if (string.find("://") == std::string::npos) + { + return "http://" + escapeUrl(string); + } + return escapeUrl(string); +} + +// // LLUrlEntrySLURL Describes generic http: and https: Urls // LLUrlEntrySLURL::LLUrlEntrySLURL() diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index b3fb333fdd..4adffde99c 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -135,6 +135,17 @@ public: }; /// +/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com +/// +class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase +{ +public: + LLUrlEntryHTTPNoProtocol(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getUrl(const std::string &string); +}; + +/// /// LLUrlEntrySLURL Describes http://slurl.com/... Urls /// class LLUrlEntrySLURL : public LLUrlEntryBase diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index f47db2db1a..afcff0d409 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -58,6 +58,9 @@ LLUrlRegistry::LLUrlRegistry() //so it should be registered in the end of list registerUrl(new LLUrlEntrySL()); registerUrl(new LLUrlEntrySLLabel()); + // most common pattern is a URL without any protocol, + // e.g., "secondlife.com" + registerUrl(new LLUrlEntryHTTPNoProtocol()); } LLUrlRegistry::~LLUrlRegistry() @@ -118,10 +121,23 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en return true; } +static bool stringHasUrl(const std::string &text) +{ + // fast heuristic test for a URL in a string. This is used + // to avoid lots of costly regex calls, BUT it needs to be + // kept in sync with the LLUrlEntry regexes we support. + return (text.find("://") != std::string::npos || + text.find("www.") != std::string::npos || + text.find(".com") != std::string::npos || + text.find(".net") != std::string::npos || + text.find(".edu") != std::string::npos || + text.find(".org") != std::string::npos); +} + bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb) { // avoid costly regexes if there is clearly no URL in the text - if (text.find("://") == std::string::npos) + if (! stringHasUrl(text)) { return false; } diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp index 315baa001d..95e3692e10 100755 --- a/indra/llvfs/llpidlock.cpp +++ b/indra/llvfs/llpidlock.cpp @@ -41,6 +41,15 @@ #include "llframetimer.h" #if LL_WINDOWS //For windows platform. + +#include <windows.h> + +namespace { + inline DWORD getpid() { + return GetCurrentProcessId(); + } +} + bool isProcessAlive(U32 pid) { return (bool) GetProcessVersion((DWORD)pid); diff --git a/indra/llvfs/llpidlock.h b/indra/llvfs/llpidlock.h index 42aee4dc4f..496e99cf5a 100755 --- a/indra/llvfs/llpidlock.h +++ b/indra/llvfs/llpidlock.h @@ -37,17 +37,9 @@ class LLSD; class LLFrameTimer; -#if LL_WINDOWS //For windows platform. - -#include <windows.h> - -#define getpid GetCurrentProcessId - -#else //Everyone Else - +#if !LL_WINDOWS //For non-windows platforms. #include <signal.h> - -#endif //Everyone else. +#endif namespace LLPidLock { diff --git a/indra/lscript/lscript_export.h b/indra/lscript/lscript_export.h index d4626a8cd2..4c883582e2 100644 --- a/indra/lscript/lscript_export.h +++ b/indra/lscript/lscript_export.h @@ -35,6 +35,6 @@ #include "lscript_library.h" -extern LLScriptLibrary gScriptLibrary; + #endif diff --git a/indra/lscript/lscript_library.h b/indra/lscript/lscript_library.h index 6728d70d0a..363d11f3aa 100644 --- a/indra/lscript/lscript_library.h +++ b/indra/lscript/lscript_library.h @@ -70,7 +70,7 @@ public: std::vector<LLScriptLibraryFunction> mFunctions; }; -extern LLScriptLibrary gScriptLibrary; + class LLScriptLibData { @@ -428,4 +428,6 @@ public: }; +extern LLScriptLibrary gScriptLibrary; + #endif diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 276ad39dfb..707edaa3d6 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -211,7 +211,7 @@ private: LLQtWebKit::getInstance()->enablePlugins(true); #elif LL_DARWIN // Disable plugins - LLQtWebKit::getInstance()->enablePlugins(false); + LLQtWebKit::getInstance()->enablePlugins(true); #elif LL_LINUX // Disable plugins LLQtWebKit::getInstance()->enablePlugins(false); @@ -626,7 +626,11 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) } else if(message_name == "cleanup") { - // TODO: clean up here + // DTOR most likely won't be called but the recent change to the way this process + // is (not) killed means we see this message and can do what we need to here. + // Note: this cleanup is ultimately what writes cookies to the disk + LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); + LLQtWebKit::getInstance()->reset(); } else if(message_name == "shm_added") { @@ -635,7 +639,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) info.mSize = (size_t)message_in.getValueS32("size"); std::string name = message_in.getValue("name"); - // std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name // << ", size: " << info.mSize // << ", address: " << info.mAddress diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c808ec44df..431add2ab1 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -104,6 +104,7 @@ set(viewer_SOURCE_FILES llclassifiedstatsresponder.cpp llcloud.cpp llcolorswatch.cpp + llcommanddispatcherlistener.cpp llcommandhandler.cpp llcommandlineparser.cpp llcompilequeue.cpp @@ -227,7 +228,6 @@ set(viewer_SOURCE_FILES llgroupactions.cpp llgrouplist.cpp llgroupmgr.cpp - llgroupnotify.cpp llhomelocationresponder.cpp llhudeffect.cpp llhudeffectbeam.cpp @@ -298,7 +298,6 @@ set(viewer_SOURCE_FILES llnotificationofferhandler.cpp llnotificationscripthandler.cpp llnotificationtiphandler.cpp - llnotify.cpp lloutputmonitorctrl.cpp lloverlaybar.cpp llpanelavatar.cpp @@ -324,6 +323,7 @@ set(viewer_SOURCE_FILES llpanellandmarks.cpp llpanellandmedia.cpp llpanellogin.cpp + llpanelloginlistener.cpp llpanellookinfo.cpp llpanelmaininventory.cpp llpanelmediasettingsgeneral.cpp @@ -444,6 +444,7 @@ set(viewer_SOURCE_FILES lluploaddialog.cpp llurl.cpp llurldispatcher.cpp + llurldispatcherlistener.cpp llurlhistory.cpp llurllineeditorctrl.cpp llurlsimstring.cpp @@ -611,6 +612,7 @@ set(viewer_HEADER_FILES llclassifiedstatsresponder.h llcloud.h llcolorswatch.h + llcommanddispatcherlistener.h llcommandhandler.h llcommandlineparser.h llcompilequeue.h @@ -734,7 +736,6 @@ set(viewer_HEADER_FILES llgroupactions.h llgrouplist.h llgroupmgr.h - llgroupnotify.h llhomelocationresponder.h llhudeffect.h llhudeffectbeam.h @@ -800,7 +801,6 @@ set(viewer_HEADER_FILES llnetmap.h llnotificationhandler.h llnotificationmanager.h - llnotify.h lloutputmonitorctrl.h lloverlaybar.h llpanelavatar.h @@ -826,6 +826,7 @@ set(viewer_HEADER_FILES llpanellandmarks.h llpanellandmedia.h llpanellogin.h + llpanelloginlistener.h llpanellookinfo.h llpanelmaininventory.h llpanelmediasettingsgeneral.h @@ -950,6 +951,7 @@ set(viewer_HEADER_FILES lluploaddialog.h llurl.h llurldispatcher.h + llurldispatcherlistener.h llurlhistory.h llurllineeditorctrl.h llurlsimstring.h @@ -1780,3 +1782,5 @@ if (LL_TESTS) endif (LL_TESTS) + qtxmlpatternsd4.dll + qtxmlpatterns4.dll diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 80a3977d02..578f8fd4f0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1068,17 +1068,6 @@ <key>Value</key> <integer>23</integer> </map> - <key>ButtonVPad</key> - <map> - <key>Comment</key> - <string>Default vertical spacing between buttons (pixels)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>1</integer> - </map> <key>CacheLocation</key> <map> <key>Comment</key> @@ -3596,7 +3585,18 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://www.secondlife.com/</string> + <string>http://lecs.viewer-sidebar.secondlife.com.s3.amazonaws.com/sidebar.html</string> + </map> + <key>SearchURL</key> + <map> + <key>Comment</key> + <string>URL for Search website, displayed in the Find floater</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>http://int.searchwww-phx0.damballah.lindenlab.com/viewer/[CATEGORY]?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]</string> </map> <key>HighResSnapshot</key> <map> @@ -5038,7 +5038,18 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>35</integer> + <integer>5</integer> + </map> + <key>NotificationChannelHeightRatio</key> + <map> + <key>Comment</key> + <string>Notification channel and World View ratio(0.0 - always show 1 notification, 1.0 - max ratio).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.5</real> </map> <key>OverflowToastHeight</key> <map> @@ -5460,6 +5471,17 @@ <key>Value</key> <integer>13</integer> </map> + <key>PrimMediaMasterEnabled</key> + <map> + <key>Comment</key> + <string>Whether or not Media on a Prim is enabled.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>PrimMediaControlsUseHoverControlSet</key> <map> <key>Comment</key> @@ -5504,6 +5526,28 @@ <key>Value</key> <real>5.0</real> </map> + <key>PrimMediaMaxSortedQueueSize</key> + <map> + <key>Comment</key> + <string>Maximum number of objects the viewer will load media for initially</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>100000</integer> + </map> + <key>PrimMediaMaxRoundRobinQueueSize</key> + <map> + <key>Comment</key> + <string>Maximum number of objects the viewer will continuously update media for</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>100000</integer> + </map> <key>ProbeHardwareOnStartup</key> <map> <key>Comment</key> @@ -7517,45 +7561,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>SearchURLDefault</key> - <map> - <key>Comment</key> - <string>URL to load for empty searches</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>http://search.secondlife.com/client_search.php?</string> - </map> - <key>SearchURLQuery</key> - <map> - <key>Comment</key> - <string>URL to use for searches</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>http://search.secondlife.com/client_search.php?q=[QUERY]&s=[COLLECTION]&</string> - </map> - <key>SearchURLSuffix2</key> - <map> - <key>Comment</key> - <string>Parameters added to end of search queries</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>lang=[LANG]&mat=[MATURITY]&t=[TEEN]&region=[REGION]&x=[X]&y=[Y]&z=[Z]&session=[SESSION]</string> - </map> <key>SelectMovableOnly</key> <map> <key>Comment</key> diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index d7182dfaab..ae89eb4413 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -9283,7 +9283,7 @@ render_pass="bump"> wearable="skin" edit_group="skin_facedetail" edit_group_order="3" - name="wrinkles" + name="Wrinkles" label_min="Less" label_max="More" value_min="0" diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 2b582c90f0..628982973c 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -38,7 +38,6 @@ #include "llagentlistener.h" #include "llagentwearables.h" #include "llagentui.h" - #include "llanimationstates.h" #include "llbottomtray.h" #include "llcallingcard.h" @@ -65,6 +64,7 @@ #include "llsky.h" #include "llsmoothstep.h" #include "llstatusbar.h" +#include "llteleportflags.h" #include "lltool.h" #include "lltoolmgr.h" #include "lltrans.h" diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 3114a37ada..1e2eac39eb 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -41,7 +41,6 @@ #include "llinventoryobserver.h" #include "llinventorypanel.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llviewerregion.h" #include "llvoavatarself.h" #include "llwearable.h" diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index c06098689d..43b2f34ecd 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -455,7 +455,10 @@ void LLAppearanceManager::purgeCategory(const LLUUID& category, bool keep_outfit LLViewerInventoryItem *item = items.get(i); if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER)) continue; - gInventory.purgeObject(item->getUUID()); + if (item->getIsLinkType()) + { + gInventory.purgeObject(item->getUUID()); + } } } @@ -871,10 +874,48 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor (a->getWearableType() == b->getWearableType())); } +class LLDeferredCOFLinkObserver: public LLInventoryObserver +{ +public: + LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update): + mItemID(item_id), + mDoUpdate(do_update) + { + } + + ~LLDeferredCOFLinkObserver() + { + } + + /* virtual */ void changed(U32 mask) + { + const LLInventoryItem *item = gInventory.getItem(mItemID); + if (item) + { + gInventory.removeObserver(this); + LLAppearanceManager::instance().addCOFItemLink(item,mDoUpdate); + delete this; + } + } + +private: + const LLUUID mItemID; + bool mDoUpdate; +}; + + void LLAppearanceManager::addCOFItemLink(const LLUUID &item_id, bool do_update ) { const LLInventoryItem *item = gInventory.getItem(item_id); - addCOFItemLink(item, do_update); + if (!item) + { + LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update); + gInventory.addObserver(observer); + } + else + { + addCOFItemLink(item, do_update); + } } void LLAppearanceManager::addCOFItemLink(const LLInventoryItem *item, bool do_update ) @@ -909,7 +950,10 @@ void LLAppearanceManager::addCOFItemLink(const LLInventoryItem *item, bool do_up else if (areMatchingWearables(vitem,inv_item)) { gAgentWearables.removeWearable(inv_item->getWearableType(),true,0); - gInventory.purgeObject(inv_item->getUUID()); + if (inv_item->getIsLinkType()) + { + gInventory.purgeObject(inv_item->getUUID()); + } } } if (linked_already) @@ -958,10 +1002,9 @@ void LLAppearanceManager::removeCOFItemLinks(const LLUUID& item_id, bool do_upda for (S32 i=0; i<item_array.count(); i++) { const LLInventoryItem* item = item_array.get(i).get(); - if (item->getLinkedUUID() == item_id) + if (item->getIsLinkType() && item->getLinkedUUID() == item_id) { - const LLUUID& item_id = item_array.get(i)->getUUID(); - gInventory.purgeObject(item_id); + gInventory.purgeObject(item->getUUID()); } } if (do_update) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 508badcc6f..07b3399637 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -39,7 +39,6 @@ #include "llfeaturemanager.h" #include "lluictrlfactory.h" #include "lltexteditor.h" -#include "llalertdialog.h" #include "llerrorcontrol.h" #include "llviewertexturelist.h" #include "llgroupmgr.h" @@ -78,16 +77,21 @@ #include "lllocationhistory.h" #include "llfasttimerview.h" #include "llvoicechannel.h" +#include "llsidetray.h" + #include "llweb.h" #include "llsecondlifeurls.h" // Linden library includes +#include "llimagej2c.h" #include "llmemory.h" #include "llprimitive.h" #include "llurlaction.h" +#include "llvfile.h" #include "llvfsthread.h" #include "llvolumemgr.h" +#include "llxfermanager.h" #include "llnotificationmanager.h" #include "llnotifications.h" @@ -107,7 +111,6 @@ #include "apr_dso.h" #include <boost/lexical_cast.hpp> -#include "llnotify.h" #include "llviewerkeyboard.h" #include "lllfsthread.h" #include "llworkerthread.h" @@ -389,7 +392,6 @@ bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue) static void settings_to_globals() { LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad"); - LLBUTTON_V_PAD = gSavedSettings.getS32("ButtonVPad"); BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall"); BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight"); @@ -744,7 +746,15 @@ bool LLAppViewer::init() LLViewerJointMesh::updateVectorize(); // load MIME type -> media impl mappings - LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") ); + std::string mime_types_name; +#if LL_DARWIN + mime_types_name = "mime_types_mac.xml"; +#elif LL_LINUX + mime_types_name = "mime_types_linux.xml"; +#else + mime_types_name = "mime_types.xml"; +#endif + LLMIMETypes::parseMIMETypes( mime_types_name ); // Copy settings to globals. *TODO: Remove or move to appropriage class initializers settings_to_globals(); @@ -2854,6 +2864,8 @@ void LLAppViewer::requestQuit() gFloaterView->closeAllChildren(true); } + LLSideTray::getInstance()->notifyChildren(LLSD().with("request","quit")); + send_stats(); gLogoutTimer.reset(); @@ -3758,6 +3770,13 @@ void LLAppViewer::idleShutdown() { return; } + + if (LLSideTray::getInstance()->notifyChildren(LLSD().with("request","wait_quit"))) + { + return; + } + + // ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup() // *TODO: ugly diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index c1bfbca868..40e74061b5 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -325,6 +325,7 @@ extern BOOL gUseWireframe; // VFS globals - gVFS is for general use // gStaticVFS is read-only and is shipped w/ the viewer // it has pre-cache data like the UI .TGAs +class LLVFS; extern LLVFS *gStaticVFS; extern LLMemoryInfo gSysMemory; diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 1d03cc8823..a2322e28b4 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -39,7 +39,6 @@ #include "llcompilequeue.h" #include "llfloaterbuycurrency.h" #include "llfilepicker.h" -#include "llnotify.h" #include "llinventoryobserver.h" #include "llinventorypanel.h" #include "llpermissionsflags.h" diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 5f90a7627f..33dc7ee2c8 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -61,6 +61,7 @@ #include "llviewerregion.h" #include "llimfloater.h" #include "lltrans.h" +#include "llcallingcard.h" // static void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name) @@ -265,6 +266,24 @@ bool LLAvatarActions::isCalling(const LLUUID &id) return (LLIMModel::getInstance()->findIMSession(session_id) != NULL); } +//static +bool LLAvatarActions::canCall(const LLUUID &id) +{ + if(isFriend(id)) + { + return LLAvatarTracker::instance().isBuddyOnline(id) && LLVoiceClient::voiceEnabled(); + } + else + { + // don't need to check online/offline status because "usual resident" (resident that is not a friend) + // can be only ONLINE. There is no way to see "usual resident" in OFFLINE status. If we see "usual + // resident" it automatically means that the resident is ONLINE. So to make a call to the "usual resident" + // we need to check only that "our" voice is enabled. + return LLVoiceClient::voiceEnabled(); + } + +} + // static void LLAvatarActions::startConference(const std::vector<LLUUID>& ids) { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 2dd2a4c4b1..01c18d4228 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -129,6 +129,11 @@ public: static bool isCalling(const LLUUID &id); /** + * @return true if call to the resident can be made (resident is online and voice is enabled) + */ + + static bool canCall(const LLUUID &id); + /** * Invite avatar to a group. */ static void inviteToGroup(const LLUUID& id); diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index 7cda2d31e6..33e5046f50 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -440,11 +440,17 @@ void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, E // Copy the map (because observers may delete themselves when updated?) LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers; - observer_multimap_t::iterator oi = observers.lower_bound(id); - observer_multimap_t::iterator end = observers.upper_bound(id); + observer_multimap_t::iterator oi = observers.begin(); + observer_multimap_t::iterator end = observers.end(); for (; oi != end; ++oi) { - oi->second->processProperties(data,type); + // only notify observers for the same agent, or if the observer + // didn't know the agent ID and passed a NULL id. + const LLUUID &agent_id = oi->first; + if (agent_id == id || agent_id.isNull()) + { + oi->second->processProperties(data,type); + } } } diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 895b4ed80e..2f5523e04d 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -33,8 +33,12 @@ #include "llviewerprecompiledheaders.h" +#include "llnotificationsutil.h" +#include "lltrans.h" + #include "llcallfloater.h" +#include "llagent.h" #include "llagentdata.h" // for gAgentID #include "llavatarlist.h" #include "llbottomtray.h" @@ -79,8 +83,12 @@ LLCallFloater::LLCallFloater(const LLSD& key) , mAvatarList(NULL) , mNonAvatarCaller(NULL) , mVoiceType(VC_LOCAL_CHAT) +, mAgentPanel(NULL) +, mSpeakingIndicator(NULL) +, mIsModeratorMutedVoice(false) { mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL); + LLVoiceClient::getInstance()->addObserver(this); } LLCallFloater::~LLCallFloater() @@ -88,6 +96,13 @@ LLCallFloater::~LLCallFloater() mChannelChangedConnection.disconnect(); delete mPaticipants; mPaticipants = NULL; + + // Don't use LLVoiceClient::getInstance() here + // singleton MAY have already been destroyed. + if(gVoiceClient) + { + gVoiceClient->removeObserver(this); + } } // virtual @@ -120,6 +135,34 @@ void LLCallFloater::onOpen(const LLSD& /*key*/) { } +// virtual +void LLCallFloater::draw() +{ + // we have to refresh participants to display ones not in voice as disabled. + // It should be done only when she joins or leaves voice chat. + // But seems that LLVoiceClientParticipantObserver is not enough to satisfy this requirement. + // *TODO: mantipov: remove from draw() + onChange(); + + bool is_moderator_muted = gVoiceClient->getIsModeratorMuted(gAgentID); + + if (mIsModeratorMutedVoice != is_moderator_muted) + { + setModeratorMutedVoice(is_moderator_muted); + } + + LLDockableFloater::draw(); +} + +// virtual +void LLCallFloater::onChange() +{ + if (NULL == mPaticipants) return; + + mPaticipants->refreshVoiceState(); +} + + ////////////////////////////////////////////////////////////////////////// /// PRIVATE SECTION ////////////////////////////////////////////////////////////////////////// @@ -165,9 +208,19 @@ void LLCallFloater::updateSession() mVoiceType = VC_PEER_TO_PEER; break; case IM_SESSION_CONFERENCE_START: - mVoiceType = VC_AD_HOC_CHAT; + case IM_SESSION_GROUP_START: + case IM_SESSION_INVITE: + if (gAgent.isInGroup(session_id)) + { + mVoiceType = VC_GROUP_CHAT; + } + else + { + mVoiceType = VC_AD_HOC_CHAT; + } break; default: + llwarning("Failed to determine voice call IM type", 0); mVoiceType = VC_GROUP_CHAT; break; } @@ -188,6 +241,7 @@ void LLCallFloater::updateSession() childSetVisible("leave_btn_panel", !is_local_chat); refreshPartisipantList(); + updateModeratorState(); } void LLCallFloater::refreshPartisipantList() @@ -220,11 +274,20 @@ void LLCallFloater::refreshPartisipantList() { mAvatarList->setNoItemsCommentText(getString("no_one_near")); } + mPaticipants->refreshVoiceState(); } } void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/) { + // Don't update participant list if no channel info is available. + // Fix for ticket EXT-3427 + // @see LLParticipantList::~LLParticipantList() + if(LLVoiceChannel::getCurrentVoiceChannel() && + LLVoiceChannel::STATE_NO_CHANNEL_INFO == LLVoiceChannel::getCurrentVoiceChannel()->getState()) + { + return; + } // Forget speaker manager from the previous session to avoid using it after session was destroyed. mSpeakerManager = NULL; updateSession(); @@ -263,13 +326,52 @@ void LLCallFloater::updateTitle() void LLCallFloater::initAgentData() { - childSetValue("user_icon", gAgentID); + mAgentPanel = getChild<LLPanel> ("my_panel"); + + if ( mAgentPanel ) + { + mAgentPanel->childSetValue("user_icon", gAgentID); + + std::string name; + gCacheName->getFullName(gAgentID, name); + mAgentPanel->childSetValue("user_text", name); + + mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator"); + mSpeakingIndicator->setSpeakerId(gAgentID); + } +} + +void LLCallFloater::setModeratorMutedVoice(bool moderator_muted) +{ + mIsModeratorMutedVoice = moderator_muted; + if (moderator_muted) + { + LLNotificationsUtil::add("VoiceIsMutedByModerator"); + } + mSpeakingIndicator->setIsMuted(moderator_muted); +} + +void LLCallFloater::updateModeratorState() +{ std::string name; gCacheName->getFullName(gAgentID, name); - childSetValue("user_text", name); - LLOutputMonitorCtrl* speaking_indicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); - speaking_indicator->setSpeakerId(gAgentID); + if(gAgent.isInGroup(mSpeakerManager->getSessionID())) + { + // This method can be called when LLVoiceChannel.mState == STATE_NO_CHANNEL_INFO + // in this case there are no any speakers yet. + if (mSpeakerManager->findSpeaker(gAgentID)) + { + // Agent is Moderator + if (mSpeakerManager->findSpeaker(gAgentID)->mIsModerator) + + { + const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); + name += " " + moderator_indicator; + } + } + } + mAgentPanel->childSetValue("user_text", name); } //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index b615f57d5b..b2288a42ff 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -35,12 +35,13 @@ #define LL_LLCALLFLOATER_H #include "lldockablefloater.h" +#include "llvoiceclient.h" class LLAvatarList; class LLNonAvatarCaller; +class LLOutputMonitorCtrl; class LLParticipantList; class LLSpeakerMgr; - /** * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron on the Speak button. * It can be torn-off and freely positioned onscreen. @@ -52,7 +53,7 @@ class LLSpeakerMgr; * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel also provides an * 'Leave Call' button to allow the Resident to leave that voice channel. */ -class LLCallFloater : public LLDockableFloater +class LLCallFloater : public LLDockableFloater, LLVoiceClientParticipantObserver { public: LLCallFloater(const LLSD& key); @@ -60,6 +61,14 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void draw(); + + /** + * Is called by LLVoiceClient::notifyParticipantObservers when voice participant list is changed. + * + * Refreshes list to display participants not in voice as disabled. + */ + /*virtual*/ void onChange(); private: typedef enum e_voice_controls_type @@ -87,6 +96,8 @@ private: void onCurrentChannelChanged(const LLUUID& session_id); void updateTitle(); void initAgentData(); + void setModeratorMutedVoice(bool moderator_muted); + void updateModeratorState(); private: LLSpeakerMgr* mSpeakerManager; @@ -94,6 +105,9 @@ private: LLAvatarList* mAvatarList; LLNonAvatarCaller* mNonAvatarCaller; EVoiceControls mVoiceType; + LLPanel* mAgentPanel; + LLOutputMonitorCtrl* mSpeakingIndicator; + bool mIsModeratorMutedVoice; boost::signals2::connection mChannelChangedConnection; }; diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 714bd20ab8..82413878ad 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -55,7 +55,6 @@ #include "llinventorymodel.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llresmgr.h" #include "llimview.h" #include "llviewercontrol.h" diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 415c118ff1..cbb566b3a7 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -228,3 +228,14 @@ void LLChannelManager::muteAllChannels(bool mute) } } +void LLChannelManager::killToastsFromChannel(const LLUUID& channel_id, const LLScreenChannel::Matcher& matcher) +{ + LLScreenChannel + * screen_channel = + dynamic_cast<LLScreenChannel*> (findChannelByID(channel_id)); + if (screen_channel != NULL) + { + screen_channel->killMatchedToasts(matcher); + } +} + diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index 4b66a1ef89..c2be39122f 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -109,6 +109,11 @@ public: */ void muteAllChannels(bool mute); + /** + * Kills matched toasts from specified toast screen channel. + */ + void killToastsFromChannel(const LLUUID& channel_id, const LLScreenChannel::Matcher& matcher); + private: LLScreenChannel* createChannel(LLChannelManager::Params& p); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index efe9ea4c35..ee60df1b4b 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -49,6 +49,8 @@ static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history"); +const static std::string NEW_LINE(rawstr_to_utf8("\n")); + class LLChatHistoryHeader: public LLPanel { public: @@ -332,12 +334,12 @@ LLChatHistory::~LLChatHistory() { static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0); - LLRect old_text_rect = mTextRect; - mTextRect = mScroller->getContentWindowRect(); - mTextRect.stretch(-texteditor_border); - mTextRect.mLeft += mLeftTextPad; - mTextRect.mRight -= mRightTextPad; - if (mTextRect != old_text_rect) + LLRect old_text_rect = mVisibleTextRect; + mVisibleTextRect = mScroller->getContentWindowRect(); + mVisibleTextRect.stretch(-texteditor_border); + mVisibleTextRect.mLeft += mLeftTextPad; + mVisibleTextRect.mRight -= mRightTextPad; + if (mVisibleTextRect != old_text_rect) { needsReflow(); } @@ -454,10 +456,21 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ if (chat.mFromName.size() > 0) appendText(chat.mFromName + " ", TRUE, style_params); - appendText(chat.mText.substr(4), FALSE, style_params); + // Ensure that message ends with NewLine, to avoid losing of new lines + // while copy/paste from text chat. See EXT-3263. + appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params); } else - appendText(chat.mText, FALSE, style_params); + { + std::string message(chat.mText); + if ( message.size() > 0 && !LLStringOps::isSpace(message[message.size() - 1]) ) + { + // Ensure that message ends with NewLine, to avoid losing of new lines + // while copy/paste from text chat. See EXT-3263. + message += NEW_LINE; + } + appendText(message, FALSE, style_params); + } blockUndo(); } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 4b3b7a99d8..c7f77810df 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -53,6 +53,7 @@ #include "llgroupmgr.h" #include "llnotificationmanager.h" #include "lltransientfloatermgr.h" +#include "llsyswellwindow.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); static LLDefaultChildRegistry::Register<LLIMWellChiclet> t2_0("chiclet_im_well"); @@ -61,6 +62,7 @@ static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p"); static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group"); static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc"); static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script"); +static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer"); static const LLRect CHICLET_RECT(0, 25, 25, 0); static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0); @@ -78,29 +80,91 @@ boost::signals2::signal<LLChiclet* (const LLUUID&), ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +/** + * Updates the Well's 'Lit' state to flash it when "new messages" are come. + * + * It gets callback which will be called 2*N times with passed period. See EXT-3147 + */ +class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer +{ +public: + typedef boost::function<void()> callback_t; + + /** + * Constructor. + * + * @param count - how many times callback should be called (twice to not change original state) + * @param period - how frequently callback should be called + * @param cb - callback to be called each tick + */ + FlashToLitTimer(S32 count, F32 period, callback_t cb) + : LLEventTimer(period) + , mCallback(cb) + , mFlashCount(2 * count) + , mCurrentFlashCount(0) + { + mEventTimer.stop(); + } + + BOOL tick() + { + mCallback(); + + if (++mCurrentFlashCount == mFlashCount) mEventTimer.stop(); + return FALSE; + } + + void flash() + { + mCurrentFlashCount = 0; + mEventTimer.start(); + } + + void stopFlashing() + { + mEventTimer.stop(); + } + +private: + callback_t mCallback; + + /** + * How many times Well will blink. + */ + S32 mFlashCount; + S32 mCurrentFlashCount; +}; + LLSysWellChiclet::Params::Params() : button("button") , unread_notifications("unread_notifications") +, max_displayed_count("max_displayed_count", 9) +, flash_to_lit_count("flash_to_lit_count", 3) +, flash_period("flash_period", 0.5F) { button.name("button"); button.tab_stop(FALSE); button.label(LLStringUtil::null); - } LLSysWellChiclet::LLSysWellChiclet(const Params& p) : LLChiclet(p) , mButton(NULL) , mCounter(0) +, mMaxDisplayedCount(p.max_displayed_count) +, mIsNewMessagesState(false) +, mFlashToLitTimer(NULL) { LLButton::Params button_params = p.button; mButton = LLUICtrlFactory::create<LLButton>(button_params); addChild(mButton); + + mFlashToLitTimer = new FlashToLitTimer(p.flash_to_lit_count, p.flash_period, boost::bind(&LLSysWellChiclet::changeLitState, this)); } LLSysWellChiclet::~LLSysWellChiclet() { - + delete mFlashToLitTimer; } void LLSysWellChiclet::setCounter(S32 counter) @@ -108,11 +172,30 @@ void LLSysWellChiclet::setCounter(S32 counter) std::string s_count; if(counter != 0) { - s_count = llformat("%d", counter); + static std::string more_messages_exist("+"); + std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : ""); + s_count = llformat("%d%s" + , llmin(counter, mMaxDisplayedCount) + , more_messages.c_str() + ); } mButton->setLabel(s_count); + setNewMessagesState(counter > 0); + + // we have to flash to 'Lit' state each time new unread message is comming. + if (counter > mCounter) + { + mFlashToLitTimer->flash(); + } + else if (counter == 0) + { + // if notification is resolved while well is flashing it can leave in the 'Lit' state + // when flashing finishes itself. Let break flashing here. + mFlashToLitTimer->stopFlashing(); + } + mCounter = counter; } @@ -126,6 +209,25 @@ void LLSysWellChiclet::setToggleState(BOOL toggled) { mButton->setToggleState(toggled); } +void LLSysWellChiclet::changeLitState() +{ + setNewMessagesState(!mIsNewMessagesState); +} + +void LLSysWellChiclet::setNewMessagesState(bool new_messages) +{ + /* + Emulate 4 states of button by background images, see detains in EXT-3147 + xml attribute Description + image_unselected "Unlit" - there are no new messages + image_selected "Unlit" + "Selected" - there are no new messages and the Well is open + image_pressed "Lit" - there are new messages + image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open + */ + mButton->setForcePressedState(new_messages); + + mIsNewMessagesState = new_messages; +} /************************************************************************/ /* LLIMWellChiclet implementation */ @@ -137,6 +239,8 @@ LLIMWellChiclet::LLIMWellChiclet(const Params& p) LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1)); LLIMMgr::getInstance()->addSessionObserver(this); + + LLIMWellWindow::getInstance()->setSysWellChiclet(this); } LLIMWellChiclet::~LLIMWellChiclet() @@ -161,6 +265,10 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) connectCounterUpdatersToSignal("notify"); connectCounterUpdatersToSignal("groupnotify"); connectCounterUpdatersToSignal("offer"); + + // ensure that notification well window exists, to synchronously + // handle toast add/delete events. + LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); } void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) @@ -939,12 +1047,34 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){ } } +void object_chiclet_callback(const LLSD& data) +{ + LLUUID object_id = data["object_id"]; + bool new_message = data["new_message"]; + + std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(object_id); + std::list<LLChiclet *>::iterator iter; + for (iter = chiclets.begin(); iter != chiclets.end(); iter++) + { + LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter); + if (chiclet != NULL) + { + if(data.has("unread")) + { + chiclet->setCounter(data["unread"]); + } + chiclet->setShowNewMessagesIcon(new_message); + } + } +} BOOL LLChicletPanel::postBuild() { LLPanel::postBuild(); LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1)); LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1)); + LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(object_chiclet_callback, _1)); + LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(object_chiclet_callback, _1)); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1)); LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1)); @@ -1545,6 +1675,11 @@ void LLScriptChiclet::setSessionId(const LLUUID& session_id) } } +void LLScriptChiclet::setCounter(S32 counter) +{ + setShowNewMessagesIcon( counter > 0 ); +} + void LLScriptChiclet::onMouseDown() { LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId()); @@ -1601,6 +1736,11 @@ void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) } } +void LLInvOfferChiclet::setCounter(S32 counter) +{ + setShowNewMessagesIcon( counter > 0 ); +} + void LLInvOfferChiclet::onMouseDown() { LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId()); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 609ce16713..353fc01c34 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -315,7 +315,7 @@ public: { Optional<std::string> new_messages_icon_name; - Params() : new_messages_icon_name("new_messages_icon_name", "icn_voice-localchat.tga") + Params() : new_messages_icon_name("new_messages_icon_name", "Unread_IM") {} }; @@ -389,7 +389,7 @@ public: * Made public so that it can be triggered from outside * (more specifically, from the Active IM window). */ - void onMouseDown(); + virtual void onMouseDown(); protected: @@ -594,7 +594,7 @@ public: /*virtual*/ void setSessionId(const LLUUID& session_id); - /*virtual*/ void setCounter(S32 counter){} + /*virtual*/ void setCounter(S32 counter); /*virtual*/ S32 getCounter() { return 0; } @@ -634,7 +634,7 @@ public: /*virtual*/ void setSessionId(const LLUUID& session_id); - /*virtual*/ void setCounter(S32 counter){} + /*virtual*/ void setCounter(S32 counter); /*virtual*/ S32 getCounter() { return 0; } @@ -745,7 +745,7 @@ private: /** * Implements notification chiclet. Used to display total amount of unread messages - * across all IM sessions, total amount of system notifications. + * across all IM sessions, total amount of system notifications. See EXT-3147 for details */ class LLSysWellChiclet : public LLChiclet { @@ -757,6 +757,24 @@ public: Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; + /** + * Contains maximum displayed count of unread messages. Default value is 9. + * + * If count is less than "max_unread_count" will be displayed as is. + * Otherwise 9+ will be shown (for default value). + */ + Optional<S32> max_displayed_count; + + /** + * How many time chiclet should flash before set "Lit" state. Default value is 3. + */ + Optional<S32> flash_to_lit_count; + + /** + * Period of flashing while setting "Lit" state, in seconds. Default value is 0.5. + */ + Optional<F32> flash_period; + Params(); }; @@ -773,14 +791,30 @@ public: void setToggleState(BOOL toggled); + void setNewMessagesState(bool new_messages); + protected: LLSysWellChiclet(const Params& p); friend class LLUICtrlFactory; + /** + * Change Well 'Lit' state from 'Lit' to 'Unlit' and vice-versa. + * + * There is an assumption that it will be called 2*N times to do not change its start state. + * @see FlashToLitTimer + */ + void changeLitState(); + protected: + class FlashToLitTimer; LLButton* mButton; S32 mCounter; + S32 mMaxDisplayedCount; + bool mIsNewMessagesState; + + FlashToLitTimer* mFlashToLitTimer; + }; /** diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index b2399d238b..dc6847f236 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -306,13 +306,16 @@ void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op ) } } -void LLColorSwatchCtrl::onFloaterClose() +// This is called when the main floatercustomize panel is closed. +// Since this class has pointers up to its parents, we need to cleanup +// this class first in order to avoid a crash. +void LLColorSwatchCtrl::onParentFloaterClosed() { LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get(); - if (pickerp) { pickerp->setSwatch(NULL); + pickerp->closeFloater(); } mPickerHandle.markDead(); diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h index 2f6aec85e8..4bb7d837cb 100644 --- a/indra/newview/llcolorswatch.h +++ b/indra/newview/llcolorswatch.h @@ -105,7 +105,7 @@ public: /*virtual*/ void setEnabled( BOOL enabled ); static void onColorChanged ( void* data, EColorPickOp pick_op = COLOR_CHANGE ); - void onFloaterClose(); + void onParentFloaterClosed(); protected: BOOL mValid; diff --git a/indra/newview/llcommanddispatcherlistener.cpp b/indra/newview/llcommanddispatcherlistener.cpp new file mode 100644 index 0000000000..00a20de30e --- /dev/null +++ b/indra/newview/llcommanddispatcherlistener.cpp @@ -0,0 +1,47 @@ +/** + * @file llcommanddispatcherlistener.cpp + * @author Nat Goodspeed + * @date 2009-12-10 + * @brief Implementation for llcommanddispatcherlistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llcommanddispatcherlistener.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llcommandhandler.h" + +LLCommandDispatcherListener::LLCommandDispatcherListener(/* LLCommandDispatcher* instance */): + LLEventAPI("LLCommandDispatcher", "Access to LLCommandHandler commands") /* , + mDispatcher(instance) */ +{ + add("dispatch", + "Execute a command registered as an LLCommandHandler,\n" + "passing any required parameters:\n" + "[\"cmd\"] string command name\n" + "[\"params\"] array of parameters, as if from components of URL path\n" + "[\"query\"] map of parameters, as if from ?key1=val&key2=val\n" + "[\"trusted\"] boolean indicating trusted browser [default true]", + &LLCommandDispatcherListener::dispatch); +} + +void LLCommandDispatcherListener::dispatch(const LLSD& params) const +{ + // For most purposes, we expect callers to want to be trusted. + bool trusted_browser = true; + if (params.has("trusted")) + { + // But for testing, allow a caller to specify untrusted. + trusted_browser = params["trusted"].asBoolean(); + } + LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], NULL, + trusted_browser); +} diff --git a/indra/newview/llcommanddispatcherlistener.h b/indra/newview/llcommanddispatcherlistener.h new file mode 100644 index 0000000000..d0070ddd71 --- /dev/null +++ b/indra/newview/llcommanddispatcherlistener.h @@ -0,0 +1,30 @@ +/** + * @file llcommanddispatcherlistener.h + * @author Nat Goodspeed + * @date 2009-12-10 + * @brief LLEventAPI for LLCommandDispatcher + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLCOMMANDDISPATCHERLISTENER_H) +#define LL_LLCOMMANDDISPATCHERLISTENER_H + +#include "lleventapi.h" +class LLCommandDispatcher; +class LLSD; + +class LLCommandDispatcherListener: public LLEventAPI +{ +public: + LLCommandDispatcherListener(/* LLCommandDispatcher* instance */); // all static members + +private: + void dispatch(const LLSD& params) const; + + //LLCommandDispatcher* mDispatcher; +}; + +#endif /* ! defined(LL_LLCOMMANDDISPATCHERLISTENER_H) */ diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 1d92661ea2..8c7e7bea83 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -35,12 +35,15 @@ #include "llcommandhandler.h" #include "llnotificationsutil.h" +#include "llcommanddispatcherlistener.h" // system includes #include <boost/tokenizer.hpp> #define THROTTLE_PERIOD 15 // required secs between throttled commands +static LLCommandDispatcherListener sCommandDispatcherListener; + //--------------------------------------------------------------------------- // Underlying registry for command handlers, not directly accessible. //--------------------------------------------------------------------------- diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp index 411cb331a8..ead377deb0 100644 --- a/indra/newview/lldelayedgestureerror.cpp +++ b/indra/newview/lldelayedgestureerror.cpp @@ -36,7 +36,6 @@ #include <list> #include "llnotificationsutil.h" -#include "llnotify.h" #include "llcallbacklist.h" #include "llinventory.h" #include "llviewerinventory.h" diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index b64799bd86..edfb9dc864 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -37,7 +37,6 @@ #include "llnotificationsutil.h" #include "message.h" -#include "llnotify.h" #include "lleventinfo.h" #include "llfloaterreg.h" #include "llfloaterworldmap.h" diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index bd6936f05c..9c37c953fe 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -51,8 +51,16 @@ public: /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { // more label always spans width of text box - width = mEditor.getTextRect().getWidth() - mEditor.getHPad(); - height = llceil(mStyle->getFont()->getLineHeight()); + if (num_chars == 0) + { + width = 0; + height = 0; + } + else + { + width = mEditor.getDocumentView()->getRect().getWidth() - mEditor.getHPad(); + height = llceil(mStyle->getFont()->getLineHeight()); + } return true; } /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const @@ -104,7 +112,8 @@ private: LLExpandableTextBox::LLTextBoxEx::Params::Params() : more_label("more_label") -{} +{ +} LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p) : LLTextBox(p), @@ -117,16 +126,13 @@ LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p) void LLExpandableTextBox::LLTextBoxEx::reshape(S32 width, S32 height, BOOL called_from_parent) { + hideExpandText(); LLTextBox::reshape(width, height, called_from_parent); if (getTextPixelHeight() > getRect().getHeight()) { showExpandText(); } - else - { - hideExpandText(); - } } void LLExpandableTextBox::LLTextBoxEx::setText(const LLStringExplicit& text,const LLStyle::Params& input_params) @@ -317,7 +323,8 @@ void LLExpandableTextBox::expandTextBox() mTextBox->hideExpandText(); S32 text_delta = mTextBox->getVerticalTextDelta(); - text_delta += mTextBox->getVPad() * 2 + mScroll->getBorderWidth() * 2; + text_delta += mTextBox->getVPad() * 2; + text_delta += mScroll->getBorderWidth() * 2; // no need to expand if(text_delta <= 0) { diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index ab2455620f..7ecbc3db60 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -64,11 +64,6 @@ extern "C" { #if LL_GTK # include "gtk/gtk.h" #endif // LL_GTK - -// also mostly for Linux, for some X11-specific filepicker usability tweaks -#if LL_X11 -#include "SDL/SDL_syswm.h" -#endif } class LLFilePicker diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index 0bcdad5da1..7fd0e070be 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -40,7 +40,6 @@ // viewer includes #include "llagent.h" // for gAgent.inPrelude() -#include "llnotify.h" #include "llviewercontrol.h" #include "llui.h" #include "llappviewer.h" diff --git a/indra/newview/llfloateranimpreview.h b/indra/newview/llfloateranimpreview.h index 09b04f1f42..dd2c0b809a 100644 --- a/indra/newview/llfloateranimpreview.h +++ b/indra/newview/llfloateranimpreview.h @@ -33,6 +33,7 @@ #ifndef LL_LLFLOATERANIMPREVIEW_H #define LL_LLFLOATERANIMPREVIEW_H +#include "llassettype.h" #include "llfloaternamedesc.h" #include "lldynamictexture.h" #include "llcharacter.h" diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index b63bcccf6b..698ccec9c1 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -35,7 +35,6 @@ #include "llfloaterauction.h" #include "llfloaterregioninfo.h" -#include "lldir.h" #include "llgl.h" #include "llimagej2c.h" #include "llimagetga.h" @@ -43,12 +42,12 @@ #include "llvfile.h" #include "llvfs.h" #include "llwindow.h" +#include "message.h" #include "llagent.h" #include "llcombobox.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llsavedsettingsglue.h" #include "llviewertexturelist.h" #include "llviewerparcelmgr.h" diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index 68f06b1e5b..e925796526 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -33,11 +33,11 @@ #include "llviewerprecompiledheaders.h" -#include "llfloaterbump.h" +#include "llsd.h" +#include "mean_collision_data.h" +#include "llfloaterbump.h" #include "llscrolllistctrl.h" - -#include "llsd.h" #include "lluictrlfactory.h" #include "llviewermessage.h" diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index 16a5bb63e7..fba557c656 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -41,7 +41,6 @@ #include "llfloaterbuy.h" #include "llagent.h" // for agent id -#include "llalertdialog.h" #include "llinventorymodel.h" // for gInventory #include "llfloaterreg.h" #include "llfloaterinventory.h" // for get_item_icon diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index 39c7bc02af..0daef27af2 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -43,7 +43,6 @@ #include "llcachename.h" #include "llagent.h" // for agent id -#include "llalertdialog.h" #include "llcheckboxctrl.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" // for gInventory diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 3a8c3ab4d2..9b88923e7e 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -49,7 +49,6 @@ #include "lliconctrl.h" #include "lllineeditor.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llparcel.h" #include "llslurl.h" #include "llstatusbar.h" diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 57bb93d81a..b9e0f928f1 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -41,6 +41,7 @@ // project include #include "llagent.h" +#include "llappviewer.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -142,6 +143,10 @@ BOOL LLFloaterChat::postBuild() void LLFloaterChat::updateConsoleVisibility() { + if(gDisconnected) + { + return; + } // determine whether we should show console due to not being visible gConsole->setVisible( !isInVisibleChain() // are we not in part of UI being drawn? || isMinimized() // are we minimized? diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 56b56dc3d2..73b79d8e13 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -241,16 +241,6 @@ BOOL LLFloaterColorPicker::postBuild() return TRUE; } -/*virtual*/ -void LLFloaterColorPicker::onClose(bool app_settings) -{ - if (mSwatch) - { - mSwatch->onFloaterClose(); - } - stopUsingPipette(); -} - ////////////////////////////////////////////////////////////////////////////// // void LLFloaterColorPicker::initUI ( F32 rValIn, F32 gValIn, F32 bValIn ) diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h index b381740acd..0bbbe2051c 100644 --- a/indra/newview/llfloatercolorpicker.h +++ b/indra/newview/llfloatercolorpicker.h @@ -56,7 +56,6 @@ class LLFloaterColorPicker // overrides virtual BOOL postBuild (); - virtual void onClose(bool app_settings); virtual void draw (); virtual BOOL handleMouseDown ( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseUp ( S32 x, S32 y, MASK mask ); diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 1482d3fe21..56291c57a6 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -50,7 +50,6 @@ #include "llinventorymodel.h" #include "llnamelistctrl.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llresmgr.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index 04ba11530a..e1409b8ad5 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -45,7 +45,6 @@ #include "message.h" #include "llagent.h" -#include "llalertdialog.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -69,7 +68,6 @@ #include "llviewerwindow.h" #include "llworld.h" #include "llfloateravatarpicker.h" -#include "llnotify.h" #include "llxfermanager.h" #include "llvlcomposition.h" #include "llsurface.h" diff --git a/indra/newview/llfloaterhud.cpp b/indra/newview/llfloaterhud.cpp index 14cff3bcc3..d2ee3e44c5 100644 --- a/indra/newview/llfloaterhud.cpp +++ b/indra/newview/llfloaterhud.cpp @@ -37,7 +37,6 @@ // Viewer libs #include "llviewercontrol.h" #include "llmediactrl.h" -#include "llalertdialog.h" // Linden libs #include "llnotificationsutil.h" diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index ed0f24d160..66bf5246b0 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -55,7 +55,6 @@ #include "llavataractions.h" #include "lllineeditor.h" #include "llnamelistctrl.h" -#include "llnotify.h" #include "llpanellandaudio.h" #include "llpanellandmedia.h" #include "llradiogroup.h" @@ -2300,7 +2299,7 @@ void LLPanelLandAccess::refresh() mListBanned->deleteAllItems(); LLParcel *parcel = mParcel->getParcel(); - + // Display options if (parcel) { @@ -2396,22 +2395,40 @@ void LLPanelLandAccess::refresh() mListBanned->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix); } } + + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + if(region) + { + std::string region_access = "("; + region_access += region->getSimAccessString(); + region_access += ")"; + childSetLabelArg( "public_access", "[MATURITY]", region_access ); + } + else + { + childSetLabelArg( "public_access", "[MATURITY]", std::string() ); + } + if(parcel->getRegionDenyAnonymousOverride()) { childSetValue("limit_payment", TRUE); + childSetLabelArg( "limit_payment", "[ESTATE_PAYMENT_LIMIT]", getString("access_estate_defined") ); } else { childSetValue("limit_payment", (parcel->getParcelFlag(PF_DENY_ANONYMOUS))); + childSetLabelArg( "limit_payment", "[ESTATE_PAYMENT_LIMIT]", std::string() ); } if(parcel->getRegionDenyAgeUnverifiedOverride()) { childSetValue("limit_age_verified", TRUE); + childSetLabelArg( "limit_age_verified", "[ESTATE_AGE_LIMIT]", getString("access_estate_defined") ); } else { childSetValue("limit_age_verified", (parcel->getParcelFlag(PF_DENY_AGEUNVERIFIED))); + childSetLabelArg( "limit_age_verified", "[ESTATE_AGE_LIMIT]", std::string() ); } BOOL use_pass = parcel->getParcelFlag(PF_USE_PASS_LIST); diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 56a86c2cb7..bc89f93763 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -44,7 +44,6 @@ #include "llnotificationsutil.h" #include "lltextbox.h" -#include "llalertdialog.h" #include "llinventorybridge.h" #include "llfloaterinventory.h" #include "llinventorymodel.h" @@ -72,11 +71,14 @@ LLFloaterOpenObject::~LLFloaterOpenObject() { // sInstance = NULL; } + // virtual BOOL LLFloaterOpenObject::postBuild() { childSetTextArg("object_name", "[DESC]", std::string("Object") ); // *Note: probably do not want to translate this mPanelInventoryObject = getChild<LLPanelObjectInventory>("object_contents"); + + refresh(); return TRUE; } @@ -95,29 +97,57 @@ void LLFloaterOpenObject::onOpen(const LLSD& key) return; } mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); + refresh(); } + void LLFloaterOpenObject::refresh() { mPanelInventoryObject->refresh(); - std::string name; - BOOL enabled; + std::string name = ""; + + // Enable the copy || copy & wear buttons only if we have something we can copy or copy & wear (respectively). + bool copy_enabled = false; + bool wear_enabled = false; LLSelectNode* node = mObjectSelection->getFirstRootNode(); - if (node) + if (node) { name = node->mName; - enabled = TRUE; - } - else - { - name = ""; - enabled = FALSE; + copy_enabled = true; + + LLViewerObject* object = node->getObject(); + if (object) + { + // this folder is coming from an object, as there is only one folder in an object, the root, + // we need to collect the entire contents and handle them as a group + InventoryObjectList inventory_objects; + object->getInventoryContents(inventory_objects); + + if (!inventory_objects.empty()) + { + for (InventoryObjectList::iterator it = inventory_objects.begin(); + it != inventory_objects.end(); + ++it) + { + LLInventoryItem* item = static_cast<LLInventoryItem*> ((LLInventoryObject*)(*it)); + LLInventoryType::EType type = item->getInventoryType(); + if (type == LLInventoryType::IT_OBJECT + || type == LLInventoryType::IT_ATTACHMENT + || type == LLInventoryType::IT_WEARABLE + || type == LLInventoryType::IT_GESTURE) + { + wear_enabled = true; + break; + } + } + } + } } childSetTextArg("object_name", "[DESC]", name); - childSetEnabled("copy_to_inventory_button", enabled); - childSetEnabled("copy_and_wear_button", enabled); + childSetEnabled("copy_to_inventory_button", copy_enabled); + childSetEnabled("copy_and_wear_button", wear_enabled); } diff --git a/indra/newview/llfloaterparcel.cpp b/indra/newview/llfloaterparcel.cpp index 88a39a495f..e2be784116 100644 --- a/indra/newview/llfloaterparcel.cpp +++ b/indra/newview/llfloaterparcel.cpp @@ -40,6 +40,7 @@ // viewer project includes #include "llcommandhandler.h" #include "llpanelplace.h" +#include "llsidetray.h" // linden library includes #include "lluuid.h" @@ -70,7 +71,10 @@ public: { if (parcel_id.notNull()) { - LLFloaterReg::showInstance("parcel_info", LLSD(parcel_id)); + LLSD key; + key["type"] = "remote_place"; + key["id"] = parcel_id; + LLSideTray::getInstance()->showPanel("panel_places", key); return true; } } diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index 17bb8221ad..7edc27d4c3 100644 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -32,7 +32,6 @@ */ #include "llviewerprecompiledheaders.h" -#include "llalertdialog.h" #include "llcheckboxctrl.h" #include "llfloaterperms.h" #include "llviewercontrol.h" diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index 572eeb57fe..8da44e2035 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -56,9 +56,8 @@ #include "llstatusbar.h" #include "llviewerregion.h" #include "lleconomy.h" +#include "message.h" -#include "llgl.h" -#include "llglheaders.h" #include "llimagejpeg.h" #include "llimagej2c.h" #include "llvfile.h" diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h index 49cce53106..0a44b50779 100644 --- a/indra/newview/llfloaterpostcard.h +++ b/indra/newview/llfloaterpostcard.h @@ -70,7 +70,7 @@ public: void sendPostcard(); -protected: +private: LLPointer<LLImageJPEG> mJPEGImage; LLPointer<LLViewerTexture> mViewerImage; @@ -78,7 +78,7 @@ protected: LLAssetID mAssetID; LLVector2 mImageScale; LLVector3d mPosTakenGlobal; - boolean mHasFirstMsgFocus; + bool mHasFirstMsgFocus; }; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ab27375b87..a333868b8c 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -588,6 +588,9 @@ void LLFloaterPreference::onOpen(const LLSD& key) // when the floater is opened. That will make cancel do its // job saveSettings(); + + // This is a "fresh" floater, closing floater shoud cancel any changes + mCancelOnClose = true; } void LLFloaterPreference::onVertexShaderEnable() @@ -633,7 +636,11 @@ void LLFloaterPreference::onBtnOK() // that prevents cancel from undoing our changes when we hit OK mCancelOnClose = false; closeFloater(false); - mCancelOnClose = true; + + // closeFloater() will be called when viewer is quitting, leaving mCancelOnClose = true; + // will cancel all changes we saved here, don't let this happen. + // Fix for EXT-3465 + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); LLUIColorTable::instance().saveUserSettings(); std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 05a46ad894..496fa62d05 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -42,18 +42,18 @@ #include "llglheaders.h" #include "llregionflags.h" #include "llstl.h" +#include "llvfile.h" +#include "llxfermanager.h" #include "indra_constants.h" #include "message.h" #include "llagent.h" -#include "llalertdialog.h" #include "llappviewer.h" #include "llfloateravatarpicker.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" #include "llfilepicker.h" -#include "llfloaterdaycycle.h" #include "llfloatergodtools.h" // for send_sim_wide_deletes() #include "llfloatertopobjects.h" // added to fix SL-32336 #include "llfloatergroups.h" @@ -62,7 +62,6 @@ #include "llfloaterwindlight.h" #include "llinventorymodel.h" #include "lllineeditor.h" -#include "llalertdialog.h" #include "llnamelistctrl.h" #include "llnotifications.h" #include "llnotificationsutil.h" @@ -88,8 +87,6 @@ #include "lltrans.h" #include "llagentui.h" -#define ELAR_ENABLED 0 // Enable when server support is implemented - const S32 TERRAIN_TEXTURE_COUNT = 4; const S32 CORNER_COUNT = 4; @@ -1995,11 +1992,6 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region) childSetEnabled("remove_banned_avatar_btn", god || owner || manager); childSetEnabled("message_estate_btn", god || owner || manager); childSetEnabled("kick_user_from_estate_btn", god || owner || manager); -#if ELAR_ENABLED - childSetEnabled("abuse_email_address", god || owner || manager); -#else - childSetEnabled("abuse_email_address", false); -#endif // estate managers can't add estate managers childSetEnabled("add_estate_manager_btn", god || owner); @@ -2065,8 +2057,6 @@ BOOL LLPanelEstateInfo::postBuild() initCtrl("limit_payment"); initCtrl("limit_age_verified"); initCtrl("voice_chat_check"); - getChild<LLUICtrl>("abuse_email_address")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeAnything, this)); - getChild<LLLineEditor>("abuse_email_address")->setKeystrokeCallback(onChangeText, this); // set up the use global time checkbox getChild<LLUICtrl>("use_global_time_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeUseGlobalTime, this)); @@ -2276,8 +2266,6 @@ bool LLPanelEstateInfo::commitEstateInfoCaps() } body["sun_hour"] = sun_hour; - body["owner_abuse_email"] = childGetValue("abuse_email_address").asString(); - // we use a responder so that we can re-get the data after committing to the database LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder(this)); return true; @@ -2436,16 +2424,6 @@ void LLPanelEstateInfo::setOwnerName(const std::string& name) childSetValue("estate_owner", LLSD(name)); } -const std::string LLPanelEstateInfo::getAbuseEmailAddress() const -{ - return childGetValue("abuse_email_address").asString(); -} - -void LLPanelEstateInfo::setAbuseEmailAddress(const std::string& address) -{ - childSetValue("abuse_email_address", LLSD(address)); -} - void LLPanelEstateInfo::setAccessAllowedEnabled(bool enable_agent, bool enable_group, bool enable_ban) @@ -2954,18 +2932,6 @@ bool LLDispatchEstateUpdateInfo::operator()( std::string estate_name = strings[0].c_str(); // preserve c_str() call! panel->setEstateName(estate_name); -#if ELAR_ENABLED - if (strings.size() > 9) - { - std::string abuse_email = strings[9].c_str(); // preserve c_str() call! - panel->setAbuseEmailAddress(abuse_email); - } - else -#endif - { - panel->setAbuseEmailAddress(panel->getString("email_unsupported")); - } - LLViewerRegion* regionp = gAgent.getRegion(); LLUUID owner_id(strings[1]); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index a3b91223b7..a21b96bf16 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -35,9 +35,12 @@ #define LL_LLFLOATERREGIONINFO_H #include <vector> +#include "llassettype.h" #include "llfloater.h" +#include "llhost.h" #include "llpanel.h" +class LLDispatcher; class LLLineEditor; class LLMessageSystem; class LLPanelRegionInfo; @@ -51,6 +54,7 @@ class LLNameListCtrl; class LLSliderCtrl; class LLSpinCtrl; class LLTextBox; +class LLVFS; class LLPanelRegionGeneralInfo; class LLPanelRegionDebugInfo; @@ -330,9 +334,6 @@ public: const std::string getOwnerName() const; void setOwnerName(const std::string& name); - const std::string getAbuseEmailAddress() const; - void setAbuseEmailAddress(const std::string& address); - // If visible from mainland, allowed agent and allowed groups // are ignored, so must disable UI. void setAccessAllowedEnabled(bool enable_agent, bool enable_group, bool enable_ban); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 408303a1e0..9f3dcae8ef 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -40,11 +40,14 @@ // linden library includes #include "llassetstorage.h" #include "llfontgl.h" -#include "llgl.h" // for renderer +#include "llimagej2c.h" #include "llinventory.h" #include "llnotificationsutil.h" #include "llstring.h" #include "llsys.h" +#include "llvfile.h" +#include "llvfs.h" +#include "mean_collision_data.h" #include "message.h" #include "v3math.h" @@ -95,7 +98,6 @@ const U32 INCLUDE_SCREENSHOT = 0x01 << 0; LLFloaterReporter::LLFloaterReporter(const LLSD& key) : LLFloater(key), mReportType(COMPLAINT_REPORT), - mEmailToEstateOwner(FALSE), mObjectID(), mScreenID(), mAbuserID(), @@ -117,18 +119,7 @@ void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg) if ( LLFloaterReg::instanceVisible("reporter") ) { - LLFloaterReporter *f = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); - BOOL email_to_estate_owner = ( region_flags & REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER ); - f->mEmailToEstateOwner = email_to_estate_owner; - - if ( email_to_estate_owner ) - { - LLNotificationsUtil::add("HelpReportAbuseEmailEO"); - } - else - { - LLNotificationsUtil::add("HelpReportAbuseEmailLL"); - } + LLNotificationsUtil::add("HelpReportAbuseEmailLL"); }; } // virtual @@ -218,17 +209,7 @@ LLFloaterReporter::~LLFloaterReporter() // virtual void LLFloaterReporter::draw() { - // this is set by a static callback sometime after the dialog is created. - // Only disable screenshot for abuse reports to estate owners - if ( mEmailToEstateOwner ) - { - childSetValue("screen_check", FALSE ); - childSetEnabled("screen_check", FALSE ); - } - else - { - childSetEnabled("screen_check", TRUE ); - } + childSetEnabled("screen_check", TRUE ); LLFloater::draw(); } @@ -637,11 +618,7 @@ LLSD LLFloaterReporter::gatherReport() LLUUID screenshot_id = LLUUID::null; if (childGetValue("screen_check")) { - - if ( mEmailToEstateOwner == FALSE ) - { - screenshot_id = childGetValue("screenshot"); - } + screenshot_id = childGetValue("screenshot"); }; LLSD report = LLSD::emptyMap(); diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index 917f513641..a3776f3d27 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -124,7 +124,6 @@ private: private: EReportType mReportType; - BOOL mEmailToEstateOwner; LLUUID mObjectID; LLUUID mScreenID; LLUUID mAbuserID; diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 2c618263ec..595d84f9f0 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -38,11 +38,14 @@ #include "lluri.h" #include "llagent.h" #include "llui.h" +#include "llviewercontrol.h" +#include "llweb.h" LLFloaterSearch::LLFloaterSearch(const LLSD& key) : LLFloater(key), LLViewerMediaObserver(), - mBrowser(NULL) + mBrowser(NULL), + mSearchGodLevel(0) { // declare a map that transforms a category name into // the URL suffix that is used to search that category @@ -64,7 +67,6 @@ BOOL LLFloaterSearch::postBuild() { mBrowser->addObserver(this); mBrowser->setTrusted(true); - mBrowser->setHomePageUrl(getString("search_url")); } return TRUE; @@ -86,12 +88,21 @@ void LLFloaterSearch::handleMediaEvent(LLPluginClassMedia *self, EMediaEvent eve case MEDIA_EVENT_NAVIGATE_COMPLETE: childSetText("status_text", getString("done_text")); break; - + default: break; } } +void LLFloaterSearch::godLevelChanged(U8 godlevel) +{ + // search results can change based upon god level - if the user + // changes god level, then give them a warning (we don't refresh + // the search as this might undo any page navigation or + // AJAX-driven changes since the last search). + childSetVisible("refresh_search", (godlevel != mSearchGodLevel)); +} + void LLFloaterSearch::search(const LLSD &key) { if (! mBrowser) @@ -99,33 +110,36 @@ void LLFloaterSearch::search(const LLSD &key) return; } - // get the URL for the search page - std::string url = getString("search_url"); - if (! LLStringUtil::endsWith(url, "/")) - { - url += "/"; - } + // reset the god level warning as we're sending the latest state + childHide("refresh_search"); + mSearchGodLevel = gAgent.getGodLevel(); // work out the subdir to use based on the requested category + LLSD subs; std::string category = key.has("category") ? key["category"].asString() : ""; if (mCategoryPaths.has(category)) { - url += mCategoryPaths[category].asString(); + subs["CATEGORY"] = mCategoryPaths[category].asString(); } else { - url += mCategoryPaths["all"].asString(); + subs["CATEGORY"] = mCategoryPaths["all"].asString(); } - // append the search query string + // add the search query string std::string search_text = key.has("id") ? key["id"].asString() : ""; - url += std::string("?q=") + LLURI::escape(search_text); + subs["QUERY"] = LLURI::escape(search_text); - // append the permissions token that login.cgi gave us + // add the permissions token that login.cgi gave us + // We use "search_token", and fallback to "auth_token" if not present. LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token"); - url += "&p=" + search_token.asString(); + if (search_token.asString().empty()) + { + search_token = LLLoginInstance::getInstance()->getResponse("auth_token"); + } + subs["AUTH_TOKEN"] = search_token.asString(); - // also append the user's preferred maturity (can be changed via prefs) + // add the user's preferred maturity (can be changed via prefs) std::string maturity; if (gAgent.prefersAdult()) { @@ -139,14 +153,15 @@ void LLFloaterSearch::search(const LLSD &key) { maturity = "13"; // PG } - url += "&r=" + maturity; - - // add the current localization information - url += "&lang=" + LLUI::getLanguage(); + subs["MATURITY"] = maturity; // add the user's god status - std::string godlike = gAgent.isGodlike() ? "1" : "0"; - url += "&g=" + godlike; + subs["GODLIKE"] = gAgent.isGodlike() ? "1" : "0"; + + // get the search URL and expand all of the substitutions + // (also adds things like [LANGUAGE], [VERSION], [OS], etc.) + std::string url = gSavedSettings.getString("SearchURL"); + url = LLWeb::expandURLSubstitutions(url, subs); // and load the URL in the web view mBrowser->navigateTo(url); diff --git a/indra/newview/llfloatersearch.h b/indra/newview/llfloatersearch.h index 743107484f..ba817adf7f 100644 --- a/indra/newview/llfloatersearch.h +++ b/indra/newview/llfloatersearch.h @@ -66,14 +66,20 @@ public: /// "events", "groups", "wiki", "destinations", "classifieds" void search(const LLSD &key); + /// changing godmode can affect the search results that are + /// returned by the search website - use this method to tell the + /// search floater that the user has changed god level. + void godLevelChanged(U8 godlevel); + private: /*virtual*/ BOOL postBuild(); // inherited from LLViewerMediaObserver /*virtual*/ void handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event); - + LLMediaCtrl *mBrowser; LLSD mCategoryPaths; + U8 mSearchGodLevel; }; #endif // LL_LLFLOATERSEARCH_H diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 49e8f9c956..e5260aa7b9 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -39,7 +39,6 @@ #include "lllineeditor.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llparcel.h" #include "llselectmgr.h" #include "lltexturectrl.h" diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 6ba032c152..7fb71d4d4f 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -991,7 +991,7 @@ S32 LLFloaterTools::calcRenderCost() if (viewer_volume) { cost += viewer_volume->getRenderCost(textures); - cost += textures.size() * 5; + cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST; textures.clear(); } } @@ -1080,7 +1080,7 @@ void LLFloaterTools::getMediaState() { LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection(); LLViewerObject* first_object = selected_objects->getFirstObject(); - LLLineEditor* media_info = getChild<LLLineEditor>("media_info"); + LLTextBox* media_info = getChild<LLTextBox>("media_info"); if( !(first_object && first_object->getPCode() == LL_PCODE_VOLUME @@ -1088,12 +1088,6 @@ void LLFloaterTools::getMediaState() )) { childSetEnabled("Add_Media", FALSE); -/* childSetEnabled("media_tex", FALSE); - childSetEnabled("add_media", FALSE); - childSetEnabled("delete_media", FALSE); - childSetEnabled("edit_media", FALSE); - childSetEnabled("media_info", FALSE); - media_info->setEnabled(FALSE);*/ media_info->clear(); clearMediaSettings(); return; @@ -1105,13 +1099,6 @@ void LLFloaterTools::getMediaState() if(!has_media_capability) { childSetEnabled("Add_Media", FALSE); - /* childSetEnabled("media_tex", FALSE); - childSetEnabled("add_media", FALSE); - childSetEnabled("delete_media", FALSE); - childSetEnabled("edit_media", FALSE); - childSetEnabled("media_info", FALSE); - media_info->setEnabled(FALSE); - media_info->clear();*/ LL_WARNS("LLFloaterTools: media") << "Media not enabled (no capability) in this region!" << LL_ENDL; clearMediaSettings(); return; @@ -1233,7 +1220,6 @@ void LLFloaterTools::getMediaState() childSetEnabled( "edit_media", bool_has_media & editable ); childSetEnabled( "delete_media", bool_has_media & editable ); childSetEnabled( "add_media", ( ! bool_has_media ) & editable ); - media_info->setEnabled(false); // TODO: display a list of all media on the face - use 'identical' flag } else // not all face has media but at least one does. @@ -1260,8 +1246,6 @@ void LLFloaterTools::getMediaState() } } - media_info->setEnabled(false); - media_info->setTentative(true); childSetEnabled("media_tex", TRUE); childSetEnabled( "edit_media", TRUE); childSetEnabled( "delete_media", TRUE); @@ -1392,7 +1376,7 @@ void LLFloaterTools::updateMediaTitle() if ( ! media_title.empty() ) { // update the UI widget - LLLineEditor* media_title_field = getChild<LLLineEditor>("media_info"); + LLTextBox* media_title_field = getChild<LLTextBox>("media_info"); if ( media_title_field ) { media_title_field->setText( media_title ); diff --git a/indra/newview/llfloaterurldisplay.cpp b/indra/newview/llfloaterurldisplay.cpp index 3b9321a876..4b67cbb308 100644 --- a/indra/newview/llfloaterurldisplay.cpp +++ b/indra/newview/llfloaterurldisplay.cpp @@ -33,13 +33,14 @@ #include "llviewerprecompiledheaders.h" +#include "llregionhandle.h" +#include "v3dmath.h" + #include "llfloaterurldisplay.h" #include "llpanelplace.h" #include "lluictrlfactory.h" -#include "v3dmath.h" - //////////////////////////////////////////////////////////////////////////// // LLFloaterURLDisplay diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 5e769feea6..91d0f0e370 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -32,6 +32,8 @@ #include "llviewerprecompiledheaders.h" +#include "llhttpclient.h" + #include "llfloaterurlentry.h" #include "llpanellandmedia.h" diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 7ca491a698..98f9171237 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -74,8 +74,8 @@ #include "llmapimagetype.h" #include "llweb.h" #include "llslider.h" +#include "message.h" -#include "llglheaders.h" #include "llwindow.h" // copyTextToClipboard() //--------------------------------------------------------------------------- diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 1c5d7ae9b9..adf7f08702 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -411,7 +411,12 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter } - if (folderp->getVisible()) + + // Need to call arrange regardless of visibility, since children's visibility + // might need to be changed too (e.g. even though a folder is invisible, its + // children also need to be set invisible for state-tracking purposes, e.g. + // llfolderviewitem::filter). + // if (folderp->getVisible()) { S32 child_height = 0; S32 child_width = 0; @@ -479,13 +484,13 @@ void LLFolderView::filter( LLInventoryFilter& filter ) if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) { - mFiltered = FALSE; + mPassedFilter = FALSE; mMinWidth = 0; LLFolderViewFolder::filter(filter); } else { - mFiltered = TRUE; + mPassedFilter = TRUE; } } @@ -1934,6 +1939,26 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) return NULL; } +LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id) +{ + if (id.isNull()) + { + return this; + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end(); + ++iter) + { + LLFolderViewFolder *folder = (*iter); + if (folder->getListener()->getUUID() == id) + { + return folder; + } + } + return NULL; +} + bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) { std::string action = userdata.asString(); diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index d18ba385d8..2598af4df4 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -248,6 +248,7 @@ public: void addItemID(const LLUUID& id, LLFolderViewItem* itemp); void removeItemID(const LLUUID& id); LLFolderViewItem* getItemByID(const LLUUID& id); + LLFolderViewFolder* getFolderByID(const LLUUID& id); bool doToSelected(LLInventoryModel* model, const LLSD& userdata); diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 5bef306485..135821f662 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -40,6 +40,7 @@ #include "llinventoryfilter.h" #include "llpanel.h" #include "llviewercontrol.h" // gSavedSettings +#include "llviewerinventory.h" #include "llviewerwindow.h" // Argh, only for setCursor() // linden library includes @@ -121,7 +122,7 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p) mHasVisibleChildren(FALSE), mIndentation(0), mNumDescendantsSelected(0), - mFiltered(FALSE), + mPassedFilter(FALSE), mLastFilterGeneration(-1), mStringMatchOffset(std::string::npos), mControlLabelRotation(0.f), @@ -223,17 +224,17 @@ BOOL LLFolderViewItem::potentiallyVisible() BOOL LLFolderViewItem::getFiltered() { - return mFiltered && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); + return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); } BOOL LLFolderViewItem::getFiltered(S32 filter_generation) { - return mFiltered && mLastFilterGeneration >= filter_generation; + return mPassedFilter && mLastFilterGeneration >= filter_generation; } void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) { - mFiltered = filtered; + mPassedFilter = filtered; mLastFilterGeneration = filter_generation; } @@ -423,19 +424,20 @@ S32 LLFolderViewItem::getItemHeight() void LLFolderViewItem::filter( LLInventoryFilter& filter) { - BOOL filtered = mListener && filter.check(this); + const BOOL previous_passed_filter = mPassedFilter; + const BOOL passed_filter = mListener && filter.check(this); - // if our visibility will change as a result of this filter, then + // If our visibility will change as a result of this filter, then // we need to be rearranged in our parent folder - if (getVisible() != filtered) + if (mParentFolder) { - if (mParentFolder) - { + if (getVisible() != passed_filter) + mParentFolder->requestArrange(); + if (passed_filter != previous_passed_filter) mParentFolder->requestArrange(); - } } - setFiltered(filtered, filter.getCurrentGeneration()); + setFiltered(passed_filter, filter.getCurrentGeneration()); mStringMatchOffset = filter.getStringMatchOffset(); filter.decrementFilterCount(); @@ -603,6 +605,11 @@ const std::string& LLFolderViewItem::getSearchableLabel() const return mSearchableLabel; } +LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void) +{ + return gInventory.getItem(getListener()->getUUID()); +} + std::string LLFolderViewItem::getName( void ) const { if(mListener) @@ -1237,7 +1244,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) if (getLastFilterGeneration() < filter_generation) { if (getLastFilterGeneration() >= must_pass_generation && // folder has been compared to a valid precursor filter - !mFiltered) // and did not pass the filter + !mPassedFilter) // and did not pass the filter { // go ahead and flag this folder as done mLastFilterGeneration = filter_generation; @@ -1375,7 +1382,7 @@ void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation) { // if this folder is now filtered, but wasn't before // (it just passed) - if (filtered && !mFiltered) + if (filtered && !mPassedFilter) { // reset current height, because last time we drew it // it might have had more visible items than now diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 0ea031108b..620aa070b9 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -45,6 +45,7 @@ class LLFolderViewListenerFunctor; class LLInventoryFilter; class LLMenuGL; class LLUIImage; +class LLViewerInventoryItem; // These are grouping of inventory types. // Order matters when sorting system folders to the top. @@ -120,6 +121,9 @@ public: static const F32 FOLDER_CLOSE_TIME_CONSTANT; static const F32 FOLDER_OPEN_TIME_CONSTANT; + // Mostly for debugging printout purposes. + const std::string& getSearchableLabel() { return mSearchableLabel; } + protected: friend class LLUICtrlFactory; friend class LLFolderViewEventListener; @@ -148,7 +152,7 @@ protected: BOOL mHasVisibleChildren; S32 mIndentation; S32 mNumDescendantsSelected; - BOOL mFiltered; + BOOL mPassedFilter; S32 mLastFilterGeneration; std::string::size_type mStringMatchOffset; F32 mControlLabelRotation; @@ -156,8 +160,8 @@ protected: BOOL mDragAndDropTarget; LLUIImagePtr mArrowImage; LLUIImagePtr mBoxImage; - BOOL mIsLoading; - LLTimer mTimeSinceRequestStart; + BOOL mIsLoading; + LLTimer mTimeSinceRequestStart; bool mDontShowInHierarchy; // helper function to change the selection from the root. @@ -202,7 +206,7 @@ public: virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); virtual S32 getItemHeight(); void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarchy = dont_show; } - bool getDontShowInHierarchy() { return mDontShowInHierarchy; } + bool getDontShowInHierarchy() const { return mDontShowInHierarchy; } // applies filters to control visibility of inventory items virtual void filter( LLInventoryFilter& filter); @@ -281,6 +285,9 @@ public: const LLFolderViewEventListener* getListener( void ) const { return mListener; } LLFolderViewEventListener* getListener( void ) { return mListener; } + + // Gets the inventory item if it exists (null otherwise) + LLViewerInventoryItem * getInventoryItem(void); // just rename the object. void rename(const std::string& new_name); @@ -328,7 +335,7 @@ public: EAcceptance* accept, std::string& tooltip_msg); - private: +private: static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts }; diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 4f487ddf04..df7aa9eabf 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -52,7 +52,6 @@ #include "llagent.h" #include "lldelayedgestureerror.h" #include "llinventorymodel.h" -#include "llnotify.h" #include "llviewermessage.h" #include "llvoavatarself.h" #include "llviewerstats.h" diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index fdb2b886a6..ff75d461df 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -35,6 +35,8 @@ #include "llgroupactions.h" +#include "message.h" + #include "llagent.h" #include "llcommandhandler.h" #include "llfloaterreg.h" @@ -197,12 +199,12 @@ void LLGroupActions::activate(const LLUUID& group_id) gAgent.sendReliableMessage(); } -bool isGroupUIVisible() +static bool isGroupUIVisible() { LLPanel* panel = LLSideTray::getInstance()->findChild<LLPanel>("panel_group_info_sidetray"); if(!panel) return false; - return panel->getVisible(); + return panel->isInVisibleChain(); } // static diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 80b706a215..ab9db10f38 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -225,6 +225,11 @@ mGroupID(LLUUID::null) } } +LLGroupListItem::~LLGroupListItem() +{ + LLGroupMgr::getInstance()->removeObserver(this); +} + //virtual BOOL LLGroupListItem::postBuild() { @@ -277,8 +282,13 @@ void LLGroupListItem::setName(const std::string& name, const std::string& highli void LLGroupListItem::setGroupID(const LLUUID& group_id) { + LLGroupMgr::getInstance()->removeObserver(this); + + mID = group_id; mGroupID = group_id; setActive(group_id == gAgent.getGroupID()); + + LLGroupMgr::getInstance()->addObserver(this); } void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id) @@ -337,4 +347,11 @@ void LLGroupListItem::onProfileBtnClick() LLGroupActions::show(mGroupID); } +void LLGroupListItem::changed(LLGroupChange gc) +{ + LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID); + if(group_data) + setGroupIconID(group_data->mInsigniaID); +} + //EOF diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 41b4d01711..33cfe005b9 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -38,6 +38,7 @@ #include "llpanel.h" #include "llpointer.h" #include "llstyle.h" +#include "llgroupmgr.h" /** * Auto-updating list of agent groups. @@ -80,9 +81,11 @@ class LLIconCtrl; class LLTextBox; class LLGroupListItem : public LLPanel + , public LLGroupMgrObserver { public: LLGroupListItem(); + ~LLGroupListItem(); /*virtual*/ BOOL postBuild(); /*virtual*/ void setValue(const LLSD& value); void onMouseEnter(S32 x, S32 y, MASK mask); @@ -96,6 +99,7 @@ public: void setGroupIconID(const LLUUID& group_icon_id); void setGroupIconVisible(bool visible); + virtual void changed(LLGroupChange gc); private: void setActive(bool active); void onInfoBtnClick(); diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index ebb5feb2bf..af58e81ca4 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -758,7 +758,8 @@ void LLGroupMgr::clearGroupData(const LLUUID& group_id) void LLGroupMgr::addObserver(LLGroupMgrObserver* observer) { - mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer)); + if( observer->getID() != LLUUID::null ) + mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer)); } void LLGroupMgr::removeObserver(LLGroupMgrObserver* observer) diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index a0604be57e..487fdd4c5b 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -45,6 +45,7 @@ class LLGroupMgrObserver { public: LLGroupMgrObserver(const LLUUID& id) : mID(id){}; + LLGroupMgrObserver() : mID(LLUUID::null){}; virtual ~LLGroupMgrObserver(){}; virtual void changed(LLGroupChange gc) = 0; const LLUUID& getID() { return mID; } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 2bc07d0c27..7dc21e6e23 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -90,8 +90,20 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) case IM_SESSION_CONFERENCE_START: mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); break; - default: + case IM_SESSION_GROUP_START: mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); + break; + case IM_SESSION_INVITE: + if (gAgent.isInGroup(mSessionID)) + { + mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); + } + else + { + mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); + } + break; + default: break; } } } @@ -415,6 +427,7 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) if(channel) { channel->updateShowToastsState(); + channel->redrawToasts(); } } @@ -439,6 +452,7 @@ void LLIMFloater::setVisible(BOOL visible) if(channel) { channel->updateShowToastsState(); + channel->redrawToasts(); } if (visible && mChatHistory && mInputEditor) @@ -455,7 +469,7 @@ bool LLIMFloater::toggle(const LLUUID& session_id) if(!isChatMultiTab()) { LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); - if (floater && floater->getVisible() && floater->isDocked()) + if (floater && floater->getVisible()) { // clicking on chiclet to close floater just hides it to maintain existing // scroll/text entry state @@ -933,3 +947,20 @@ void LLIMFloater::initIMFloater() // init chat window type before user changed it in preferences isChatMultiTab(); } + +//static +void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) +{ + LLUUID session_id = data["session_id"]; + if (session_id.isNull()) return; + + LLUUID from_id = data["from_id"]; + if (gAgentID == from_id || LLUUID::null == from_id) return; + + LLIMFloater* floater = LLIMFloater::findInstance(session_id); + if (!floater) return; + + if (IM_NOTHING_SPECIAL != floater->mDialog) return; + + floater->removeTypingIndicator(); +} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index f90bc35c34..bc7a43e852 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -33,9 +33,10 @@ #ifndef LL_IMFLOATER_H #define LL_IMFLOATER_H -#include "lltransientdockablefloater.h" +#include "llinstantmessage.h" #include "lllogchat.h" #include "lltooldraganddrop.h" +#include "lltransientdockablefloater.h" class LLLineEditor; class LLPanelChatControlPanel; @@ -109,6 +110,9 @@ public: static void initIMFloater(); + //used as a callback on receiving new IM message + static void sRemoveTypingIndicator(const LLSD& data); + private: // process focus events to set a currently active session /* virtual */ void onFocusLost(); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index e6ded5f371..8b6762ce38 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -66,7 +66,6 @@ #include "llimview.h" // for LLIMModel to get other avatar id in chat #include "llkeyboard.h" #include "lllineeditor.h" -#include "llnotify.h" #include "llpanelimcontrolpanel.h" #include "llrecentpeople.h" #include "llresmgr.h" diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4780b51c55..b50d4674f7 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -72,7 +72,6 @@ #include "llviewerwindow.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llnearbychat.h" #include "llviewerregion.h" #include "llvoicechannel.h" @@ -88,6 +87,9 @@ const static std::string IM_TEXT("message"); const static std::string IM_FROM("from"); const static std::string IM_FROM_ID("from_id"); +const static std::string NO_SESSION("(IM Session Doesn't Exist)"); +const static std::string ADHOC_NAME_SUFFIX(" Conference"); + std::string LLCallDialogManager::sPreviousSessionlName = ""; std::string LLCallDialogManager::sCurrentSessionlName = ""; LLIMModel::LLIMSession* LLCallDialogManager::sSession = NULL; @@ -116,6 +118,13 @@ void toast_callback(const LLSD& msg){ return; } + // Skip toasting if we have open window of IM with this session id + LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]); + if (open_im_floater && open_im_floater->getVisible()) + { + return; + } + LLSD args; args["MESSAGE"] = msg["message"]; args["TIME"] = msg["time"]; @@ -154,29 +163,45 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& mInitialTargetIDs(ids), mVoiceChannel(NULL), mSpeakers(NULL), - mCallDialogManager(NULL), mSessionInitialized(false), mCallBackEnabled(true), mTextIMPossible(true), mOtherParticipantIsAvatar(true), mStartCallOnInitialize(false) { + // set P2P type by default + mSessionType = P2P_SESSION; + if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type) { mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id); + + // check if it was AVALINE call + if (!mOtherParticipantIsAvatar) + { + mSessionType = AVALINE_SESSION; + } } else { mVoiceChannel = new LLVoiceChannelGroup(session_id, name); + + // determine whether it is group or conference session + if (gAgent.isInGroup(mSessionID)) + { + mSessionType = GROUP_SESSION; + } + else + { + mSessionType = ADHOC_SESSION; + } } if(mVoiceChannel) { - mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2)); + mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3)); } - // define what type of session was opened - setSessionType(); - + mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); // All participants will be added to the list of people we've recently interacted with. @@ -209,45 +234,18 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& } } -void LLIMModel::LLIMSession::setSessionType() -{ - // set P2P type by default - mSessionType = P2P_SESSION; - - if (dynamic_cast<LLVoiceChannelP2P*>(mVoiceChannel) && !mOtherParticipantIsAvatar) // P2P AVALINE channel was opened - { - mSessionType = AVALINE_SESSION; - return; - } - else if(dynamic_cast<LLVoiceChannelGroup*>(mVoiceChannel)) // GROUP channel was opened - { - if (mType == IM_SESSION_CONFERENCE_START) - { - mSessionType = ADHOC_SESSION; - return; - } - else if(mType == IM_SESSION_GROUP_START) - { - mSessionType = GROUP_SESSION; - return; - } - } -} - -void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction) { // *TODO: remove hardcoded string!!!!!!!!!!! bool is_p2p_session = dynamic_cast<LLVoiceChannelP2P*>(mVoiceChannel); - bool is_incoming_call = false; std::string other_avatar_name; if(is_p2p_session) { - is_incoming_call = static_cast<LLVoiceChannelP2P*>(mVoiceChannel)->isIncomingCall(); gCacheName->getFullName(mOtherParticipantID, other_avatar_name); - if(is_incoming_call) + if(direction == LLVoiceChannel::INCOMING_CALL) { switch(new_state) { @@ -288,9 +286,6 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES LLIMModel::LLIMSession::~LLIMSession() { - delete mCallDialogManager; - mCallDialogManager = NULL; - delete mSpeakers; mSpeakers = NULL; @@ -455,10 +450,16 @@ void LLIMModel::testMessages() addMessage(bot2_session_id, from, bot2_id, "Test Message: OMGWTFBBQ."); } - +//session name should not be empty bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids) { + if (name.empty()) + { + llwarns << "Attempt to create a new session with empty name; id = " << session_id << llendl; + return false; + } + if (findIMSession(session_id)) { llwarns << "IM Session " << session_id << " already exists" << llendl; @@ -615,7 +616,7 @@ const std::string& LLIMModel::getName(const LLUUID& session_id) const if (!session) { llwarns << "session " << session_id << "does not exist " << llendl; - return LLStringUtil::null; + return NO_SESSION; } return session->mName; @@ -1048,7 +1049,7 @@ public: if (LLIMMgr::INVITATION_TYPE_VOICE == mInvitiationType) { - gIMMgr->startCall(mSessionID); + gIMMgr->startCall(mSessionID, LLVoiceChannel::INCOMING_CALL); } if ((mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE @@ -1074,7 +1075,7 @@ public: if ( 404 == statusNum ) { std::string error_string; - error_string = "does not exist"; + error_string = "session_does_not_exist_error"; gIMMgr->showSessionStartError(error_string, mSessionID); } } @@ -1259,7 +1260,7 @@ void LLCallDialogManager::onVoiceChannelChanged(const LLUUID &session_id) sCurrentSessionlName = session->mName; } -void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction) { LLSD mCallDialogPayload; LLOutgoingCallDialog* ocd; @@ -1272,8 +1273,8 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat switch(new_state) { case LLVoiceChannel::STATE_CALL_STARTED : - // do not show "Calling to..." if it is incoming P2P call - if(sSession->mSessionType == LLIMModel::LLIMSession::P2P_SESSION && static_cast<LLVoiceChannelP2P*>(sSession->mVoiceChannel)->isIncomingCall()) + // do not show "Calling to..." if it is incoming call + if(direction == LLVoiceChannel::INCOMING_CALL) { return; } @@ -1285,6 +1286,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat ocd->getChild<LLTextBox>("leaving")->setVisible(true); ocd->getChild<LLTextBox>("connecting")->setVisible(false); ocd->getChild<LLTextBox>("noanswer")->setVisible(false); + ocd->getChild<LLButton>("Cancel")->setVisible(true); } return; @@ -1296,10 +1298,12 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat ocd->getChild<LLTextBox>("leaving")->setVisible(true); ocd->getChild<LLTextBox>("connecting")->setVisible(true); ocd->getChild<LLTextBox>("noanswer")->setVisible(false); + ocd->getChild<LLButton>("Cancel")->setVisible(true); } return; case LLVoiceChannel::STATE_ERROR : + mCallDialogPayload["start_timer"] = true; ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); if (ocd) { @@ -1307,6 +1311,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat ocd->getChild<LLTextBox>("leaving")->setVisible(false); ocd->getChild<LLTextBox>("connecting")->setVisible(false); ocd->getChild<LLTextBox>("noanswer")->setVisible(true); + ocd->getChild<LLButton>("Cancel")->setVisible(false); } return; @@ -1358,6 +1363,33 @@ LLCallDialog(payload) instance->onCancel(instance); } } +void LLOutgoingCallDialog::draw() +{ + if (lifetimeHasExpired()) + { + onLifetimeExpired(); + } + LLDockableFloater::draw(); +} + +bool LLOutgoingCallDialog::lifetimeHasExpired() +{ + if (mLifetimeTimer.getStarted()) + { + F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); + if (elapsed_time > LIFETIME) + { + return true; + } + } + return false; +} + +void LLOutgoingCallDialog::onLifetimeExpired() +{ + mLifetimeTimer.stop(); + closeFloater(); +} void LLOutgoingCallDialog::onOpen(const LLSD& key) { @@ -1386,6 +1418,13 @@ void LLOutgoingCallDialog::onOpen(const LLSD& key) childSetTextArg("connecting", "[CALLEE_NAME]", callee_name); LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon"); icon->setValue(callee_id); + + // stop timer by default + mLifetimeTimer.stop(); + if(mPayload.has("start_timer")) + { + mLifetimeTimer.reset(); + } } @@ -1417,6 +1456,7 @@ BOOL LLOutgoingCallDialog::postBuild() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLIncomingCallDialog //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) : LLCallDialog(payload) { @@ -1426,26 +1466,34 @@ BOOL LLIncomingCallDialog::postBuild() { LLDockableFloater::postBuild(); + LLUUID session_id = mPayload["session_id"].asUUID(); LLSD caller_id = mPayload["caller_id"]; - EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger(); - - std::string call_type = getString("VoiceInviteP2P"); std::string caller_name = mPayload["caller_name"].asString(); + + std::string call_type; + if (gAgent.isInGroup(session_id)) + { + LLStringUtil::format_map_t args; + LLGroupData data; + if (gAgent.getGroupData(session_id, data)) + { + args["[GROUP]"] = data.mName; + call_type = getString(mPayload["notify_box_type"], args); + } + } + else + { + call_type = getString(mPayload["notify_box_type"]); + } + if (caller_name == "anonymous") { caller_name = getString("anonymous"); } setTitle(caller_name + " " + call_type); - - // If it is not a P2P invite, then it's an AdHoc invite - if ( type != IM_SESSION_P2P_INVITE ) - { - call_type = getString("VoiceInviteAdHoc"); - } // check to see if this is an Avaline call - LLUUID session_id = mPayload["session_id"].asUUID(); bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); childSetVisible("Start IM", is_avatar); // no IM for avaline @@ -1509,6 +1557,8 @@ void LLIncomingCallDialog::processCallResponse(S32 response) return; LLUUID session_id = mPayload["session_id"].asUUID(); + LLUUID caller_id = mPayload["caller_id"].asUUID(); + std::string session_name = mPayload["session_name"].asString(); EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger(); LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)mPayload["inv_type"].asInteger(); bool voice = true; @@ -1525,14 +1575,14 @@ void LLIncomingCallDialog::processCallResponse(S32 response) { // create a normal IM session session_id = gIMMgr->addP2PSession( - mPayload["session_name"].asString(), - mPayload["caller_id"].asUUID(), + session_name, + caller_id, mPayload["session_handle"].asString(), mPayload["session_uri"].asString()); if (voice) { - if (gIMMgr->startCall(session_id)) + if (gIMMgr->startCall(session_id, LLVoiceChannel::INCOMING_CALL)) { // always open IM window when connecting to voice LLIMFloater::show(session_id); @@ -1544,10 +1594,38 @@ void LLIncomingCallDialog::processCallResponse(S32 response) } else { - LLUUID new_session_id = gIMMgr->addSession( - mPayload["session_name"].asString(), - type, - session_id); + //session name should not be empty, but it can contain spaces so we don't trim + std::string correct_session_name = session_name; + if (session_name.empty()) + { + llwarns << "Received an empty session name from a server" << llendl; + + switch(type){ + case IM_SESSION_CONFERENCE_START: + case IM_SESSION_GROUP_START: + case IM_SESSION_INVITE: + if (gAgent.isInGroup(session_id)) + { + LLGroupData data; + if (!gAgent.getGroupData(session_id, data)) break; + correct_session_name = data.mName; + } + else + { + if (gCacheName->getFullName(caller_id, correct_session_name)) + { + correct_session_name.append(ADHOC_NAME_SUFFIX); + } + } + llinfos << "Corrected session name is " << correct_session_name << llendl; + break; + default: + llwarning("Received an empty session name from a server and failed to generate a new proper session name", 0); + break; + } + } + + LLUUID new_session_id = gIMMgr->addSession(correct_session_name, type, session_id); if (new_session_id != LLUUID::null) { LLIMFloater::show(new_session_id); @@ -1715,6 +1793,8 @@ LLIMMgr::LLIMMgr() : { mPendingInvitations = LLSD::emptyMap(); mPendingAgentListUpdates = LLSD::emptyMap(); + + LLIMModel::getInstance()->addNewMsgCallback(boost::bind(&LLIMFloater::sRemoveTypingIndicator, _1)); } // Add a message to a session. @@ -1983,6 +2063,12 @@ LLUUID LLIMMgr::addSession( return LLUUID::null; } + if (name.empty()) + { + llwarning("Session name cannot be null!", 0); + return LLUUID::null; + } + LLUUID session_id = computeSessionID(dialog,other_participant_id); bool new_session = !LLIMModel::getInstance()->findIMSession(session_id); @@ -2349,11 +2435,12 @@ void LLIMMgr::removeSessionObserver(LLIMSessionObserver *observer) mSessionObservers.remove(observer); } -bool LLIMMgr::startCall(const LLUUID& session_id) +bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction) { LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id); if (!voice_channel) return false; + voice_channel->setCallDirection(direction); voice_channel->activate(); return true; } diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index c2288a719a..e2fcd63e28 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -69,10 +69,9 @@ public: virtual ~LLIMSession(); void sessionInitReplyReceived(const LLUUID& new_session_id); - void setSessionType(); //define what type of session was opened void addMessagesFromHistory(const std::list<LLSD>& history); void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time); - void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); + void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction); static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata); LLUUID mSessionID; @@ -81,7 +80,6 @@ public: SType mSessionType; LLUUID mOtherParticipantID; std::vector<LLUUID> mInitialTargetIDs; - LLCallDialogManager* mCallDialogManager; // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; @@ -142,6 +140,7 @@ public: /** * Create new session object in a model + * @param name session name should not be empty, will return false if empty */ bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids = std::vector<LLUUID>()); @@ -297,6 +296,7 @@ public: /** * Creates a P2P session with the requisite handle for responding to voice calls. * + * @param name session name, cannot be null * @param caller_uri - sip URI of caller. It should be always be passed into the method to avoid * incorrect working of LLVoiceChannel instances. See EXT-2985. */ @@ -383,7 +383,7 @@ public: * Start call in a session * @return false if voice channel doesn't exist **/ - bool startCall(const LLUUID& session_id); + bool startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction = LLVoiceChannel::OUTGOING_CALL); /** * End call in a session @@ -447,7 +447,7 @@ public: static void initClass(); static void onVoiceChannelChanged(const LLUUID &session_id); - static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); + static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction); protected: static std::string sPreviousSessionlName; @@ -494,7 +494,16 @@ public: static void onCancel(void* user_data); + // check timer state + /*virtual*/ void draw(); + private: + // lifetime timer for NO_ANSWER notification + LLTimer mLifetimeTimer; + // lifetime duration for NO_ANSWER notification + static const S32 LIFETIME = 5; + bool lifetimeHasExpired(); + void onLifetimeExpired(); }; // Globals diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index 42d061ff72..cb35a287e9 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -416,18 +416,6 @@ void LLInspectObject::updateDescription(LLSelectNode* nodep) LLTextBox* textbox = getChild<LLTextBox>("object_description"); textbox->setValue(desc); - - // Truncate description text to fit in widget - // *HACK: OMG, use lower-left corner to truncate text - // Don't round the position, we want the left of the character - S32 corner_index = textbox->getDocIndexFromLocalCoord( 0, 0, FALSE); - LLWString desc_wide = textbox->getWText(); - // index == length if position is past last character - if (corner_index < (S32)desc_wide.length()) - { - desc_wide = desc_wide.substr(0, corner_index); - textbox->setWText(desc_wide); - } } void LLInspectObject::updateMediaCurrentURL() diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3746e9cfeb..bacc685130 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -506,12 +506,59 @@ void hide_context_entries(LLMenuGL& menu, } } +bool isWornLink(LLUUID link_id) +{ + LLViewerInventoryItem *link = gInventory.getItem(link_id); + if (!link) + return false; + LLViewerInventoryItem *item = link->getLinkedItem(); + if (!item) + return false; + + switch(item->getType()) + { + case LLAssetType::AT_OBJECT: + { + LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject(); + if(my_avatar && my_avatar->isWearingAttachment(item->getUUID())) + return true; + } + break; + + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_CLOTHING: + if(gAgentWearables.isWearingItem(item->getUUID())) + return true; + break; + + case LLAssetType::AT_GESTURE: + if (LLGestureManager::instance().isGestureActive(item->getUUID())) + return true; + break; + default: + break; + } + return false; +} + // Helper for commonly-used entries void LLInvFVBridge::getClipboardEntries(bool show_asset_id, std::vector<std::string> &items, std::vector<std::string> &disabled_items, U32 flags) { const LLInventoryObject *obj = getInventoryObject(); + + bool is_sidepanel = isInOutfitsSidePanel(); + if (is_sidepanel) + { + // Sidepanel includes restricted menu. + if (obj && obj->getIsLinkType() && !isWornLink(mUUID)) + { + items.push_back(std::string("Remove Link")); + } + return; + } + if (obj) { if (obj->getIsLinkType()) @@ -566,6 +613,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } items.push_back(std::string("Paste Separator")); + + if (obj && obj->getIsLinkType() && !isWornLink(mUUID)) + { + items.push_back(std::string("Remove Link")); + } + items.push_back(std::string("Delete")); if (!isItemRemovable()) { @@ -913,6 +966,16 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) } } +bool LLInvFVBridge::isInOutfitsSidePanel() const +{ + LLInventoryPanel *my_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLPanelOutfitsInventory *outfit_panel = + dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); + if (!outfit_panel) + return false; + return outfit_panel->isTabPanel(my_panel); +} + // +=================================================+ // | InventoryFVBridgeBuilder | // +=================================================+ @@ -1408,13 +1471,14 @@ BOOL LLFolderBridge::isItemRemovable() { return FALSE; } + // Allow protected types to be removed, but issue a warning. - /* - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + // Restrict to god mode so users don't inadvertently mess up their inventory. + if(LLFolderType::lookupIsProtectedType(category->getPreferredType()) && + !gAgent.isGodlike()) { return FALSE; } - */ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); @@ -2386,19 +2450,6 @@ void LLFolderBridge::staticFolderOptionsMenu() sSelf->folderOptionsMenu(); } -bool isInOutfitsSidePanel(LLPanel *panel) -{ - LLInventoryPanel *my_panel = dynamic_cast<LLInventoryPanel*>(panel); - LLPanelOutfitsInventory *outfit_panel = - dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); - if (!outfit_panel) - return false; - return outfit_panel->isAccordionPanel(my_panel); - - //LLInventoryPanel *outfit_inv_panel = outfit_panel ? outfit_panel->getActivePanel(): NULL; - //return (my_panel && (my_panel == outfit_inv_panel)); -} - void LLFolderBridge::folderOptionsMenu() { std::vector<std::string> disabled_items; @@ -2412,13 +2463,12 @@ void LLFolderBridge::folderOptionsMenu() // BAP change once we're no longer treating regular categories as ensembles. const bool is_ensemble = category && (type == LLFolderType::FT_NONE || LLFolderType::lookupIsEnsembleType(type)); - const bool is_sidepanel = isInOutfitsSidePanel(mInventoryPanel.get()); // calling card related functionality for folders. + const bool is_sidepanel = isInOutfitsSidePanel(); if (is_sidepanel) { - mItems.clear(); mItems.push_back("Rename"); mItems.push_back("Delete"); } @@ -2446,7 +2496,10 @@ void LLFolderBridge::folderOptionsMenu() checkFolderForContentsOfType(model, is_object) || checkFolderForContentsOfType(model, is_gesture) ) { - mItems.push_back(std::string("Folder Wearables Separator")); + if (!is_sidepanel) + { + mItems.push_back(std::string("Folder Wearables Separator")); + } // Only enable add/replace outfit for non-default folders. if (!is_default_folder) @@ -2459,8 +2512,8 @@ void LLFolderBridge::folderOptionsMenu() mItems.push_back(std::string("Wear As Ensemble")); } mItems.push_back(std::string("Remove From Outfit")); - if (is_sidepanel) - mItems.push_back(std::string("Outfit Separator")); + + mItems.push_back(std::string("Outfit Separator")); } hide_context_entries(*mMenu, mItems, disabled_items); @@ -2488,14 +2541,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mDisabledItems.clear(); lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; + // std::vector<std::string> disabled_items; LLInventoryModel* model = getInventoryModel(); if(!model) return; const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point) - mDisabledItems.clear(); //adding code to clear out disabled members from previous if (lost_and_found_id == mUUID) { // This is the lost+found folder. @@ -2524,7 +2576,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) LLViewerInventoryCategory *cat = getCategory(); // BAP removed protected check to re-enable standard ops in untyped folders. // Not sure what the right thing is to do here. - if (!isCOFFolder() && cat /*&& + if (!isCOFFolder() && cat && cat->getPreferredType()!=LLFolderType::FT_OUTFIT /*&& LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/) { // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. @@ -2853,6 +2905,9 @@ void saveItemsOrder(LLInventoryModel::item_array_t& items) item->updateServer(FALSE); gInventory.updateItem(item); + + // Tell the parent folder to refresh its sort order. + gInventory.addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); } gInventory.notifyObservers(); @@ -2949,8 +3004,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - const LLUUID& landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); - const BOOL folder_allows_reorder = ((mUUID == landmarks_id) || (mUUID == favorites_id)); + const BOOL folder_allows_reorder = (mUUID == favorites_id); // we can move item inside a folder only if this folder is Favorites. See EXT-719 accept = is_movable && ((mUUID != inv_item->getParentUUID()) || folder_allows_reorder); @@ -2965,7 +3019,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // everything in the active window so that we don't follow // the selection to its new location (which is very // annoying). - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); + LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); if (active_panel) { LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); @@ -3150,6 +3204,22 @@ void LLTextureBridge::openItem() } } +bool LLTextureBridge::canSaveTexture(void) +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return false; + } + + const LLViewerInventoryItem *item = model->getItem(mUUID); + if (item) + { + return item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); + } + return false; +} + void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; @@ -3174,6 +3244,10 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Texture Separator")); items.push_back(std::string("Save As")); + if (!canSaveTexture()) + { + disabled_items.push_back(std::string("Save As")); + } } hide_context_entries(menu, items, disabled_items); } @@ -3776,8 +3850,13 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); + bool is_sidepanel = isInOutfitsSidePanel(); + + if (!is_sidepanel) + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + } getClipboardEntries(true, items, disabled_items, flags); @@ -4101,13 +4180,18 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else { - items.push_back(std::string("Properties")); + bool is_sidepanel = isInOutfitsSidePanel(); + + if (!is_sidepanel) + { + items.push_back(std::string("Properties")); + } - LLInventoryItem *item = getItem(); getClipboardEntries(true, items, disabled_items, flags); LLObjectBridge::sContextMenuItemID = mUUID; + LLInventoryItem *item = getItem(); if(item) { LLVOAvatarSelf* avatarp = gAgent.getAvatarObject(); @@ -4533,19 +4617,23 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { can_open = FALSE; } - if (can_open) + + bool is_sidepanel = isInOutfitsSidePanel(); + + if (can_open && !is_sidepanel) { items.push_back(std::string("Open")); } - items.push_back(std::string("Properties")); + if (!is_sidepanel) + { + items.push_back(std::string("Properties")); + } getClipboardEntries(true, items, disabled_items, flags); items.push_back(std::string("Wearable Separator")); - items.push_back(std::string("Wearable Wear")); - items.push_back(std::string("Wearable Add")); items.push_back(std::string("Wearable Edit")); if ((flags & FIRST_SELECTED_ITEM) == 0) @@ -4575,6 +4663,8 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else { + items.push_back(std::string("Wearable Wear")); + items.push_back(std::string("Wearable Add")); disabled_items.push_back(std::string("Take Off")); } break; @@ -4744,7 +4834,8 @@ void LLWearableBridge::onEditOnAvatar(void* user_data) void LLWearableBridge::editOnAvatar() { - const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID); + LLUUID linked_id = gInventory.getLinkedItemID(mUUID); + const LLWearable* wearable = gAgentWearables.getWearableFromItemID(linked_id); if( wearable ) { // Set the tab to the right wearable. diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 63be9dcdb8..117e32c6be 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -182,6 +182,9 @@ public: // LLInvFVBridge functionality virtual void clearDisplayName() {} + // Allow context menus to be customized for side panel. + bool isInOutfitsSidePanel() const; + protected: LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid); @@ -377,6 +380,7 @@ public: protected: LLTextureBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type) : LLItemBridge(inventory, uuid), mInvType(type) {} + bool canSaveTexture(void); LLInventoryType::EType mInvType; }; diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 81b10f5a62..522edd0cb5 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -40,6 +40,7 @@ #include "llinventorymodel.h" // gInventory.backgroundFetchActive() #include "llviewercontrol.h" #include "llviewerinventory.h" +#include "llfolderview.h" // linden library includes #include "lltrans.h" @@ -329,7 +330,6 @@ void LLInventoryFilter::setFilterSubString(const std::string& string) mFilterSubString = string; LLStringUtil::toUpper(mFilterSubString); LLStringUtil::trimHead(mFilterSubString); - if (less_restrictive) { setModified(FILTER_LESS_RESTRICTIVE); @@ -512,21 +512,21 @@ void LLInventoryFilter::setModified(EFilterBehavior behavior) // if not keeping current filter results, update last valid as well switch(mFilterBehavior) { - case FILTER_RESTART: - mMustPassGeneration = mFilterGeneration; - mMinRequiredGeneration = mFilterGeneration; - break; - case FILTER_LESS_RESTRICTIVE: - mMustPassGeneration = mFilterGeneration; - break; - case FILTER_MORE_RESTRICTIVE: - mMinRequiredGeneration = mFilterGeneration; - // must have passed either current filter generation (meaningless, as it hasn't been run yet) - // or some older generation, so keep the value - mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); - break; - default: - llerrs << "Bad filter behavior specified" << llendl; + case FILTER_RESTART: + mMustPassGeneration = mFilterGeneration; + mMinRequiredGeneration = mFilterGeneration; + break; + case FILTER_LESS_RESTRICTIVE: + mMustPassGeneration = mFilterGeneration; + break; + case FILTER_MORE_RESTRICTIVE: + mMinRequiredGeneration = mFilterGeneration; + // must have passed either current filter generation (meaningless, as it hasn't been run yet) + // or some older generation, so keep the value + mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); + break; + default: + llerrs << "Bad filter behavior specified" << llendl; } } else diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 5d8a8805b5..0a8108899a 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -59,7 +59,8 @@ BOOL LLInventoryModel::sBackgroundFetchActive = FALSE; BOOL LLInventoryModel::sAllFoldersFetched = FALSE; -BOOL LLInventoryModel::sFullFetchStarted = FALSE; +BOOL LLInventoryModel::sMyInventoryFetchStarted = FALSE; +BOOL LLInventoryModel::sLibraryFetchStarted = FALSE; S32 LLInventoryModel::sNumFetchRetries = 0; F32 LLInventoryModel::sMinTimeBetweenFetches = 0.3f; F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f; @@ -1342,11 +1343,11 @@ bool LLInventoryModel::isBulkFetchProcessingComplete() && sBulkFetchCount<=0) ? TRUE : FALSE ) ; } -class fetchDescendentsResponder: public LLHTTPClient::Responder +class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder { public: - fetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; - //fetchDescendentsResponder() {}; + LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; + //LLInventoryModelFetchDescendentsResponder() {}; void result(const LLSD& content); void error(U32 status, const std::string& reason); public: @@ -1356,7 +1357,7 @@ class fetchDescendentsResponder: public LLHTTPClient::Responder }; //If we get back a normal response, handle it here -void fetchDescendentsResponder::result(const LLSD& content) +void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) { if (content.has("folders")) { @@ -1423,7 +1424,8 @@ void fetchDescendentsResponder::result(const LLSD& content) LLSD category = *category_it; tcategory->fromLLSD(category); - if (LLInventoryModel::sFullFetchStarted) + if (LLInventoryModel::sMyInventoryFetchStarted || + LLInventoryModel::sLibraryFetchStarted) { sFetchQueue.push_back(tcategory->getUUID()); } @@ -1475,20 +1477,16 @@ void fetchDescendentsResponder::result(const LLSD& content) if (LLInventoryModel::isBulkFetchProcessingComplete()) { llinfos << "Inventory fetch completed" << llendl; - if (LLInventoryModel::sFullFetchStarted) - { - LLInventoryModel::sAllFoldersFetched = TRUE; - } - LLInventoryModel::stopBackgroundFetch(); + LLInventoryModel::setAllFoldersFetched(); } gInventory.notifyObservers("fetchDescendents"); } //If we get back an error (not found, etc...), handle it here -void fetchDescendentsResponder::error(U32 status, const std::string& reason) +void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason) { - llinfos << "fetchDescendentsResponder::error " + llinfos << "LLInventoryModelFetchDescendentsResponder::error " << status << ": " << reason << llendl; LLInventoryModel::incrBulkFetch(-1); @@ -1508,11 +1506,7 @@ void fetchDescendentsResponder::error(U32 status, const std::string& reason) { if (LLInventoryModel::isBulkFetchProcessingComplete()) { - if (LLInventoryModel::sFullFetchStarted) - { - LLInventoryModel::sAllFoldersFetched = TRUE; - } - LLInventoryModel::stopBackgroundFetch(); + LLInventoryModel::setAllFoldersFetched(); } } gInventory.notifyObservers("fetchDescendents"); @@ -1580,7 +1574,8 @@ void LLInventoryModel::bulkFetch(std::string url) body["folders"].append(folder_sd); folder_count++; } - if (sFullFetchStarted) + if (sMyInventoryFetchStarted || + sLibraryFetchStarted) { //Already have this folder but append child folders to list. // add all children to queue parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID()); @@ -1605,22 +1600,18 @@ void LLInventoryModel::bulkFetch(std::string url) sBulkFetchCount++; if (body["folders"].size()) { - LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0); + LLHTTPClient::post(url, body, new LLInventoryModelFetchDescendentsResponder(body),300.0); } if (body_lib["folders"].size()) { std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents"); - LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0); + LLHTTPClient::post(url_lib, body_lib, new LLInventoryModelFetchDescendentsResponder(body_lib),300.0); } sFetchTimer.reset(); } else if (isBulkFetchProcessingComplete()) { - if (sFullFetchStarted) - { - sAllFoldersFetched = TRUE; - } - stopBackgroundFetch(); + setAllFoldersFetched(); } } @@ -1636,7 +1627,6 @@ BOOL LLInventoryModel::backgroundFetchActive() return sBackgroundFetchActive; } -//static void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) { if (!sAllFoldersFetched) @@ -1644,9 +1634,16 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) sBackgroundFetchActive = TRUE; if (cat_id.isNull()) { - if (!sFullFetchStarted) + if (!sMyInventoryFetchStarted) { - sFullFetchStarted = TRUE; + sMyInventoryFetchStarted = TRUE; + sFetchQueue.push_back(gInventory.getLibraryRootFolderID()); + sFetchQueue.push_back(gInventory.getRootFolderID()); + gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + } + if (!sLibraryFetchStarted) + { + sLibraryFetchStarted = TRUE; sFetchQueue.push_back(gInventory.getLibraryRootFolderID()); sFetchQueue.push_back(gInventory.getRootFolderID()); gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); @@ -1660,6 +1657,14 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) sFetchQueue.push_front(cat_id); gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); } + if (cat_id == gInventory.getLibraryRootFolderID()) + { + sLibraryFetchStarted = TRUE; + } + if (cat_id == gInventory.getRootFolderID()) + { + sMyInventoryFetchStarted = TRUE; + } } } } @@ -1681,10 +1686,20 @@ void LLInventoryModel::stopBackgroundFetch() gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL); sBulkFetchCount=0; sMinTimeBetweenFetches=0.0f; -// sFullFetchStarted=FALSE; } } +// static +void LLInventoryModel::setAllFoldersFetched() +{ + if (sMyInventoryFetchStarted && + sLibraryFetchStarted) + { + sAllFoldersFetched = TRUE; + } + stopBackgroundFetch(); +} + //static void LLInventoryModel::backgroundFetch(void*) { @@ -1703,11 +1718,8 @@ void LLInventoryModel::backgroundFetch(void*) if (sFetchQueue.empty()) { llinfos << "Inventory fetch completed" << llendl; - if (sFullFetchStarted) - { - sAllFoldersFetched = TRUE; - } - stopBackgroundFetch(); + + setAllFoldersFetched(); return; } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index b744d821c7..27bbca493d 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -72,6 +72,8 @@ class LLInventoryCollectFunctor; class LLInventoryModel { public: + friend class LLInventoryModelFetchDescendentsResponder; + enum EHasChildren { CHILDREN_NO, @@ -282,9 +284,6 @@ public: // Make sure we have the descendents in the structure. Returns true // if a fetch was performed. bool fetchDescendentsOf(const LLUUID& folder_id); - - // Add categories to a list to be fetched in bulk. - static void bulkFetch(std::string url); // call this method to request the inventory. //void requestFromServer(const LLUUID& agent_id); @@ -369,15 +368,7 @@ public: // Utility Functions void removeItem(const LLUUID& item_id); - // start and stop background breadth-first fetching of inventory contents - // this gets triggered when performing a filter-search - static void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null); // start fetch process static void findLostItems(); - static BOOL backgroundFetchActive(); - static bool isEverythingFetched(); - static void backgroundFetch(void*); // background fetch idle function - static void incrBulkFetch(S16 fetching) { sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; } - // Data about the agent's root folder and root library folder // are stored here, rather than in LLAgent where it used to be, because @@ -477,14 +468,11 @@ private: LLUUID mLibraryRootFolderID; LLUUID mLibraryOwnerID; - // completing the fetch once per session should be sufficient - static BOOL sBackgroundFetchActive; static BOOL sTimelyFetchPending; static S32 sNumFetchRetries; static LLFrameTimer sFetchTimer; static F32 sMinTimeBetweenFetches; static F32 sMaxTimeBetweenFetches; - static S16 sBulkFetchCount; // Expected inventory cache version const static S32 sCurrentInvCacheVersion; @@ -510,11 +498,33 @@ private: public: // *NOTE: DEBUG functionality void dumpInventory() const; - static bool isBulkFetchProcessingComplete(); + + //////////////////////////////////////////////////////////////////////////////// + // Bulk / Background Fetch + +public: + // Start and stop background breadth-first fetching of inventory contents. + // This gets triggered when performing a filter-search + void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null); + static BOOL backgroundFetchActive(); + static bool isEverythingFetched(); + static void backgroundFetch(void*); // background fetch idle function + static void incrBulkFetch(S16 fetching) { sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; } static void stopBackgroundFetch(); // stop fetch process + static bool isBulkFetchProcessingComplete(); + + // Add categories to a list to be fetched in bulk. + static void bulkFetch(std::string url); - static BOOL sFullFetchStarted; +private: + static BOOL sMyInventoryFetchStarted; + static BOOL sLibraryFetchStarted; static BOOL sAllFoldersFetched; + static void setAllFoldersFetched(); + + // completing the fetch once per session should be sufficient + static BOOL sBackgroundFetchActive; + static S16 sBulkFetchCount; }; // a special inventory model for the agent diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 99e6dbe3c8..c1f192e2bf 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -62,6 +62,7 @@ public: STRUCTURE = 16, // structural change (eg item or folder moved) CALLING_CARD = 32, // (eg online, grant status, cancel) REBUILD = 64, // item UI changed (eg item type different) + SORT = 128, // folder needs to be resorted. ALL = 0xffffffff }; LLInventoryObserver(); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 4cbf27b725..3c34ba32e2 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -278,6 +278,7 @@ void LLInventoryPanel::modelChanged(U32 mask) const LLUUID& item_id = (*items_iter); const LLInventoryObject* model_item = model->getObject(item_id); LLFolderViewItem* view_item = mFolders->getItemByID(item_id); + LLFolderViewFolder* view_folder = mFolders->getFolderByID(item_id); ////////////////////////////// // LABEL Operation @@ -320,7 +321,18 @@ void LLInventoryPanel::modelChanged(U32 mask) view_item->refresh(); } } - + + ////////////////////////////// + // SORT Operation + // Sort the folder. + if (mask & LLInventoryObserver::SORT) + { + if (view_folder) + { + view_folder->requestSort(); + } + } + // We don't typically care which of these masks the item is actually flagged with, since the masks // may not be accurate (e.g. in the main inventory panel, I move an item from My Inventory into // Landmarks; this is a STRUCTURE change for that panel but is an ADD change for the Landmarks @@ -385,16 +397,6 @@ void LLInventoryPanel::modelChanged(U32 mask) } } } - - /* I don't think we need this code, but not positive -- Seraph - if (!handled) - { - // It's a small change that only requires a refresh. - // *TODO: figure out a more efficient way to do the refresh - // since it is expensive on large inventories - mFolders->refresh(); - } - */ } // static @@ -903,13 +905,10 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) if (!auto_open) return NULL; // D. Open the inventory side panel and use that. - LLSideTray *side_tray = LLSideTray::getInstance(); + LLSD key; LLSidepanelInventory *sidepanel_inventory = - dynamic_cast<LLSidepanelInventory *>(side_tray->getPanel("sidepanel_inventory")); - - // Use the inventory side panel only if it is already active. - // Activating it may unexpectedly switch off the currently active tab in some cases. - if (sidepanel_inventory && (LLPanel*)side_tray->getActiveTab() == (LLPanel*)sidepanel_inventory) + dynamic_cast<LLSidepanelInventory *>(LLSideTray::getInstance()->showPanel("sidepanel_inventory", key)); + if (sidepanel_inventory) { return sidepanel_inventory->getActivePanel(); } diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp index 08d56f8b9f..f25d2ef574 100644 --- a/indra/newview/lllandmarkactions.cpp +++ b/indra/newview/lllandmarkactions.cpp @@ -38,6 +38,7 @@ #include "llinventory.h" #include "lllandmark.h" #include "llparcel.h" +#include "llregionhandle.h" #include "llnotificationsutil.h" diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index d613cf6ba4..bd9d22c327 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -39,7 +39,6 @@ #include "llappviewer.h" #include "llagent.h" -#include "llnotify.h" #include "llvfile.h" #include "llviewerstats.h" diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 33fd3e3bf1..fc9654e9ad 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -39,6 +39,8 @@ #include "lltrans.h" #include "llviewercontrol.h" +#include "llinstantmessage.h" + #include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/regex.hpp> diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 765b504afe..5f30ab4e01 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -101,6 +101,16 @@ const U32 ARROW_TO_AXIS[4] = VZ }; +// Sort manipulator handles by their screen-space projection +struct ClosestToCamera +{ + bool operator()(const LLManipTranslate::ManipulatorHandle& a, + const LLManipTranslate::ManipulatorHandle& b) const + { + return a.mEndPosition.mV[VZ] < b.mEndPosition.mV[VZ]; + } +}; + LLManipTranslate::LLManipTranslate( LLToolComposite* composite ) : LLManip( std::string("Move"), composite ), mLastHoverMouseX(-1), @@ -273,7 +283,6 @@ void LLManipTranslate::restoreGL() LLManipTranslate::~LLManipTranslate() { - for_each(mProjectedManipulators.begin(), mProjectedManipulators.end(), DeletePointer()); } @@ -888,8 +897,9 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) planar_manip_xy_visible = TRUE; } - for_each(mProjectedManipulators.begin(), mProjectedManipulators.end(), DeletePointer()); - mProjectedManipulators.clear(); + // Project up to 9 manipulators to screen space 2*X, 2*Y, 2*Z, 3*planes + std::vector<ManipulatorHandle> projected_manipulators; + projected_manipulators.reserve(9); for (S32 i = 0; i < num_arrow_manips; i+= 2) { @@ -899,12 +909,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; projected_end = projected_end * (1.f / projected_end.mV[VW]); - ManipulatorHandle* projManipulator = - new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), MANIPULATOR_IDS[i / 2], 10.f); // 10 pixel hotspot for arrows - mProjectedManipulators.insert(projManipulator); + projected_manipulators.push_back(projected_manip); } if (planar_manip_yz_visible) @@ -916,12 +926,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; projected_end = projected_end * (1.f / projected_end.mV[VW]); - ManipulatorHandle* projManipulator = - new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), MANIPULATOR_IDS[i / 2], 20.f); // 20 pixels for planar manipulators - mProjectedManipulators.insert(projManipulator); + projected_manipulators.push_back(projected_manip); } if (planar_manip_xz_visible) @@ -933,12 +943,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; projected_end = projected_end * (1.f / projected_end.mV[VW]); - ManipulatorHandle* projManipulator = - new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), MANIPULATOR_IDS[i / 2], 20.f); // 20 pixels for planar manipulators - mProjectedManipulators.insert(projManipulator); + projected_manipulators.push_back(projected_manip); } if (planar_manip_xy_visible) @@ -950,12 +960,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; projected_end = projected_end * (1.f / projected_end.mV[VW]); - ManipulatorHandle* projManipulator = - new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), MANIPULATOR_IDS[i / 2], 20.f); // 20 pixels for planar manipulators - mProjectedManipulators.insert(projManipulator); + projected_manipulators.push_back(projected_manip); } LLVector2 manip_start_2d; @@ -967,13 +977,18 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector2 mousePos((F32)x - half_width, (F32)y - half_height); LLVector2 mouse_delta; - for (minpulator_list_t::iterator iter = mProjectedManipulators.begin(); - iter != mProjectedManipulators.end(); ++iter) + // Keep order consistent with insertion via stable_sort + std::stable_sort( projected_manipulators.begin(), + projected_manipulators.end(), + ClosestToCamera() ); + + std::vector<ManipulatorHandle>::iterator it = projected_manipulators.begin(); + for ( ; it != projected_manipulators.end(); ++it) { - ManipulatorHandle* manipulator = *iter; + ManipulatorHandle& manipulator = *it; { - manip_start_2d.setVec(manipulator->mStartPosition.mV[VX] * half_width, manipulator->mStartPosition.mV[VY] * half_height); - manip_end_2d.setVec(manipulator->mEndPosition.mV[VX] * half_width, manipulator->mEndPosition.mV[VY] * half_height); + manip_start_2d.setVec(manipulator.mStartPosition.mV[VX] * half_width, manipulator.mStartPosition.mV[VY] * half_height); + manip_end_2d.setVec(manipulator.mEndPosition.mV[VX] * half_width, manipulator.mEndPosition.mV[VY] * half_height); manip_dir = manip_end_2d - manip_start_2d; mouse_delta = mousePos - manip_start_2d; @@ -985,9 +1000,9 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) if (mouse_pos_manip > 0.f && mouse_pos_manip < manip_length && - mouse_dist_manip_squared < manipulator->mHotSpotRadius * manipulator->mHotSpotRadius) + mouse_dist_manip_squared < manipulator.mHotSpotRadius * manipulator.mHotSpotRadius) { - mHighlightedPart = manipulator->mManipID; + mHighlightedPart = manipulator.mManipID; break; } } diff --git a/indra/newview/llmaniptranslate.h b/indra/newview/llmaniptranslate.h index 25ff35cc72..d20b86b2f4 100644 --- a/indra/newview/llmaniptranslate.h +++ b/indra/newview/llmaniptranslate.h @@ -89,17 +89,6 @@ protected: F32 getMinGridScale(); private: - struct compare_manipulators - { - bool operator() (const ManipulatorHandle* const a, const ManipulatorHandle* const b) const - { - if (a->mEndPosition.mV[VZ] != b->mEndPosition.mV[VZ]) - return (a->mEndPosition.mV[VZ] < b->mEndPosition.mV[VZ]); - else - return a->mManipID < b->mManipID; - } - }; - S32 mLastHoverMouseX; S32 mLastHoverMouseY; BOOL mSendUpdateOnMouseUp; @@ -116,8 +105,6 @@ private: LLVector3d mDragCursorStartGlobal; LLVector3d mDragSelectionStartGlobal; LLTimer mUpdateTimer; - typedef std::set<ManipulatorHandle*, compare_manipulators> minpulator_list_t; - minpulator_list_t mProjectedManipulators; LLVector4 mManipulatorVertices[18]; F32 mSnapOffsetMeters; LLVector3 mSnapOffsetAxis; diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 3c337961e1..91064eea6b 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -58,251 +58,342 @@ // - Any request that gets a 503 still goes through the retry logic // +// +// Forward decls +// const F32 LLMediaDataClient::QUEUE_TIMER_DELAY = 1.0; // seconds(s) const F32 LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY = 5.0; // secs const U32 LLMediaDataClient::MAX_RETRIES = 4; +const U32 LLMediaDataClient::MAX_SORTED_QUEUE_SIZE = 10000; +const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 10000; + +// << operators +std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q); +std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &q); ////////////////////////////////////////////////////////////////////////////////////// // -// LLMediaDataClient::Request +// LLMediaDataClient // ////////////////////////////////////////////////////////////////////////////////////// -/*static*/U32 LLMediaDataClient::Request::sNum = 0; -LLMediaDataClient::Request::Request(const std::string &cap_name, - const LLSD& sd_payload, - LLMediaDataClientObject *obj, - LLMediaDataClient *mdc) - : mCapName(cap_name), - mPayload(sd_payload), - mObject(obj), - mNum(++sNum), - mRetryCount(0), - mMDC(mdc) +LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay, + F32 retry_timer_delay, + U32 max_retries, + U32 max_sorted_queue_size, + U32 max_round_robin_queue_size) + : mQueueTimerDelay(queue_timer_delay), + mRetryTimerDelay(retry_timer_delay), + mMaxNumRetries(max_retries), + mMaxSortedQueueSize(max_sorted_queue_size), + mMaxRoundRobinQueueSize(max_round_robin_queue_size), + mQueueTimerIsRunning(false), + mCurrentQueueIsTheSortedQueue(true) { } -LLMediaDataClient::Request::~Request() +LLMediaDataClient::~LLMediaDataClient() { - LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL; - mMDC = NULL; - mObject = NULL; -} + stopQueueTimer(); - -std::string LLMediaDataClient::Request::getCapability() const -{ - return getObject()->getCapabilityUrl(getCapName()); + // This should clear the queue, and hopefully call all the destructors. + LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " << + (isEmpty() ? "<empty> " : "<not empty> ") << LL_ENDL; + + mSortedQueue.clear(); + mRoundRobinQueue.clear(); } -// Helper function to get the "type" of request, which just pokes around to -// discover it. -LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const +bool LLMediaDataClient::isEmpty() const { - if (mCapName == "ObjectMediaNavigate") - { - return NAVIGATE; - } - else if (mCapName == "ObjectMedia") - { - const std::string &verb = mPayload["verb"]; - if (verb == "GET") - { - return GET; - } - else if (verb == "UPDATE") - { - return UPDATE; - } - } - llassert(false); - return GET; + return mSortedQueue.empty() && mRoundRobinQueue.empty(); } -const char *LLMediaDataClient::Request::getTypeAsString() const +bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object) { - Type t = getType(); - switch (t) - { - case GET: - return "GET"; - break; - case UPDATE: - return "UPDATE"; - break; - case NAVIGATE: - return "NAVIGATE"; - break; - } - return ""; + return (LLMediaDataClient::findOrRemove(mSortedQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull() + || (LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull())); } - -void LLMediaDataClient::Request::reEnqueue() const +bool LLMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object) { - // I sure hope this doesn't deref a bad pointer: - mMDC->enqueue(this); + bool removedFromSortedQueue = LLMediaDataClient::findOrRemove(mSortedQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull(); + bool removedFromRoundRobinQueue = LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull(); + return removedFromSortedQueue || removedFromRoundRobinQueue; } -F32 LLMediaDataClient::Request::getRetryTimerDelay() const +//static +LLMediaDataClient::request_ptr_t LLMediaDataClient::findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, LLMediaDataClient::Request::Type type) { - return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY : - mMDC->mRetryTimerDelay; + request_ptr_t result; + request_queue_t::iterator iter = queue.begin(); + request_queue_t::iterator end = queue.end(); + while (iter != end) + { + if (obj->getID() == (*iter)->getObject()->getID() && (type == LLMediaDataClient::Request::ANY || type == (*iter)->getType())) + { + result = *iter; + if (remove) queue.erase(iter); + break; + } + iter++; + } + return result; } -U32 LLMediaDataClient::Request::getMaxNumRetries() const +void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload) { - return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries; + if (object.isNull() || ! object->hasMedia()) return; + + // Push the object on the queue + enqueue(new Request(getCapabilityName(), payload, object, this)); } -std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r) +void LLMediaDataClient::enqueue(const Request *request) { - s << "<request>" - << "<num>" << r.getNum() << "</num>" - << "<type>" << r.getTypeAsString() << "</type>" - << "<object_id>" << r.getObject()->getID() << "</object_id>" - << "<num_retries>" << r.getRetryCount() << "</num_retries>" - << "</request> "; - return s; + if (request->isNew()) + { + // Add to sorted queue + if (LLMediaDataClient::findOrRemove(mSortedQueue, request->getObject(), true/*remove*/, request->getType()).notNull()) + { + LL_DEBUGS("LLMediaDataClient") << "REMOVING OLD request for " << *request << " ALREADY THERE!" << LL_ENDL; + } + + LL_DEBUGS("LLMediaDataClient") << "Queuing SORTED request for " << *request << LL_ENDL; + + // Sadly, we have to const-cast because items put into the queue are not const + mSortedQueue.push_back(const_cast<LLMediaDataClient::Request*>(request)); + + LL_DEBUGS("LLMediaDataClient") << "SORTED queue:" << mSortedQueue << LL_ENDL; + } + else { + if (mRoundRobinQueue.size() > mMaxRoundRobinQueueSize) + { + LL_INFOS_ONCE("LLMediaDataClient") << "RR QUEUE MAXED OUT!!!" << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << "Not queuing " << *request << LL_ENDL; + return; + } + + // ROUND ROBIN: if it is there, and it is a GET request, leave it. If not, put at front! + request_ptr_t existing_request; + if (request->getType() == Request::GET) + { + existing_request = LLMediaDataClient::findOrRemove(mRoundRobinQueue, request->getObject(), false/*remove*/, request->getType()); + } + if (existing_request.isNull()) + { + LL_DEBUGS("LLMediaDataClient") << "Queuing RR request for " << *request << LL_ENDL; + // Push the request on the pending queue + // Sadly, we have to const-cast because items put into the queue are not const + mRoundRobinQueue.push_front(const_cast<LLMediaDataClient::Request*>(request)); + + LL_DEBUGS("LLMediaDataClient") << "RR queue:" << mRoundRobinQueue << LL_ENDL; + } + else + { + LL_DEBUGS("LLMediaDataClient") << "ALREADY THERE: NOT Queuing request for " << *request << LL_ENDL; + + existing_request->markSent(false); + } + } + // Start the timer if not already running + startQueueTimer(); } - -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::Responder::RetryTimer -// -////////////////////////////////////////////////////////////////////////////////////// - -LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr) - : LLEventTimer(time), mResponder(mdr) +void LLMediaDataClient::startQueueTimer() { + if (! mQueueTimerIsRunning) + { + LL_DEBUGS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL; + // LLEventTimer automagically takes care of the lifetime of this object + new QueueTimer(mQueueTimerDelay, this); + } + else { + LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL; + } } -// virtual -LLMediaDataClient::Responder::RetryTimer::~RetryTimer() +void LLMediaDataClient::stopQueueTimer() { - LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL; - - // XXX This is weird: Instead of doing the work in tick() (which re-schedules - // a timer, which might be risky), do it here, in the destructor. Yes, it is very odd. - // Instead of retrying, we just put the request back onto the queue - LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL; - mResponder->getRequest()->reEnqueue(); - - // Release the ref to the responder. - mResponder = NULL; + mQueueTimerIsRunning = false; } -// virtual -BOOL LLMediaDataClient::Responder::RetryTimer::tick() +bool LLMediaDataClient::processQueueTimer() { - // Don't fire again - return TRUE; + sortQueue(); + + if(!isEmpty()) + { + LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue size is: " << mSortedQueue.size() + << ", RR queue size is: " << mRoundRobinQueue.size() << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue is: " << mSortedQueue << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, RR queue is: " << mRoundRobinQueue << LL_ENDL; + } + + serviceQueue(); + + LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue size is: " << mSortedQueue.size() + << ", RR queue size is: " << mRoundRobinQueue.size() << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue is: " << mSortedQueue << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, RR queue is: " << mRoundRobinQueue << LL_ENDL; + + return isEmpty(); } - -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::Responder -// -////////////////////////////////////////////////////////////////////////////////////// - -LLMediaDataClient::Responder::Responder(const request_ptr_t &request) - : mRequest(request) +void LLMediaDataClient::sortQueue() { + if(!mSortedQueue.empty()) + { + // Score all items first + request_queue_t::iterator iter = mSortedQueue.begin(); + request_queue_t::iterator end = mSortedQueue.end(); + while (iter != end) + { + (*iter)->updateScore(); + iter++; + } + + // Re-sort the list... + // NOTE: should this be a stable_sort? If so we need to change to using a vector. + mSortedQueue.sort(LLMediaDataClient::compareRequests); + + // ...then cull items over the max + U32 size = mSortedQueue.size(); + if (size > mMaxSortedQueueSize) + { + U32 num_to_cull = (size - mMaxSortedQueueSize); + LL_INFOS("LLMediaDataClient") << "sorted queue MAXED OUT! Culling " + << num_to_cull << " items" << LL_ENDL; + while (num_to_cull-- > 0) + { + mSortedQueue.pop_back(); + } + } + } } -LLMediaDataClient::Responder::~Responder() +// static +bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2) { - LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL; - mRequest = NULL; + if (o2.isNull()) return true; + if (o1.isNull()) return false; + return ( o1->getScore() > o2->getScore() ); } -/*virtual*/ -void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) -{ - if (status == HTTP_SERVICE_UNAVAILABLE) +void LLMediaDataClient::serviceQueue() +{ + request_queue_t *queue_p = getCurrentQueue(); + + // quick retry loop for cases where we shouldn't wait for the next timer tick + while(true) { - F32 retry_timeout = mRequest->getRetryTimerDelay(); - - mRequest->incRetryCount(); + if (queue_p->empty()) + { + LL_DEBUGS("LLMediaDataClient") << "queue empty: " << (*queue_p) << LL_ENDL; + break; + } - if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) + // Peel one off of the items from the queue, and execute request + request_ptr_t request = queue_p->front(); + llassert(!request.isNull()); + const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject(); + llassert(NULL != object); + + // Check for conditions that would make us just pop and rapidly loop through + // the queue. + if(request.isNull() || + request->isMarkedSent() || + NULL == object || + object->isDead() || + !object->hasMedia()) { - LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; + if (request.isNull()) + { + LL_INFOS("LLMediaDataClient") << "Skipping NULL request" << LL_ENDL; + } + else { + LL_INFOS("LLMediaDataClient") << "Skipping : " << *request << " " + << ((request->isMarkedSent()) ? " request is marked sent" : + ((NULL == object) ? " object is NULL " : + ((object->isDead()) ? "object is dead" : + ((!object->hasMedia()) ? "object has no media!" : "BADNESS!")))) << LL_ENDL; + } + queue_p->pop_front(); + continue; // jump back to the start of the quick retry loop + } + + // Next, ask if this is "interesting enough" to fetch. If not, just stop + // and wait for the next timer go-round. Only do this for the sorted + // queue. + if (mCurrentQueueIsTheSortedQueue && !object->isInterestingEnough()) + { + LL_DEBUGS("LLMediaDataClient") << "Not fetching " << *request << ": not interesting enough" << LL_ENDL; + break; + } + + // Finally, try to send the HTTP message to the cap url + std::string url = request->getCapability(); + bool maybe_retry = false; + if (!url.empty()) + { + const LLSD &sd_payload = request->getPayload(); + LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL; + + // Call the subclass for creating the responder + LLHTTPClient::post(url, sd_payload, createResponder(request)); + } + else { + LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL; + maybe_retry = true; + } - // Start timer (instances are automagically tracked by - // InstanceTracker<> and LLEventTimer) - new RetryTimer(F32(retry_timeout/*secs*/), this); + bool exceeded_retries = request->getRetryCount() > mMaxNumRetries; + if (maybe_retry && ! exceeded_retries) // Try N times before giving up + { + // We got an empty cap, but in that case we will retry again next + // timer fire. + request->incRetryCount(); } else { - LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retry count " << - mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; + if (exceeded_retries) + { + LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " + << mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL; + // XXX Should we bring up a warning dialog?? + } + + queue_p->pop_front(); + + if (! mCurrentQueueIsTheSortedQueue) { + // Round robin + request->markSent(true); + mRoundRobinQueue.push_back(request); + } } + + // end of quick loop -- any cases where we want to loop will use 'continue' to jump back to the start. + break; } - else { - std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason; - LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL; - } + + swapCurrentQueue(); } - -/*virtual*/ -void LLMediaDataClient::Responder::result(const LLSD& content) +void LLMediaDataClient::swapCurrentQueue() { - LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_print_sd(content) << LL_ENDL; + // Swap + mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue; + // If its empty, swap back + if (getCurrentQueue()->empty()) + { + mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue; + } } - -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::Comparator -// -////////////////////////////////////////////////////////////////////////////////////// - -// static -bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2) +LLMediaDataClient::request_queue_t *LLMediaDataClient::getCurrentQueue() { - if (o2.isNull()) return true; - if (o1.isNull()) return false; - - // The score is intended to be a measure of how close an object is or - // how much screen real estate (interest) it takes up - // Further away = lower score. - // Lesser interest = lower score - // For instance, here are some cases: - // 1: Two items with no impl, closest one wins - // 2: Two items with an impl: interest should rule, but distance is - // still taken into account (i.e. something really close might take - // precedence over a large item far away) - // 3: One item with an impl, another without: item with impl wins - // (XXX is that what we want?) - // Calculate the scores for each. - F64 o1_score = getObjectScore(o1->getObject()); - F64 o2_score = getObjectScore(o2->getObject()); - return ( o1_score > o2_score ); + return (mCurrentQueueIsTheSortedQueue) ? &mSortedQueue : &mRoundRobinQueue; } -// static -F64 LLMediaDataClient::getObjectScore(const LLMediaDataClientObject::ptr_t &obj) -{ - // *TODO: make this less expensive? - F64 dist = obj->getDistanceFromAvatar() + 0.1; // avoids div by 0 - // square the distance so that they are in the same "unit magnitude" as - // the interest (which is an area) - dist *= dist; - F64 interest = obj->getTotalMediaInterest() + 1.0; - - return interest/dist; -} - -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::PriorityQueue -// Queue of LLMediaDataClientObject smart pointers to request media for. -// -////////////////////////////////////////////////////////////////////////////////////// - // dump the queue std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q) { @@ -311,29 +402,13 @@ std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue LLMediaDataClient::request_queue_t::const_iterator end = q.end(); while (iter != end) { - s << "\t" << i << "]: " << (*iter)->getObject()->getID().asString(); + s << "\t" << i << "]: " << (*iter)->getObject()->getID().asString() << "(" << (*iter)->getObject()->getMediaInterest() << ")"; iter++; i++; } return s; } -// find the given object in the queue. -bool LLMediaDataClient::find(const LLMediaDataClientObject::ptr_t &obj) const -{ - request_queue_t::const_iterator iter = pRequestQueue->begin(); - request_queue_t::const_iterator end = pRequestQueue->end(); - while (iter != end) - { - if (obj->getID() == (*iter)->getObject()->getID()) - { - return true; - } - iter++; - } - return false; -} - ////////////////////////////////////////////////////////////////////////////////////// // // LLMediaDataClient::QueueTimer @@ -342,7 +417,7 @@ bool LLMediaDataClient::find(const LLMediaDataClientObject::ptr_t &obj) const ////////////////////////////////////////////////////////////////////////////////////// LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc) - : LLEventTimer(time), mMDC(mdc) +: LLEventTimer(time), mMDC(mdc) { mMDC->setIsRunning(true); } @@ -357,177 +432,224 @@ LLMediaDataClient::QueueTimer::~QueueTimer() // virtual BOOL LLMediaDataClient::QueueTimer::tick() { - if (NULL == mMDC->pRequestQueue) - { - // Shutting down? stop. - LL_DEBUGS("LLMediaDataClient") << "queue gone" << LL_ENDL; - return TRUE; - } - - request_queue_t &queue = *(mMDC->pRequestQueue); + if (mMDC.isNull()) return TRUE; + return mMDC->processQueueTimer(); +} - if(!queue.empty()) - { - LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL; - // Re-sort the list every time... - // XXX Is this really what we want? - queue.sort(LLMediaDataClient::compareRequests); - } +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::Responder::RetryTimer +// +////////////////////////////////////////////////////////////////////////////////////// + +LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr) +: LLEventTimer(time), mResponder(mdr) +{ +} + +// virtual +LLMediaDataClient::Responder::RetryTimer::~RetryTimer() +{ + LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL; - // quick retry loop for cases where we shouldn't wait for the next timer tick - while(true) - { - if (queue.empty()) - { - LL_DEBUGS("LLMediaDataClient") << "queue empty: " << queue << LL_ENDL; - return TRUE; - } + // XXX This is weird: Instead of doing the work in tick() (which re-schedules + // a timer, which might be risky), do it here, in the destructor. Yes, it is very odd. + // Instead of retrying, we just put the request back onto the queue + LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << " retrying" << LL_ENDL; + mResponder->getRequest()->reEnqueue(); - // Peel one off of the items from the queue, and execute request - request_ptr_t request = queue.front(); - llassert(!request.isNull()); - const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject(); - bool performed_request = false; - bool error = false; - llassert(NULL != object); + // Release the ref to the responder. + mResponder = NULL; +} - if(object->isDead()) - { - // This object has been marked dead. Pop it and move on to the next item in the queue immediately. - LL_INFOS("LLMediaDataClient") << "Skipping " << *request << ": object is dead!" << LL_ENDL; - queue.pop_front(); - continue; // jump back to the start of the quick retry loop - } +// virtual +BOOL LLMediaDataClient::Responder::RetryTimer::tick() +{ + // Don't fire again + return TRUE; +} - if (NULL != object && object->hasMedia()) - { - std::string url = request->getCapability(); - if (!url.empty()) - { - const LLSD &sd_payload = request->getPayload(); - LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL; - // Call the subclass for creating the responder - LLHTTPClient::post(url, sd_payload, mMDC->createResponder(request)); - performed_request = true; - } - else { - LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL; - } - } - else { - if (request.isNull()) - { - LL_WARNS("LLMediaDataClient") << "Not Sending request: NULL request!" << LL_ENDL; - } - else if (NULL == object) - { - LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << LL_ENDL; - } - else if (!object->hasMedia()) - { - LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL; - } - error = true; - } - bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries; - if (performed_request || exceeded_retries || error) // Try N times before giving up - { - if (exceeded_retries) - { - LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " - << mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL; - // XXX Should we bring up a warning dialog?? - } - queue.pop_front(); - } - else { - request->incRetryCount(); - } - - // end of quick retry loop -- any cases where we want to loop will use 'continue' to jump back to the start. - break; - } +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::Request +// +////////////////////////////////////////////////////////////////////////////////////// +/*static*/U32 LLMediaDataClient::Request::sNum = 0; - LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, queue is now: " << (*(mMDC->pRequestQueue)) << LL_ENDL; +LLMediaDataClient::Request::Request(const char *cap_name, + const LLSD& sd_payload, + LLMediaDataClientObject *obj, + LLMediaDataClient *mdc) +: mCapName(cap_name), + mPayload(sd_payload), + mObject(obj), + mNum(++sNum), + mRetryCount(0), + mMDC(mdc), + mMarkedSent(false), + mScore((F64)0.0) +{ +} - return queue.empty(); +LLMediaDataClient::Request::~Request() +{ + LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL; + mMDC = NULL; + mObject = NULL; } - -void LLMediaDataClient::startQueueTimer() + + +std::string LLMediaDataClient::Request::getCapability() const { - if (! mQueueTimerIsRunning) + return getObject()->getCapabilityUrl(getCapName()); +} + +// Helper function to get the "type" of request, which just pokes around to +// discover it. +LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const +{ + if (0 == strcmp(mCapName, "ObjectMediaNavigate")) { - LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL; - // LLEventTimer automagically takes care of the lifetime of this object - new QueueTimer(mQueueTimerDelay, this); + return NAVIGATE; } - else { - LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL; + else if (0 == strcmp(mCapName, "ObjectMedia")) + { + const std::string &verb = mPayload["verb"]; + if (verb == "GET") + { + return GET; + } + else if (verb == "UPDATE") + { + return UPDATE; + } } + llassert(false); + return GET; } - -void LLMediaDataClient::stopQueueTimer() + +const char *LLMediaDataClient::Request::getTypeAsString() const { - mQueueTimerIsRunning = false; + Type t = getType(); + switch (t) + { + case GET: + return "GET"; + break; + case UPDATE: + return "UPDATE"; + break; + case NAVIGATE: + return "NAVIGATE"; + break; + case ANY: + return "ANY"; + break; + } + return ""; } - -void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload) + + +void LLMediaDataClient::Request::reEnqueue() const { - if (object.isNull() || ! object->hasMedia()) return; + // I sure hope this doesn't deref a bad pointer: + mMDC->enqueue(this); +} - // Push the object on the priority queue - enqueue(new Request(getCapabilityName(), payload, object, this)); +F32 LLMediaDataClient::Request::getRetryTimerDelay() const +{ + return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY : + mMDC->mRetryTimerDelay; } -void LLMediaDataClient::enqueue(const Request *request) +U32 LLMediaDataClient::Request::getMaxNumRetries() const { - LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL; - // Push the request on the priority queue - // Sadly, we have to const-cast because items put into the queue are not const - pRequestQueue->push_back(const_cast<LLMediaDataClient::Request*>(request)); - LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL; - // Start the timer if not already running - startQueueTimer(); + return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries; } +void LLMediaDataClient::Request::markSent(bool flag) +{ + if (mMarkedSent != flag) + { + mMarkedSent = flag; + if (!mMarkedSent) + { + mNum = ++sNum; + } + } +} + +void LLMediaDataClient::Request::updateScore() +{ + F64 tmp = mObject->getMediaInterest(); + if (tmp != mScore) + { + LL_DEBUGS("LLMediaDataClient") << "Score for " << mObject->getID() << " changed from " << mScore << " to " << tmp << LL_ENDL; + mScore = tmp; + } +} + +std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r) +{ + s << "request: num=" << r.getNum() + << " type=" << r.getTypeAsString() + << " ID=" << r.getObject()->getID() + << " #retries=" << r.getRetryCount(); + return s; +} + + ////////////////////////////////////////////////////////////////////////////////////// // -// LLMediaDataClient +// LLMediaDataClient::Responder // ////////////////////////////////////////////////////////////////////////////////////// -LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay, - F32 retry_timer_delay, - U32 max_retries) - : mQueueTimerDelay(queue_timer_delay), - mRetryTimerDelay(retry_timer_delay), - mMaxNumRetries(max_retries), - mQueueTimerIsRunning(false) +LLMediaDataClient::Responder::Responder(const request_ptr_t &request) +: mRequest(request) { - pRequestQueue = new request_queue_t(); } -LLMediaDataClient::~LLMediaDataClient() +LLMediaDataClient::Responder::~Responder() { - stopQueueTimer(); - - // This should clear the queue, and hopefully call all the destructors. - LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " << - (pRequestQueue->empty() ? "<empty> " : "<not empty> ") << (*pRequestQueue) << LL_ENDL; - delete pRequestQueue; - pRequestQueue = NULL; + LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL; + mRequest = NULL; } -bool LLMediaDataClient::isEmpty() const +/*virtual*/ +void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) { - return (NULL == pRequestQueue) ? true : pRequestQueue->empty(); + if (status == HTTP_SERVICE_UNAVAILABLE) + { + F32 retry_timeout = mRequest->getRetryTimerDelay(); + + mRequest->incRetryCount(); + + if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) + { + LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; + + // Start timer (instances are automagically tracked by + // InstanceTracker<> and LLEventTimer) + new RetryTimer(F32(retry_timeout/*secs*/), this); + } + else { + LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count " << + mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; + } + } + else { + std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason; + LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL; + } } -bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object) const +/*virtual*/ +void LLMediaDataClient::Responder::result(const LLSD& content) { - return (NULL == pRequestQueue) ? false : find(object); + LL_DEBUGS("LLMediaDataClient") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL; } ////////////////////////////////////////////////////////////////////////////////////// @@ -569,7 +691,7 @@ void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object) } sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data; - LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL; request(object, sd_payload); } @@ -581,7 +703,7 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content) llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE) if (type == LLMediaDataClient::Request::GET) { - LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_print_sd(content) << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL; // Look for an error if (content.has("error")) @@ -598,12 +720,13 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content) if (object_id != getRequest()->getObject()->getID()) { // NOT good, wrong object id!! - LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL; + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL; return; } // Otherwise, update with object media data - getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]); + getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY], + content[LLTextureEntry::MEDIA_VERSION_KEY]); } } else if (type == LLMediaDataClient::Request::UPDATE) diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h index 812e9cbdec..75d32e707b 100755 --- a/indra/newview/llmediadataclient.h +++ b/indra/newview/llmediadataclient.h @@ -55,15 +55,19 @@ public: // Does this object have media? virtual bool hasMedia() const = 0; // Update the object's media data to the given array - virtual void updateObjectMediaData(LLSD const &media_data_array) = 0; - // Return the distance from the object to the avatar - virtual F64 getDistanceFromAvatar() const = 0; + virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &version_string) = 0; // Return the total "interest" of the media (on-screen area) - virtual F64 getTotalMediaInterest() const = 0; + virtual F64 getMediaInterest() const = 0; // Return the given cap url virtual std::string getCapabilityUrl(const std::string &name) const = 0; // Return whether the object has been marked dead virtual bool isDead() const = 0; + // Returns a media version number for the object + virtual U32 getMediaVersion() const = 0; + // Returns whether the object is "interesting enough" to fetch + virtual bool isInterestingEnough() const = 0; + // Returns whether we've seen this object yet or not + virtual bool isNew() const = 0; // smart pointer typedef LLPointer<LLMediaDataClientObject> ptr_t; @@ -79,11 +83,15 @@ public: const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s) const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs const static U32 MAX_RETRIES;// = 4; + const static U32 MAX_SORTED_QUEUE_SIZE;// = 10000; + const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 10000; // Constructor LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, - U32 max_retries = MAX_RETRIES); + U32 max_retries = MAX_RETRIES, + U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, + U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE); // Make the request void request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload); @@ -94,7 +102,13 @@ public: bool isEmpty() const; // Returns true iff the given object is in the queue - bool isInQueue(const LLMediaDataClientObject::ptr_t &object) const; + bool isInQueue(const LLMediaDataClientObject::ptr_t &object); + + // Remove the given object from the queue. Returns true iff the given object is removed. + bool removeFromQueue(const LLMediaDataClientObject::ptr_t &object); + + // Called only by the Queue timer and tests (potentially) + bool processQueueTimer(); protected: // Destructor @@ -107,11 +121,12 @@ protected: enum Type { GET, UPDATE, - NAVIGATE + NAVIGATE, + ANY }; - Request(const std::string &cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc); - const std::string &getCapName() const { return mCapName; } + Request(const char *cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc); + const char *getCapName() const { return mCapName; } const LLSD &getPayload() const { return mPayload; } LLMediaDataClientObject *getObject() const { return mObject; } @@ -132,6 +147,12 @@ protected: F32 getRetryTimerDelay() const; U32 getMaxNumRetries() const; + bool isNew() const { return mObject.notNull() ? mObject->isNew() : false; } + void markSent(bool flag); + bool isMarkedSent() const { return mMarkedSent; } + void updateScore(); + F64 getScore() const { return mScore; } + public: friend std::ostream& operator<<(std::ostream &s, const Request &q); @@ -139,14 +160,16 @@ protected: virtual ~Request(); // use unref(); private: - std::string mCapName; + const char *mCapName; LLSD mPayload; LLMediaDataClientObject::ptr_t mObject; // Simple tracking - const U32 mNum; + U32 mNum; static U32 sNum; U32 mRetryCount; - + F64 mScore; + bool mMarkedSent; + // Back pointer to the MDC...not a ref! LLMediaDataClient *mMDC; }; @@ -184,18 +207,23 @@ protected: }; protected: - - void enqueue(const Request*); - + // Subclasses must override this factory method to return a new responder virtual Responder *createResponder(const request_ptr_t &request) const = 0; // Subclasses must override to return a cap name virtual const char *getCapabilityName() const = 0; -private: + virtual void sortQueue(); + virtual void serviceQueue(); +private: typedef std::list<request_ptr_t> request_queue_t; + + void enqueue(const Request*); + + // Return whether the given object is/was in the queue + static LLMediaDataClient::request_ptr_t findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, Request::Type type); // Comparator for sorting static bool compareRequests(const request_ptr_t &o1, const request_ptr_t &o2); @@ -215,34 +243,40 @@ private: // back-pointer LLPointer<LLMediaDataClient> mMDC; }; - - // Return whether the given object is in the queue - bool find(const LLMediaDataClientObject::ptr_t &obj) const; void startQueueTimer(); void stopQueueTimer(); void setIsRunning(bool val) { mQueueTimerIsRunning = val; } - + + void swapCurrentQueue(); + request_queue_t *getCurrentQueue(); + const F32 mQueueTimerDelay; const F32 mRetryTimerDelay; const U32 mMaxNumRetries; + const U32 mMaxSortedQueueSize; + const U32 mMaxRoundRobinQueueSize; bool mQueueTimerIsRunning; - request_queue_t *pRequestQueue; + request_queue_t mSortedQueue; + request_queue_t mRoundRobinQueue; + bool mCurrentQueueIsTheSortedQueue; }; -// MediaDataResponder specific for the ObjectMedia cap +// MediaDataClient specific for the ObjectMedia cap class LLObjectMediaDataClient : public LLMediaDataClient { public: LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, - U32 max_retries = MAX_RETRIES) + U32 max_retries = MAX_RETRIES, + U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, + U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE) : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries) {} - ~LLObjectMediaDataClient() {} + virtual ~LLObjectMediaDataClient() {} void fetchMedia(LLMediaDataClientObject *object); void updateMedia(LLMediaDataClientObject *object); @@ -264,7 +298,7 @@ protected: }; -// MediaDataResponder specific for the ObjectMediaNavigate cap +// MediaDataClient specific for the ObjectMediaNavigate cap class LLObjectMediaNavigateClient : public LLMediaDataClient { public: @@ -273,10 +307,12 @@ public: LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, - U32 max_retries = MAX_RETRIES) + U32 max_retries = MAX_RETRIES, + U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, + U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE) : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries) {} - ~LLObjectMediaNavigateClient() {} + virtual ~LLObjectMediaNavigateClient() {} void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url); diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index 28ddaa61c4..a2aef9ba63 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -49,7 +49,6 @@ #include "llfloaterchat.h" #include "llfloaterworldmap.h" #include "lllineeditor.h" -#include "llnotify.h" #include "llstatusbar.h" #include "llimview.h" #include "lltextbox.h" diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index c17427bec1..22201aecb2 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -160,9 +160,12 @@ void LLFloaterMove::setEnabled(BOOL enabled) // virtual void LLFloaterMove::setVisible(BOOL visible) { - // Ignore excessive calls of this method (from LLTransientFloaterMgr?). + // Do nothing with Stand/Stop Flying panel in excessive calls of this method (from LLTransientFloaterMgr?). if (getVisible() == visible) + { + LLTransientDockableFloater::setVisible(visible); return; + } if (visible) { diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 08bc1fac8b..cdab3b2310 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -34,10 +34,12 @@ #include "llnavigationbar.h" -#include <llfloaterreg.h> -#include <llfocusmgr.h> -#include <lliconctrl.h> -#include <llmenugl.h> +#include "llregionhandle.h" + +#include "llfloaterreg.h" +#include "llfocusmgr.h" +#include "lliconctrl.h" +#include "llmenugl.h" #include "llagent.h" #include "llviewerregion.h" diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 8fb4ea4211..8dbaa5ac53 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -32,6 +32,8 @@ #include "llviewerprecompiledheaders.h" +#include "message.h" + #include "llfloaterreg.h" #include "lltrans.h" diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 5c240aa54a..515c86bae8 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -39,6 +39,7 @@ //#include "llnotificationsutil.h" #include "llchannelmanager.h" #include "llchat.h" +#include "llinstantmessage.h" #include "llnotificationptr.h" namespace LLNotificationsUI @@ -266,6 +267,11 @@ public: static bool canLogToIM(const LLNotificationPtr& notification); /** + * Checks sufficient conditions to log notification message to nearby chat session. + */ + static bool canLogToNearbyChat(const LLNotificationPtr& notification); + + /** * Checks sufficient conditions to spawn IM session. */ static bool canSpawnIMSession(const LLNotificationPtr& notification); @@ -287,6 +293,11 @@ public: * Writes group notice notification message to IM group session. */ static void logGroupNoticeToIMGroup(const LLNotificationPtr& notification); + + /** + * Writes notification message to nearby chat. + */ + static void logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type); }; } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 6748bd7982..5b54092c5c 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -37,6 +37,8 @@ #include "llnotifications.h" #include "llimview.h" #include "llagent.h" +#include "llfloaterreg.h" +#include "llnearbychat.h" using namespace LLNotificationsUI; @@ -47,7 +49,9 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), USER_GIVE_ITEM("UserGiveItem"), OFFER_FRIENDSHIP("OfferFriendship"), FRIENDSHIP_ACCEPTED("FriendshipAccepted"), - FRIENDSHIP_OFFERED("FriendshipOffered"); + FRIENDSHIP_OFFERED("FriendshipOffered"), + FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), + SERVER_OBJECT_MESSAGE("ServerObjectMessage"); // static bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) @@ -55,7 +59,16 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) return GRANTED_MODIFY_RIGHTS == notification->getName() || REVOKED_MODIFY_RIGHTS == notification->getName() || PAYMENT_RECIVED == notification->getName() - || FRIENDSHIP_OFFERED == notification->getName(); + || FRIENDSHIP_OFFERED == notification->getName() + || SERVER_OBJECT_MESSAGE == notification->getName(); +} + +// static +bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) +{ + return notification->getType() == "notifytip" + && FRIEND_ONLINE != notification->getName() + && FRIEND_OFFLINE != notification->getName(); } // static @@ -144,3 +157,15 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( payload["group_id"], sender_id); } +// static +void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type) +{ + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); + if(nearby_chat) + { + LLChat chat_msg(notification->getMessage()); + chat_msg.mSourceType = type; + nearby_chat->addMessage(chat_msg); + } +} + diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 95f5ec801c..9afaddae82 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -88,18 +88,17 @@ bool LLTipHandler::processNotification(const LLSD& notify) if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { // archive message in nearby chat - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); - if(nearby_chat) + if (LLHandlerUtil::canLogToNearbyChat(notification)) { - LLChat chat_msg(notification->getMessage()); - chat_msg.mSourceType = CHAT_SOURCE_SYSTEM; - nearby_chat->addMessage(chat_msg); + LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); // don't show toast if Nearby Chat is opened + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance< + LLNearbyChat>("nearby_chat", LLSD()); if (nearby_chat->getVisible()) { return true; - } + } } LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index eb9cb10d56..ffe7f57167 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -51,6 +51,7 @@ #include "llfloaterworldmap.h" #include "llfloaterreg.h" #include "llnotificationsutil.h" +#include "llvoiceclient.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLDropTarget @@ -395,6 +396,7 @@ void LLPanelProfileTab::updateButtons() && gAgent.isGodlike() || is_agent_mappable(getAvatarId()); childSetEnabled("show_on_map_btn", enable_map_btn); + childSetEnabled("call", LLAvatarActions::canCall(getAvatarId())); } ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 70d92442ad..0dae667e7f 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -48,7 +48,6 @@ #include "message.h" #include "llagent.h" -#include "llalertdialog.h" #include "llavataractions.h" #include "llbutton.h" #include "llcheckboxctrl.h" diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 2cb3967685..fff2575893 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -90,6 +90,7 @@ LLPanelGroup::LLPanelGroup() : LLPanel(), LLGroupMgrObserver( LLUUID() ), mAllowEdit( TRUE ) + ,mShowingNotifyDialog(false) { // Set up the factory callbacks. // Roles sub tabs @@ -538,3 +539,69 @@ void LLPanelGroup::showNotice(const std::string& subject, } +bool LLPanelGroup::canClose() +{ + if(getVisible() == false) + return true; + + bool need_save = false; + std::string mesg; + for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it) + if(need_save|=(*it)->needsApply(mesg)) + break; + if(!need_save) + return false; + // If no message was provided, give a generic one. + if (mesg.empty()) + { + mesg = mDefaultNeedsApplyMesg; + } + // Create a notify box, telling the user about the unapplied tab. + LLSD args; + args["NEEDS_APPLY_MESSAGE"] = mesg; + args["WANT_APPLY_MESSAGE"] = mWantApplyMesg; + + LLNotificationsUtil::add("SaveChanges", args, LLSD(), boost::bind(&LLPanelGroup::handleNotifyCallback,this, _1, _2)); + + mShowingNotifyDialog = true; + + return false; +} + +bool LLPanelGroup::notifyChildren(const LLSD& info) +{ + if(info.has("request") && mID.isNull() ) + { + std::string str_action = info["request"]; + + if (str_action == "quit" ) + { + canClose(); + return true; + } + if(str_action == "wait_quit") + return mShowingNotifyDialog; + } + return false; +} +bool LLPanelGroup::handleNotifyCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + mShowingNotifyDialog = false; + switch (option) + { + case 0: // "Apply Changes" + apply(); + break; + case 1: // "Ignore Changes" + break; + case 2: // "Cancel" + default: + // Do nothing. The user is canceling the action. + // If we were quitting, we didn't really mean it. + LLAppViewer::instance()->abortQuit(); + break; + } + return false; +} + diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index 306e6575fc..f6aefdb676 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -89,7 +89,10 @@ public: const std::string& inventory_name, LLOfferInfo* inventory_offer); - + + bool notifyChildren (const LLSD& info); + bool handleNotifyCallback(const LLSD&, const LLSD&); + protected: virtual void update(LLGroupChange gc); @@ -107,6 +110,9 @@ protected: protected: bool apply(LLPanelGroupTab* tab); + bool canClose(); + + bool mShowingNotifyDialog; LLTimer mRefreshTimer; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index b6c58808ae..29b647415c 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -44,7 +44,6 @@ #include "llnamelistctrl.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llpanelgrouproles.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index c85fab2092..35cd3edc81 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -37,6 +37,7 @@ #include "llfloaterreg.h" #include "llsdutil.h" #include "llsdutil_math.h" +#include "llregionhandle.h" #include "llaccordionctrl.h" #include "llaccordionctrltab.h" @@ -66,6 +67,30 @@ static const std::string TRASH_BUTTON_NAME = "trash_btn"; // helper functions static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string); +static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list); + +/** + * Bridge to support knowing when the inventory has changed to update folder (open/close) state + * for landmarks panels. + * + * Due to Inventory data are loaded in background we need to save folder state each time + * next level is loaded. See EXT-3094. + */ +class LLLandmarksPanelObserver : public LLInventoryObserver +{ +public: + LLLandmarksPanelObserver(LLLandmarksPanel* lp) : mLP(lp) {} + virtual ~LLLandmarksPanelObserver() {} + /*virtual*/ void changed(U32 mask); + +private: + LLLandmarksPanel* mLP; +}; + +void LLLandmarksPanelObserver::changed(U32 mask) +{ + mLP->saveFolderStateIfNoFilter(); +} LLLandmarksPanel::LLLandmarksPanel() : LLPanelPlacesTab() @@ -78,11 +103,18 @@ LLLandmarksPanel::LLLandmarksPanel() , mGearFolderMenu(NULL) , mGearLandmarkMenu(NULL) { + mInventoryObserver = new LLLandmarksPanelObserver(this); + gInventory.addObserver(mInventoryObserver); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml"); } LLLandmarksPanel::~LLLandmarksPanel() { + if (gInventory.containsObserver(mInventoryObserver)) + { + gInventory.removeObserver(mInventoryObserver); + } } BOOL LLLandmarksPanel::postBuild() @@ -226,6 +258,14 @@ void LLLandmarksPanel::onSelectorButtonClicked() } } +void LLLandmarksPanel::saveFolderStateIfNoFilter() +{ + save_folder_state_if_no_filter(mFavoritesInventoryPanel); + save_folder_state_if_no_filter(mLandmarksInventoryPanel); + save_folder_state_if_no_filter(mMyInventoryPanel); + save_folder_state_if_no_filter(mLibraryInventoryPanel); +} + ////////////////////////////////////////////////////////////////////////// // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// @@ -328,6 +368,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel() initLandmarksPanel(mFavoritesInventoryPanel); mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems"); + initAccordion("tab_favorites", mFavoritesInventoryPanel); } @@ -389,6 +430,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis } root_folder->setParentLandmarksPanel(this); + inventory_list->saveFolderState(); } void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list) @@ -743,7 +785,7 @@ void LLLandmarksPanel::updateFilteredAccordions() { LLInventoryPanel* inventory_list = NULL; LLAccordionCtrlTab* accordion_tab = NULL; -// bool needs_arrange = false; + bool needs_arrange = false; for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) { @@ -755,7 +797,7 @@ void LLLandmarksPanel::updateFilteredAccordions() if (NULL == inventory_list) continue; // This doesn't seem to work correctly. Disabling for now. -Seraph - /* + // Enabled to show/hide accordions with/without landmarks. See EXT-2346. (Seth PE) LLFolderView* fv = inventory_list->getRootFolder(); // arrange folder view contents to draw its descendants if it has any @@ -766,17 +808,17 @@ void LLLandmarksPanel::updateFilteredAccordions() needs_arrange = true; accordion_tab->setVisible(has_descendants); - */ - accordion_tab->setVisible(TRUE); + + //accordion_tab->setVisible(TRUE); } // we have to arrange accordion tabs for cases when filter string is less restrictive but // all items are still filtered. -// if (needs_arrange) -// { + if (needs_arrange) + { static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion"); accordion->arrange(); -// } + } } /* @@ -991,23 +1033,41 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark) ////////////////////////////////////////////////////////////////////////// static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string) { - // Open the immediate children of the root folder, since those - // are invisible in the UI and thus must always be open. - inventory_list->getRootFolder()->openTopLevelFolders(); - + // When search is cleared, restore the old folder state. if (string == "") { inventory_list->setFilterSubString(LLStringUtil::null); + // Re-open folders that were open before + inventory_list->restoreFolderState(); } + // Open the immediate children of the root folder, since those + // are invisible in the UI and thus must always be open. + inventory_list->getRootFolder()->openTopLevelFolders(); + if (inventory_list->getFilterSubString().empty() && string.empty()) { // current filter and new filter empty, do nothing return; } + // save current folder open state if no filter currently applied + if (inventory_list->getRootFolder()->getFilterSubString().empty()) + { + inventory_list->saveFolderState(); + } + // Set new filter string inventory_list->setFilterSubString(string); } + +static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list) +{ + // save current folder open state if no filter currently applied + if (inventory_list->getRootFolder() && inventory_list->getRootFolder()->getFilterSubString().empty()) + { + // inventory_list->saveFolderState(); // *TODO: commented out to fix build + } +} // EOF diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index bee141d051..b0e537f647 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -67,6 +67,11 @@ public: mCurrentSelectedList = inventory_list; } + /** + * Saves folder state for all Inventory Panels if there are no applied filter. + */ + void saveFolderStateIfNoFilter(); + protected: /** * @return true - if current selected panel is not null and selected item is a landmark @@ -151,6 +156,7 @@ private: LLMenuGL* mGearFolderMenu; LLMenuGL* mMenuAdd; LLInventorySubTreePanel* mCurrentSelectedList; + LLInventoryObserver* mInventoryObserver; LLPanel* mListCommands; bool mSortByDate; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index a729b8c06f..a9c604b72a 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -62,7 +62,6 @@ #include "llviewermenu.h" // for handle_preferences() #include "llviewernetwork.h" #include "llviewerwindow.h" // to link into child list -#include "llnotify.h" #include "llurlsimstring.h" #include "lluictrlfactory.h" #include "llhttpclient.h" @@ -73,6 +72,11 @@ #include "llfloatertos.h" #include "lltrans.h" #include "llglheaders.h" +#include "llpanelloginlistener.h" + +#if LL_WINDOWS +#pragma warning(disable: 4355) // 'this' used in initializer list +#endif // LL_WINDOWS #define USE_VIEWER_AUTH 0 @@ -166,7 +170,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, mLogoImage(), mCallback(callback), mCallbackData(cb_data), - mHtmlAvailable( TRUE ) + mHtmlAvailable( TRUE ), + mListener(new LLPanelLoginListener(this)) { setFocusRoot(TRUE); @@ -452,7 +457,7 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask) if ( KEY_F1 == key ) { LLViewerHelp* vhelp = LLViewerHelp::getInstance(); - vhelp->showTopic(vhelp->getTopicFromFocus()); + vhelp->showTopic(vhelp->f1HelpTopic()); return TRUE; } @@ -972,7 +977,7 @@ void LLPanelLogin::onClickHelp(void*) if (sInstance) { LLViewerHelp* vhelp = LLViewerHelp::getInstance(); - vhelp->showTopic(vhelp->getTopicFromFocus()); + vhelp->showTopic(vhelp->preLoginTopic()); } } diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index e3d30d7d0c..97350ce5c7 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -36,10 +36,11 @@ #include "llpanel.h" #include "llpointer.h" // LLPointer<> #include "llmediactrl.h" // LLMediaCtrlObserver +#include <boost/scoped_ptr.hpp> class LLLineEditor; class LLUIImage; - +class LLPanelLoginListener; class LLPanelLogin: public LLPanel, @@ -90,6 +91,7 @@ public: /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); private: + friend class LLPanelLoginListener; void reshapeBrowser(); static void onClickConnect(void*); static void onClickNewAccount(void*); @@ -103,6 +105,7 @@ private: private: LLPointer<LLUIImage> mLogoImage; + boost::scoped_ptr<LLPanelLoginListener> mListener; void (*mCallback)(S32 option, void *userdata); void* mCallbackData; diff --git a/indra/newview/llpanelloginlistener.cpp b/indra/newview/llpanelloginlistener.cpp new file mode 100644 index 0000000000..f7e59aaf54 --- /dev/null +++ b/indra/newview/llpanelloginlistener.cpp @@ -0,0 +1,34 @@ +/** + * @file llpanelloginlistener.cpp + * @author Nat Goodspeed + * @date 2009-12-10 + * @brief Implementation for llpanelloginlistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llpanelloginlistener.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llpanellogin.h" + +LLPanelLoginListener::LLPanelLoginListener(LLPanelLogin* instance): + LLEventAPI("LLPanelLogin", "Access to LLPanelLogin methods"), + mPanel(instance) +{ + add("onClickConnect", + "Pretend user clicked the \"Log In\" button", + &LLPanelLoginListener::onClickConnect); +} + +void LLPanelLoginListener::onClickConnect(const LLSD&) const +{ + mPanel->onClickConnect(NULL); +} diff --git a/indra/newview/llpanelloginlistener.h b/indra/newview/llpanelloginlistener.h new file mode 100644 index 0000000000..0a56c75422 --- /dev/null +++ b/indra/newview/llpanelloginlistener.h @@ -0,0 +1,30 @@ +/** + * @file llpanelloginlistener.h + * @author Nat Goodspeed + * @date 2009-12-10 + * @brief LLEventAPI for LLPanelLogin + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLPANELLOGINLISTENER_H) +#define LL_LLPANELLOGINLISTENER_H + +#include "lleventapi.h" +class LLPanelLogin; +class LLSD; + +class LLPanelLoginListener: public LLEventAPI +{ +public: + LLPanelLoginListener(LLPanelLogin* instance); + +private: + void onClickConnect(const LLSD&) const; + + LLPanelLogin* mPanel; +}; + +#endif /* ! defined(LL_LLPANELLOGINLISTENER_H) */ diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 21627e84ff..c0da8f3daa 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llpanelmaininventory.h" +#include "llagent.h" #include "lldndbutton.h" #include "llfilepicker.h" #include "llfloaterinventory.h" @@ -529,11 +530,23 @@ BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } -void LLPanelMainInventory::changed(U32 mask) +// virtual +void LLPanelMainInventory::changed(U32) { + // empty, but must have this defined for abstract base class. } +// virtual +void LLPanelMainInventory::draw() +{ + if (mActivePanel && mFilterEditor) + { + mFilterEditor->setText(mActivePanel->getFilterSubString()); + } + LLPanel::draw(); +} + void LLPanelMainInventory::setFilterTextFromFilter() { mFilterText = mActivePanel->getFilter()->getFilterText(); @@ -863,7 +876,6 @@ void LLPanelMainInventory::initListCommandsHandlers() mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2)); mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - } void LLPanelMainInventory::updateListCommands() @@ -909,6 +921,22 @@ void LLPanelMainInventory::onClipboardAction(const LLSD& userdata) getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); } +void LLPanelMainInventory::saveTexture(const LLSD& userdata) +{ + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (!current_item) + { + return; + } + + const LLUUID& item_id = current_item->getListener()->getUUID(); + LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); + if (preview_texture) + { + preview_texture->openToSave(); + } +} + void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { if (!isActionEnabled(userdata)) @@ -953,18 +981,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } if (command_name == "save_texture") { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (!current_item) - { - return; - } - - const LLUUID& item_id = current_item->getListener()->getUUID(); - LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); - if (preview_texture) - { - preview_texture->openToSave(); - } + saveTexture(userdata); } // This doesn't currently work, since the viewer can't change an assetID an item. if (command_name == "regenerate_link") @@ -1008,6 +1025,22 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } } +bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) +{ + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (current_item) + { + LLViewerInventoryItem *inv_item = current_item->getInventoryItem(); + if(inv_item) + { + bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); + LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType(); + return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT); + } + } + return false; +} + BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { const std::string command_name = userdata.asString(); @@ -1035,12 +1068,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) } if (command_name == "save_texture") { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (current_item) - { - return (current_item->getListener()->getInventoryType() == LLInventoryType::IT_TEXTURE); - } - return FALSE; + return isSaveTextureEnabled(userdata); } if (command_name == "find_original") { diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index ae78d3bec8..920de2665c 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -72,7 +72,8 @@ public: void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); - /*virtual*/ void changed(U32 mask); + /*virtual*/ void changed(U32); + /*virtual*/ void draw(); LLInventoryPanel* getPanel() { return mActivePanel; } LLInventoryPanel* getActivePanel() { return mActivePanel; } @@ -110,6 +111,8 @@ protected: void doCreate(const LLSD& userdata); void resetFilters(); void setSortBy(const LLSD& userdata); + void saveTexture(const LLSD& userdata); + bool isSaveTextureEnabled(const LLSD& userdata); private: LLFloaterInventoryFinder* getFinder(); diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 3fa0e7bf8f..f574f55beb 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -67,7 +67,6 @@ const char *CHECKERBOARD_DATA_URL = "data:image/svg+xml,%3Csvg xmlns=%22http://w //////////////////////////////////////////////////////////////////////////////// // LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() : - mControls( NULL ), mAutoLoop( NULL ), mFirstClick( NULL ), mAutoZoom( NULL ), @@ -93,8 +92,7 @@ BOOL LLPanelMediaSettingsGeneral::postBuild() mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY ); mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY ); mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY ); - mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY ); - mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY ); + mCurrentURL = getChild< LLTextBox >( LLMediaEntry::CURRENT_URL_KEY ); mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY ); mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY ); mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY ); @@ -211,7 +209,6 @@ void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable) self->mAutoPlay->clear(); self->mAutoScale->clear(); self->mAutoZoom ->clear(); - self->mControls->clear(); self->mCurrentURL->clear(); self->mFirstClick->clear(); self->mHeightPixels->clear(); @@ -221,7 +218,6 @@ void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable) self->mAutoPlay ->setEnabled(editable); self->mAutoScale ->setEnabled(editable); self->mAutoZoom ->setEnabled(editable); - self->mControls ->setEnabled(editable); self->mCurrentURL ->setEnabled(editable); self->mFirstClick ->setEnabled(editable); self->mHeightPixels ->setEnabled(editable); @@ -283,8 +279,7 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_ { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" }, { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" }, { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" }, - { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" }, - { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLLineEditor" }, + { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLTextBox" }, { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" }, { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" }, { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" }, @@ -416,7 +411,6 @@ void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in ) fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = (LLSD::Boolean)mAutoPlay->getValue(); fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = (LLSD::Boolean)mAutoScale->getValue(); fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = (LLSD::Boolean)mAutoZoom->getValue(); - fill_me_in[LLMediaEntry::CONTROLS_KEY] = (LLSD::Integer)mControls->getCurrentIndex(); //Don't fill in current URL: this is only supposed to get changed via navigate // fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue(); fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = (LLSD::Integer)mHeightPixels->getValue(); @@ -518,4 +512,9 @@ void LLPanelMediaSettingsGeneral::updateCurrentUrl() bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_current_url, value_str ); mCurrentURL->setText(value_str); mCurrentURL->setTentative(identical); + + if ( LLPanelMediaSettingsGeneral::isMultiple() ) + { + mCurrentURL->setText(LLTrans::getString("Multiple Media")); + } } diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h index 7782b25d63..5f90321362 100644 --- a/indra/newview/llpanelmediasettingsgeneral.h +++ b/indra/newview/llpanelmediasettingsgeneral.h @@ -37,7 +37,6 @@ class LLButton; class LLCheckBoxCtrl; -class LLComboBox; class LLLineEditor; class LLSpinCtrl; class LLTextureCtrl; @@ -90,7 +89,6 @@ private: void checkHomeUrlPassesWhitelist(); - LLComboBox* mControls; LLCheckBoxCtrl* mAutoLoop; LLCheckBoxCtrl* mFirstClick; LLCheckBoxCtrl* mAutoZoom; @@ -99,7 +97,7 @@ private: LLSpinCtrl* mWidthPixels; LLSpinCtrl* mHeightPixels; LLLineEditor* mHomeURL; - LLLineEditor* mCurrentURL; + LLTextBox* mCurrentURL; LLMediaCtrl* mPreviewMedia; LLTextBox* mFailWhiteListText; }; diff --git a/indra/newview/llpanelmediasettingspermissions.cpp b/indra/newview/llpanelmediasettingspermissions.cpp index 2f3f550e35..a23aed2e98 100644 --- a/indra/newview/llpanelmediasettingspermissions.cpp +++ b/indra/newview/llpanelmediasettingspermissions.cpp @@ -51,9 +51,11 @@ #include "llnamebox.h" #include "lltrans.h" #include "llfloatermediasettings.h" + //////////////////////////////////////////////////////////////////////////////// // LLPanelMediaSettingsPermissions::LLPanelMediaSettingsPermissions() : + mControls( NULL ), mPermsOwnerInteract( 0 ), mPermsOwnerControl( 0 ), mPermsGroupName( 0 ), @@ -71,6 +73,7 @@ LLPanelMediaSettingsPermissions::LLPanelMediaSettingsPermissions() : BOOL LLPanelMediaSettingsPermissions::postBuild() { // connect member vars with UI widgets + mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY ); mPermsOwnerInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_OWNER_INTERACT_KEY ); mPermsOwnerControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_OWNER_CONTROL_KEY ); mPermsGroupInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_GROUP_INTERACT_KEY ); @@ -123,19 +126,22 @@ void LLPanelMediaSettingsPermissions::draw() void LLPanelMediaSettingsPermissions::clearValues( void* userdata, bool editable) { LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata; + + self->mControls->clear(); self->mPermsOwnerInteract->clear(); self->mPermsOwnerControl->clear(); - self->mPermsGroupInteract ->clear(); + self->mPermsGroupInteract->clear(); self->mPermsGroupControl->clear(); - self->mPermsWorldInteract ->clear(); - self->mPermsWorldControl ->clear(); + self->mPermsWorldInteract->clear(); + self->mPermsWorldControl->clear(); + self->mControls->setEnabled(editable); self->mPermsOwnerInteract->setEnabled(editable); - self->mPermsOwnerControl ->setEnabled(editable); + self->mPermsOwnerControl->setEnabled(editable); self->mPermsGroupInteract->setEnabled(editable); - self->mPermsGroupControl ->setEnabled(editable); + self->mPermsGroupControl->setEnabled(editable); self->mPermsWorldInteract->setEnabled(editable); - self->mPermsWorldControl ->setEnabled(editable); + self->mPermsWorldControl->setEnabled(editable); } //////////////////////////////////////////////////////////////////////////////// @@ -175,6 +181,7 @@ void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& me } data_set [] = { + { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" }, { LLPanelContents::PERMS_OWNER_INTERACT_KEY, self->mPermsOwnerInteract, "LLCheckBoxCtrl" }, { LLPanelContents::PERMS_OWNER_CONTROL_KEY, self->mPermsOwnerControl, "LLCheckBoxCtrl" }, { LLPanelContents::PERMS_GROUP_INTERACT_KEY, self->mPermsGroupInteract, "LLCheckBoxCtrl" }, @@ -194,27 +201,27 @@ void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& me { if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) { - // the sense of the checkboxes changed and it made sense - // to just reverse their sense back again here and avoid - // changing server code. + // Most recent change to the "sense" of these checkboxes + // means the value in the checkbox matches that on the server static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> - setValue( ! media_settings[ base_key ].asBoolean() ); + setValue( media_settings[ base_key ].asBoolean() ); } else if ( data_set[ i ].ctrl_type == "LLComboBox" ) static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )-> setCurrentByIndex( media_settings[ base_key ].asInteger() ); + data_set[ i ].ctrl_ptr->setEnabled(editable); data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); }; }; + self->childSetEnabled("media_perms_label_owner", editable ); self->childSetText("media_perms_label_owner", LLTrans::getString("Media Perms Owner") ); self->childSetEnabled("media_perms_label_group", editable ); self->childSetText("media_perms_label_group", LLTrans::getString("Media Perms Group") ); self->childSetEnabled("media_perms_label_anyone", editable ); self->childSetText("media_perms_label_anyone", LLTrans::getString("Media Perms Anyone") ); - } //////////////////////////////////////////////////////////////////////////////// @@ -228,6 +235,9 @@ void LLPanelMediaSettingsPermissions::preApply() // void LLPanelMediaSettingsPermissions::getValues( LLSD &fill_me_in ) { + // moved over from the 'General settings' tab + fill_me_in[LLMediaEntry::CONTROLS_KEY] = (LLSD::Integer)mControls->getCurrentIndex(); + // *NOTE: For some reason, gcc does not like these symbol references in the // expressions below (inside the static_casts). I have NO idea why :(. // For some reason, assigning them to const temp vars here fixes the link @@ -237,13 +247,13 @@ void LLPanelMediaSettingsPermissions::getValues( LLSD &fill_me_in ) const U8 group = LLMediaEntry::PERM_GROUP; const U8 anyone = LLMediaEntry::PERM_ANYONE; const LLSD::Integer control = static_cast<LLSD::Integer>( - (mPermsOwnerControl->getValue() ? none : owner ) | - (mPermsGroupControl->getValue() ? none : group ) | - (mPermsWorldControl->getValue() ? none : anyone )); + (mPermsOwnerControl->getValue() ? owner : none ) | + (mPermsGroupControl->getValue() ? group: none ) | + (mPermsWorldControl->getValue() ? anyone : none )); const LLSD::Integer interact = static_cast<LLSD::Integer>( - (mPermsOwnerInteract->getValue() ? none : owner ) | - (mPermsGroupInteract->getValue() ? none : group ) | - (mPermsWorldInteract->getValue() ? none : anyone )); + (mPermsOwnerInteract->getValue() ? owner: none ) | + (mPermsGroupInteract->getValue() ? group : none ) | + (mPermsWorldInteract->getValue() ? anyone : none )); fill_me_in[LLMediaEntry::PERMS_CONTROL_KEY] = control; fill_me_in[LLMediaEntry::PERMS_INTERACT_KEY] = interact; } @@ -255,3 +265,5 @@ void LLPanelMediaSettingsPermissions::postApply() { // no-op } + + diff --git a/indra/newview/llpanelmediasettingspermissions.h b/indra/newview/llpanelmediasettingspermissions.h index 45a596c615..bd0c3b8ab5 100644 --- a/indra/newview/llpanelmediasettingspermissions.h +++ b/indra/newview/llpanelmediasettingspermissions.h @@ -65,6 +65,7 @@ public: static void clearValues( void* userdata, bool editable); private: + LLComboBox* mControls; LLCheckBoxCtrl* mPermsOwnerInteract; LLCheckBoxCtrl* mPermsOwnerControl; LLNameBox* mPermsGroupName; diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp index d87c7608d5..aea6b0aa3b 100644 --- a/indra/newview/llpanelmediasettingssecurity.cpp +++ b/indra/newview/llpanelmediasettingssecurity.cpp @@ -167,6 +167,9 @@ void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); }; }; + + // initial update - hides/shows status messages etc. + self->updateWhitelistEnableStatus(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 9d38dab26e..43366ef814 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -157,7 +157,7 @@ LLInventoryItem* LLTaskInvFVBridge::findItem() const LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); if(object) { - return (LLInventoryItem*)(object->getInventoryObject(mUUID)); + return dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mUUID)); } return NULL; } @@ -712,6 +712,7 @@ public: virtual LLUIImagePtr getIcon() const; virtual const std::string& getDisplayName() const { return getName(); } virtual BOOL isItemRenameable() const; + // virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL renameItem(const std::string& new_name); virtual BOOL isItemRemovable(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 4511bca23a..5b36a5406a 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -75,12 +75,12 @@ LLPanelOutfitsInventory::~LLPanelOutfitsInventory() BOOL LLPanelOutfitsInventory::postBuild() { - initAccordionPanels(); + initTabPanels(); initListCommandsHandlers(); return TRUE; } -void LLPanelOutfitsInventory::updateParent() +void LLPanelOutfitsInventory::updateVerbs() { if (mParent) { @@ -127,7 +127,7 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string) mActivePanel->setFilterSubString(string); } -void LLPanelOutfitsInventory::onWear() +void LLPanelOutfitsInventory::onWearButtonClick() { LLFolderViewEventListener* listenerp = getCorrectListenerForAction(); if (listenerp) @@ -167,7 +167,7 @@ void LLPanelOutfitsInventory::onNew() void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) { updateListCommands(); - updateParent(); + updateVerbs(); if (getRootFolder()->needsAutoRename() && items.size()) { getRootFolder()->startRenamingSelectedItem(); @@ -234,13 +234,14 @@ void LLPanelOutfitsInventory::initListCommandsHandlers() mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this)); mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this)); mListCommands->childSetAction("add_btn", boost::bind(&LLPanelOutfitsInventory::onAddButtonClick, this)); - + mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this)); + LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn"); trash_btn->setDragAndDropHandler(boost::bind(&LLPanelOutfitsInventory::handleDragAndDropToTrash, this - , _4 // BOOL drop - , _5 // EDragAndDropType cargo_type - , _7 // EAcceptance* accept - )); + , _4 // BOOL drop + , _5 // EDragAndDropType cargo_type + , _7 // EAcceptance* accept + )); mCommitCallbackRegistrar.add("panel_outfits_inventory_gear_default.Custom.Action", boost::bind(&LLPanelOutfitsInventory::onCustomAction, this, _2)); @@ -252,8 +253,10 @@ void LLPanelOutfitsInventory::initListCommandsHandlers() void LLPanelOutfitsInventory::updateListCommands() { bool trash_enabled = isActionEnabled("delete"); + bool wear_enabled = isActionEnabled("wear"); mListCommands->childSetEnabled("trash_btn", trash_enabled); + mListCommands->childSetEnabled("wear_btn", wear_enabled); } void LLPanelOutfitsInventory::onGearButtonClick() @@ -308,7 +311,7 @@ void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata) } if (command_name == "wear") { - onWear(); + onWearButtonClick(); } if (command_name == "add") { @@ -407,41 +410,41 @@ bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropTy //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// -// Accordion // +// Tab panels // -void LLPanelOutfitsInventory::initAccordionPanels() +void LLPanelOutfitsInventory::initTabPanels() { - mAccordionPanels.resize(2); + mTabPanels.resize(2); LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>("outfitslist_accordionpanel"); myoutfits_panel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, LLInventoryFilter::FILTERTYPE_CATEGORY); myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mAccordionPanels[0] = myoutfits_panel; + mTabPanels[0] = myoutfits_panel; mActivePanel = myoutfits_panel; LLInventoryPanel *cof_panel = getChild<LLInventoryPanel>("cof_accordionpanel"); cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mAccordionPanels[1] = cof_panel; + mTabPanels[1] = cof_panel; - for (accordionpanels_vec_t::iterator iter = mAccordionPanels.begin(); - iter != mAccordionPanels.end(); + for (tabpanels_vec_t::iterator iter = mTabPanels.begin(); + iter != mTabPanels.end(); ++iter) { LLInventoryPanel *panel = (*iter); - panel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onAccordionSelectionChange, this, panel, _1, _2)); + panel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onTabSelectionChange, this, panel, _1, _2)); } } -void LLPanelOutfitsInventory::onAccordionSelectionChange(LLInventoryPanel* accordion_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action) +void LLPanelOutfitsInventory::onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action) { if (user_action && items.size() > 0) { - for (accordionpanels_vec_t::iterator iter = mAccordionPanels.begin(); - iter != mAccordionPanels.end(); + for (tabpanels_vec_t::iterator iter = mTabPanels.begin(); + iter != mTabPanels.end(); ++iter) { LLInventoryPanel *panel = (*iter); - if (panel == accordion_panel) + if (panel == tab_panel) { mActivePanel = panel; } @@ -459,10 +462,10 @@ LLInventoryPanel* LLPanelOutfitsInventory::getActivePanel() return mActivePanel; } -bool LLPanelOutfitsInventory::isAccordionPanel(LLInventoryPanel *panel) +bool LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel) { - for(accordionpanels_vec_t::iterator it = mAccordionPanels.begin(); - it != mAccordionPanels.end(); + for(tabpanels_vec_t::iterator it = mTabPanels.begin(); + it != mTabPanels.end(); ++it) { if (*it == panel) diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index afeaef485d..9b6b483e3b 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -54,7 +54,6 @@ public: /*virtual*/ BOOL postBuild(); void onSearchEdit(const std::string& string); - void onWear(); void onAdd(); void onRemove(); void onEdit(); @@ -71,29 +70,30 @@ public: LLFolderView* getRootFolder(); protected: - void updateParent(); + void updateVerbs(); bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const; private: LLSidepanelAppearance* mParent; LLSaveFolderState* mSavedFolderState; + public: ////////////////////////////////////////////////////////////////////////////////// - // Accordion // + // tab panels LLInventoryPanel* getActivePanel(); - bool isAccordionPanel(LLInventoryPanel *panel); + bool isTabPanel(LLInventoryPanel *panel); protected: - void initAccordionPanels(); - void onAccordionSelectionChange(LLInventoryPanel* accordion_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action); + void initTabPanels(); + void onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action); private: LLInventoryPanel* mActivePanel; - typedef std::vector<LLInventoryPanel *> accordionpanels_vec_t; - accordionpanels_vec_t mAccordionPanels; + typedef std::vector<LLInventoryPanel *> tabpanels_vec_t; + tabpanels_vec_t mTabPanels; - // Accordion // + // tab panels // //////////////////////////////////////////////////////////////////////////////// @@ -103,6 +103,7 @@ protected: void initListCommandsHandlers(); void updateListCommands(); void onGearButtonClick(); + void onWearButtonClick(); void onAddButtonClick(); void showActionMenu(LLMenuGL* menu, std::string spawning_view_name); void onTrashButtonClick(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 1e4682701e..e134840153 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -586,6 +586,7 @@ BOOL LLPanelPeople::postBuild() registrar.add("People.Groups.ViewSort.Action", boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked, this, _2)); registrar.add("People.Recent.ViewSort.Action", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked, this, _2)); + enable_registrar.add("People.Group.Minus.Enable", boost::bind(&LLPanelPeople::isRealGroup, this)); enable_registrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2)); enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2)); enable_registrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2)); @@ -775,7 +776,7 @@ void LLPanelPeople::updateButtons() buttonSetEnabled("teleport_btn", friends_tab_active && item_selected && isFriendOnline(selected_uuids.front())); buttonSetEnabled("view_profile_btn", item_selected); buttonSetEnabled("im_btn", multiple_selected); // allow starting the friends conference for multiple selection - buttonSetEnabled("call_btn", multiple_selected); + buttonSetEnabled("call_btn", multiple_selected && canCall()); buttonSetEnabled("share_btn", item_selected); // not implemented yet bool none_group_selected = item_selected && selected_id.isNull(); @@ -783,6 +784,29 @@ void LLPanelPeople::updateButtons() buttonSetEnabled("chat_btn", !none_group_selected); } +bool LLPanelPeople::canCall() +{ + std::vector<LLUUID> selected_uuids; + getCurrentItemIDs(selected_uuids); + + bool result = false; + + std::vector<LLUUID>::const_iterator + id = selected_uuids.begin(), + uuids_end = selected_uuids.end(); + + for (;id != uuids_end; ++id) + { + if (LLAvatarActions::canCall(*id)) + { + result = true; + break; + } + } + + return result; +} + std::string LLPanelPeople::getActiveTabName() const { return mTabContainer->getCurrentPanel()->getName(); @@ -921,6 +945,11 @@ void LLPanelPeople::reSelectedCurrentTab() mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex()); } +bool LLPanelPeople::isRealGroup() +{ + return getCurrentItemID() != LLUUID::null; +} + void LLPanelPeople::onFilterEdit(const std::string& search_string) { std::string search_upper = search_string; diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index a9cc6d0ccb..f5cdc0935c 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -73,6 +73,7 @@ private: bool isFriendOnline(const LLUUID& id); bool isItemsFreeOfFriends(const std::vector<LLUUID>& uuids); + bool canCall(); void updateButtons(); std::string getActiveTabName() const; @@ -118,6 +119,8 @@ private: void onGroupsViewSortMenuItemClicked(const LLSD& userdata); void onRecentViewSortMenuItemClicked(const LLSD& userdata); + //returns false only if group is "none" + bool isRealGroup(); bool onFriendsViewSortMenuItemCheck(const LLSD& userdata); bool onRecentViewSortMenuItemCheck(const LLSD& userdata); bool onNearbyViewSortMenuItemCheck(const LLSD& userdata); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 57f3d86d53..0314642d9e 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -81,6 +81,14 @@ void ContextMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids, LLMenuGL::showPopup(spawning_view, mMenu, x, y); } +void ContextMenu::hide() +{ + if(mMenu) + { + mMenu->hide(); + } +} + //== NearbyMenu =============================================================== LLContextMenu* NearbyMenu::createMenu() @@ -100,7 +108,7 @@ LLContextMenu* NearbyMenu::createMenu() registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, id)); registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::startIM, id)); // *TODO: unimplemented - registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, id)); // *TODO: unimplemented + registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id)); registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id)); registrar.add("Avatar.BlockUnblock", boost::bind(&LLAvatarActions::toggleBlock, id)); @@ -173,7 +181,25 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) const LLUUID& id = mUUIDs.front(); return LLAvatarActions::isFriend(id); } + else if (item == std::string("can_call")) + { + bool result = false; + int size = mUUIDs.size(); + std::cout << size << std::endl; + std::vector<LLUUID>::const_iterator + id = mUUIDs.begin(), + uuids_end = mUUIDs.end(); + for (;id != uuids_end; ++id) + { + if (LLAvatarActions::canCall(*id)) + { + result = true; + break; + } + } + return result; + } return false; } diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h index ed0f8208f6..14ae2985f0 100644 --- a/indra/newview/llpanelpeoplemenus.h +++ b/indra/newview/llpanelpeoplemenus.h @@ -54,6 +54,8 @@ public: */ /*virtual*/ void show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y); + virtual void hide(); + protected: virtual LLContextMenu* createMenu() = 0; diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 541361324a..839452d061 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -91,12 +91,19 @@ LLPanelPickInfo::LLPanelPickInfo() , mAvatarId(LLUUID::null) , mSnapshotCtrl(NULL) , mPickId(LLUUID::null) + , mParcelId(LLUUID::null) + , mRequestedId(LLUUID::null) { } LLPanelPickInfo::~LLPanelPickInfo() { LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); + + if (mParcelId.notNull()) + { + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); + } } void LLPanelPickInfo::onOpen(const LLSD& key) @@ -156,12 +163,14 @@ void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type) return; } + mParcelId = pick_info->parcel_id; setSnapshotId(pick_info->snapshot_id); setPickName(pick_info->name); setPickDesc(pick_info->desc); setPosGlobal(pick_info->pos_global); - setPickLocation(createLocationText(pick_info->user_name, pick_info->original_name, - pick_info->sim_name, pick_info->pos_global)); + + // Send remote parcel info request to get parcel name and sim (region) name. + sendParcelInfoRequest(); // *NOTE dzaporozhan // We want to keep listening to APT_PICK_INFO because user may @@ -169,6 +178,17 @@ void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type) // revomeObserver is called from onClickBack } +void LLPanelPickInfo::sendParcelInfoRequest() +{ + if (mParcelId != mRequestedId) + { + LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this); + LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId); + + mRequestedId = mParcelId; + } +} + void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb) { getChild<LLButton>("back_btn")->setClickedCallback(cb); @@ -176,21 +196,16 @@ void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb) void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data) { - // HACK: Flag 0x2 == adult region, - // Flag 0x1 == mature region, otherwise assume PG - std::string rating_icon = "icon_event.tga"; - if (parcel_data.flags & 0x2) - { - rating_icon = "icon_event_adult.tga"; - } - else if (parcel_data.flags & 0x1) - { - rating_icon = "icon_event_mature.tga"; - } + setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name, + parcel_data.sim_name, getPosGlobal())); - childSetValue("maturity", rating_icon); + // We have received parcel info for the requested ID so clear it now. + mRequestedId.setNull(); - //*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us + if (mParcelId.notNull()) + { + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); + } } void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb) @@ -222,7 +237,8 @@ void LLPanelPickInfo::resetData() setPickId(LLUUID::null); setSnapshotId(LLUUID::null); mPosGlobal.clearVec(); - childSetValue("maturity", LLStringUtil::null); + mParcelId.setNull(); + mRequestedId.setNull(); } // static @@ -273,9 +289,6 @@ void LLPanelPickInfo::setPickDesc(const std::string& desc) void LLPanelPickInfo::setPickLocation(const std::string& location) { childSetValue(XML_LOCATION, location); - - //preserving non-wrapped text for info/edit modes switching - mLocation = location; } void LLPanelPickInfo::onClickMap() @@ -340,7 +353,7 @@ void LLPanelPickEdit::onOpen(const LLSD& key) setPosGlobal(gAgent.getPositionGlobal()); LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null; - std::string pick_name, pick_desc; + std::string pick_name, pick_desc, region_name; LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if(parcel) @@ -351,21 +364,17 @@ void LLPanelPickEdit::onOpen(const LLSD& key) snapshot_id = parcel->getSnapshotID(); } - if(pick_name.empty()) + LLViewerRegion* region = gAgent.getRegion(); + if(region) { - LLViewerRegion* region = gAgent.getRegion(); - if(region) - { - pick_name = region->getName(); - } + region_name = region->getName(); } setParcelID(parcel_id); - childSetValue("pick_name", pick_name); + childSetValue("pick_name", pick_name.empty() ? region_name : pick_name); childSetValue("pick_desc", pick_desc); setSnapshotId(snapshot_id); - setPickLocation(createLocationText(LLStringUtil::null, SET_LOCATION_NOTICE, - pick_name, getPosGlobal())); + setPickLocation(createLocationText(SET_LOCATION_NOTICE, pick_name, region_name, getPosGlobal())); enableSaveButton(true); } @@ -394,8 +403,9 @@ void LLPanelPickEdit::setPickData(const LLPickData* pick_data) childSetValue("pick_name", pick_data->name); childSetValue("pick_desc", pick_data->desc); setSnapshotId(pick_data->snapshot_id); - setPickLocation(createLocationText(pick_data->user_name, pick_data->original_name, /*pick_data->sim_name,*/ - pick_data->name, pick_data->pos_global)); + setPosGlobal(pick_data->pos_global); + setPickLocation(createLocationText(LLStringUtil::null, pick_data->name, + pick_data->sim_name, pick_data->pos_global)); } BOOL LLPanelPickEdit::postBuild() @@ -519,14 +529,22 @@ void LLPanelPickEdit::onClickSetLocation() // Save location for later use. setPosGlobal(gAgent.getPositionGlobal()); + std::string parcel_name, region_name; + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if (parcel) { mParcelId = parcel->getID(); - mSimName = parcel->getName(); + parcel_name = parcel->getName(); } - setPickLocation(createLocationText( - LLStringUtil::null, SET_LOCATION_NOTICE, mSimName, getPosGlobal())); + + LLViewerRegion* region = gAgent.getRegion(); + if(region) + { + region_name = region->getName(); + } + + setPickLocation(createLocationText(SET_LOCATION_NOTICE, parcel_name, region_name, getPosGlobal())); mLocationChanged = true; enableSaveButton(TRUE); diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 2c0830f2ac..95add387d0 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -72,6 +72,11 @@ public: /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); /** + * Sends remote parcel info request to resolve parcel name from its ID. + */ + void sendParcelInfoRequest(); + + /** * Sets "Back" button click callback */ virtual void setExitCallback(const commit_callback_t& cb); @@ -81,9 +86,9 @@ public: */ virtual void setEditPickCallback(const commit_callback_t& cb); - //This stuff we got from LLRemoteParcelObserver, in the last two we intentionally do nothing + //This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); - /*virtual*/ void setParcelID(const LLUUID& parcel_id) {}; + /*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; } /*virtual*/ void setErrorStatus(U32 status, const std::string& reason) {}; protected: @@ -154,8 +159,7 @@ protected: LLVector3d mPosGlobal; LLUUID mParcelId; LLUUID mPickId; - std::string mSimName; - std::string mLocation; + LLUUID mRequestedId; }; /** diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 59a68bc12d..0a13180c73 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -37,6 +37,8 @@ #include "llagent.h" #include "llagentpicksinfo.h" #include "llavatarconstants.h" +#include "llcommandhandler.h" +#include "lldispatcher.h" #include "llflatlistview.h" #include "llfloaterreg.h" #include "llfloaterworldmap.h" @@ -55,6 +57,7 @@ #include "llpanelprofile.h" #include "llpanelpick.h" #include "llpanelclassified.h" +#include "llsidetray.h" static const std::string XML_BTN_NEW = "new_btn"; static const std::string XML_BTN_DELETE = "trash_btn"; @@ -72,6 +75,102 @@ static const std::string CLASSIFIED_NAME("classified_name"); static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks"); +class LLClassifiedHandler : + public LLCommandHandler, + public LLAvatarPropertiesObserver +{ +public: + // throttle calls from untrusted browsers + LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} + + std::set<LLUUID> mClassifiedIds; + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + // handle app/classified/create urls first + if (params.size() == 1 && params[0].asString() == "create") + { + createClassified(); + return true; + } + + // then handle the general app/classified/{UUID}/{CMD} urls + if (params.size() < 2) + { + return false; + } + + // get the ID for the classified + LLUUID classified_id; + if (!classified_id.set(params[0], FALSE)) + { + return false; + } + + // show the classified in the side tray. + // need to ask the server for more info first though... + const std::string verb = params[1].asString(); + if (verb == "about") + { + mClassifiedIds.insert(classified_id); + LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); + return true; + } + + return false; + } + + void createClassified() + { + // open the new classified panel on the Me > Picks sidetray + LLSD params; + params["id"] = gAgent.getID(); + params["open_tab_name"] = "panel_picks"; + params["show_tab_panel"] = "create_classified"; + LLSideTray::getInstance()->showPanel("panel_me", params); + } + + void openClassified(LLAvatarClassifiedInfo* c_info) + { + // open the classified info panel on the Me > Picks sidetray + LLSD params; + params["id"] = c_info->creator_id; + params["open_tab_name"] = "panel_picks"; + params["show_tab_panel"] = "classified_details"; + params["classified_id"] = c_info->classified_id; + params["classified_avatar_id"] = c_info->creator_id; + params["classified_snapshot_id"] = c_info->snapshot_id; + params["classified_name"] = c_info->name; + params["classified_desc"] = c_info->description; + LLSideTray::getInstance()->showPanel("panel_profile_view", params); + } + + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type) + { + if (APT_CLASSIFIED_INFO != type) + { + return; + } + + // is this the classified that we asked for? + LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); + if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end()) + { + return; + } + + // open the detail side tray for this classified + openClassified(c_info); + + // remove our observer now that we're done + mClassifiedIds.erase(c_info->classified_id); + LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); + } + +}; +LLClassifiedHandler gClassifiedHandler; + ////////////////////////////////////////////////////////////////////////// /** @@ -612,14 +711,24 @@ void LLPanelPicks::openClassifiedInfo() LLClassifiedItem* c_item = getSelectedClassifiedItem(); + openClassifiedInfo(c_item->getClassifiedId(), c_item->getAvatarId(), + c_item->getSnapshotId(), c_item->getClassifiedName(), + c_item->getDescription()); +} + +void LLPanelPicks::openClassifiedInfo(const LLUUID &classified_id, + const LLUUID &avatar_id, + const LLUUID &snapshot_id, + const std::string &name, const std::string &desc) +{ createClassifiedInfoPanel(); LLSD params; - params["classified_id"] = c_item->getClassifiedId(); - params["avatar_id"] = c_item->getAvatarId(); - params["snapshot_id"] = c_item->getSnapshotId(); - params["name"] = c_item->getClassifiedName(); - params["desc"] = c_item->getDescription(); + params["classified_id"] = classified_id; + params["avatar_id"] = avatar_id; + params["snapshot_id"] = snapshot_id; + params["name"] = name; + params["desc"] = desc; getProfilePanel()->openPanel(mPanelClassifiedInfo, params); } diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 21794d56b2..0ebf9e26dd 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -117,6 +117,10 @@ private: void openPickInfo(); void openClassifiedInfo(); + void openClassifiedInfo(const LLUUID &classified_id, const LLUUID &avatar_id, + const LLUUID &snapshot_id, const std::string &name, + const std::string &desc); + friend class LLPanelProfile; void showAccordion(const std::string& name, bool show); diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp index 71d763b562..6985b73200 100644 --- a/indra/newview/llpanelplace.cpp +++ b/indra/newview/llpanelplace.cpp @@ -40,6 +40,7 @@ #include "llsecondlifeurls.h" #include "llfloater.h" #include "llfloaterreg.h" +#include "llregionhandle.h" #include "llagent.h" #include "llviewerwindow.h" diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 6ba3790fe2..b80eb9db38 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -39,6 +39,8 @@ #include "llsecondlifeurls.h" #include "llsdutil_math.h" +#include "llregionhandle.h" +#include "message.h" #include "lliconctrl.h" #include "lltextbox.h" @@ -231,8 +233,10 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) if (!parcel_data.name.empty()) { + mParcelTitle = parcel_data.name; + mParcelName->setText(llformat("%s (%d, %d, %d)", - parcel_data.name.c_str(), region_x, region_y, region_z)); + mParcelTitle.c_str(), region_x, region_y, region_z)); } else { @@ -282,15 +286,12 @@ void LLPanelPlaceInfo::handleVisibilityChange(BOOL new_visibility) void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel) { - std::string name = mParcelName->getText(); - if (name.empty()) - { - name = mRegionName->getText(); - } + std::string region_name = mRegionName->getText(); LLPickData data; data.pos_global = pos_global; - data.name = name; + data.name = mParcelTitle.empty() ? region_name : mParcelTitle; + data.sim_name = region_name; data.desc = mDescEditor->getText(); data.snapshot_id = mSnapshotCtrl->getImageAssetID(); data.parcel_id = mParcelID; diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index b9bf92b534..7dfc7b2444 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -111,6 +111,7 @@ protected: LLUUID mParcelID; LLUUID mRequestedID; LLVector3 mPosRegion; + std::string mParcelTitle; // used for pick title without coordinates std::string mCurrentTitle; S32 mScrollingPanelMinHeight; S32 mScrollingPanelWidth; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 0c7cc9af38..402d50ba9c 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -35,6 +35,7 @@ #include "llpanelplaceprofile.h" #include "llparcel.h" +#include "message.h" #include "lliconctrl.h" #include "lllineeditor.h" diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index f7f3c5830d..685104a8b1 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -54,6 +54,7 @@ #include "llavatarpropertiesprocessor.h" #include "llfloaterworldmap.h" #include "llinventorybridge.h" +#include "llinventoryobserver.h" #include "llinventorymodel.h" #include "lllandmarkactions.h" #include "lllandmarklist.h" @@ -62,6 +63,7 @@ #include "llpanelpick.h" #include "llpanelplaceprofile.h" #include "llpanelteleporthistory.h" +#include "llremoteparcelrequest.h" #include "llteleporthistorystorage.h" #include "lltoggleablemenu.h" #include "llviewerinventory.h" @@ -85,8 +87,10 @@ static void onSLURLBuilt(std::string& slurl); class LLPlacesParcelObserver : public LLParcelObserver { public: - LLPlacesParcelObserver(LLPanelPlaces* places_panel) - : mPlaces(places_panel) {} + LLPlacesParcelObserver(LLPanelPlaces* places_panel) : + LLParcelObserver(), + mPlaces(places_panel) + {} /*virtual*/ void changed() { @@ -101,8 +105,10 @@ private: class LLPlacesInventoryObserver : public LLInventoryObserver { public: - LLPlacesInventoryObserver(LLPanelPlaces* places_panel) - : mPlaces(places_panel) {} + LLPlacesInventoryObserver(LLPanelPlaces* places_panel) : + LLInventoryObserver(), + mPlaces(places_panel) + {} /*virtual*/ void changed(U32 mask) { @@ -114,6 +120,59 @@ private: LLPanelPlaces* mPlaces; }; +class LLPlacesRemoteParcelInfoObserver : public LLRemoteParcelInfoObserver +{ +public: + LLPlacesRemoteParcelInfoObserver(LLPanelPlaces* places_panel) : + LLRemoteParcelInfoObserver(), + mPlaces(places_panel) + {} + + ~LLPlacesRemoteParcelInfoObserver() + { + // remove any in-flight observers + std::set<LLUUID>::iterator it; + for (it = mParcelIDs.begin(); it != mParcelIDs.end(); ++it) + { + const LLUUID &id = *it; + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(id, this); + } + mParcelIDs.clear(); + } + + /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data) + { + if (mPlaces) + { + mPlaces->changedGlobalPos(LLVector3d(parcel_data.global_x, + parcel_data.global_y, + parcel_data.global_z)); + } + + mParcelIDs.erase(parcel_data.parcel_id); + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_data.parcel_id, this); + } + /*virtual*/ void setParcelID(const LLUUID& parcel_id) + { + if (!parcel_id.isNull()) + { + mParcelIDs.insert(parcel_id); + LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this); + LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id); + } + } + /*virtual*/ void setErrorStatus(U32 status, const std::string& reason) + { + llerrs << "Can't complete remote parcel request. Http Status: " + << status << ". Reason : " << reason << llendl; + } + +private: + std::set<LLUUID> mParcelIDs; + LLPanelPlaces* mPlaces; +}; + + static LLRegisterPanelClassWrapper<LLPanelPlaces> t_places("panel_places"); LLPanelPlaces::LLPanelPlaces() @@ -131,6 +190,7 @@ LLPanelPlaces::LLPanelPlaces() { mParcelObserver = new LLPlacesParcelObserver(this); mInventoryObserver = new LLPlacesInventoryObserver(this); + mRemoteParcelObserver = new LLPlacesRemoteParcelInfoObserver(this); gInventory.addObserver(mInventoryObserver); @@ -149,6 +209,7 @@ LLPanelPlaces::~LLPanelPlaces() delete mInventoryObserver; delete mParcelObserver; + delete mRemoteParcelObserver; } BOOL LLPanelPlaces::postBuild() @@ -239,7 +300,6 @@ void LLPanelPlaces::onOpen(const LLSD& key) mItem = NULL; isLandmarkEditModeOn = false; togglePlaceInfoPanel(TRUE); - updateVerbs(); if (mPlaceInfoType == AGENT_INFO_TYPE) { @@ -278,12 +338,24 @@ void LLPanelPlaces::onOpen(const LLSD& key) } else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE) { - mPosGlobal = LLVector3d(key["x"].asReal(), - key["y"].asReal(), - key["z"].asReal()); + if (key.has("id")) + { + LLUUID parcel_id = key["id"].asUUID(); + mPlaceProfile->setParcelID(parcel_id); + + // query the server to get the global 3D position of this + // parcel - we need this for teleport/mapping functions. + mRemoteParcelObserver->setParcelID(parcel_id); + } + else + { + mPosGlobal = LLVector3d(key["x"].asReal(), + key["y"].asReal(), + key["z"].asReal()); + mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal); + } mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE); - mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal); } else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE) { @@ -298,6 +370,8 @@ void LLPanelPlaces::onOpen(const LLSD& key) mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal); } + updateVerbs(); + LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); if (!parcel_mgr) return; @@ -829,6 +903,12 @@ void LLPanelPlaces::changedInventory(U32 mask) gInventory.removeObserver(mInventoryObserver); } +void LLPanelPlaces::changedGlobalPos(const LLVector3d &global_pos) +{ + mPosGlobal = global_pos; + updateVerbs(); +} + void LLPanelPlaces::updateVerbs() { bool is_place_info_visible; @@ -845,6 +925,7 @@ void LLPanelPlaces::updateVerbs() bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE; bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE; + bool have_3d_pos = ! mPosGlobal.isExactlyZero(); mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); @@ -854,6 +935,7 @@ void LLPanelPlaces::updateVerbs() mCancelBtn->setVisible(isLandmarkEditModeOn); mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); + mShowOnMapBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos); mOverflowBtn->setEnabled(is_place_info_visible && !is_create_landmark_visible); if (is_place_info_visible) @@ -862,12 +944,12 @@ void LLPanelPlaces::updateVerbs() { // We don't need to teleport to the current location // so check if the location is not within the current parcel. - mTeleportBtn->setEnabled(!mPosGlobal.isExactlyZero() && + mTeleportBtn->setEnabled(have_3d_pos && !LLViewerParcelMgr::getInstance()->inAgentParcel(mPosGlobal)); } else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE) { - mTeleportBtn->setEnabled(TRUE); + mTeleportBtn->setEnabled(have_3d_pos); } } else diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 5f9aed6357..5ee8704992 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -47,6 +47,7 @@ class LLPanelPlacesTab; class LLParcelSelection; class LLPlacesInventoryObserver; class LLPlacesParcelObserver; +class LLRemoteParcelInfoObserver; class LLTabContainer; class LLToggleableMenu; @@ -65,6 +66,8 @@ public: void changedParcelSelection(); // Called on agent inventory change to find out when inventory gets usable. void changedInventory(U32 mask); + // Called when we receive the global 3D position of a parcel. + void changedGlobalPos(const LLVector3d &global_pos); void setItem(LLInventoryItem* item); @@ -112,6 +115,7 @@ private: LLPlacesInventoryObserver* mInventoryObserver; LLPlacesParcelObserver* mParcelObserver; + LLRemoteParcelInfoObserver* mRemoteParcelObserver; // Pointer to a landmark item or to a linked landmark LLPointer<LLInventoryItem> mItem; diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index aa2b7d4554..7b2ac38568 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -57,6 +57,7 @@ #include "llsliderctrl.h" #include "llstring.h" #include "llviewercontrol.h" +#include "llviewerdisplay.h" #include "llviewerparcelmgr.h" #include "llviewermedia.h" #include "llviewermediafocus.h" @@ -66,8 +67,11 @@ #include "llfloatertools.h" // to enable hide if build tools are up +// Functions pulled from pipeline.cpp glh::matrix4f glh_get_current_modelview(); glh::matrix4f glh_get_current_projection(); +// Functions pulled from llviewerdisplay.cpp +bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model); // Warning: make sure these two match! const LLPanelPrimMediaControls::EZoomLevel LLPanelPrimMediaControls::kZoomLevels[] = { ZOOM_NONE, ZOOM_MEDIUM }; @@ -150,7 +154,7 @@ BOOL LLPanelPrimMediaControls::postBuild() mSkipFwdCtrl = getChild<LLUICtrl>("skip_forward"); mSkipBackCtrl = getChild<LLUICtrl>("skip_back"); mVolumeCtrl = getChild<LLUICtrl>("media_volume"); - mVolumeBtn = getChild<LLButton>("media_volume_button"); + mMuteBtn = getChild<LLButton>("media_mute_button"); mVolumeUpCtrl = getChild<LLUICtrl>("volume_up"); mVolumeDownCtrl = getChild<LLUICtrl>("volume_down"); mVolumeSliderCtrl = getChild<LLSliderCtrl>("volume_slider"); @@ -200,7 +204,7 @@ BOOL LLPanelPrimMediaControls::postBuild() mScrollDownCtrl->setHeldDownCallback(onScrollDownHeld, this); mScrollDownCtrl->setMouseUpCallback(onScrollStop, this); } - + mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this )); mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout"); mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime"); @@ -215,11 +219,15 @@ void LLPanelPrimMediaControls::setMediaFace(LLPointer<LLViewerObject> objectp, S { if (media_impl.notNull() && objectp.notNull()) { + LLUUID prev_id = mTargetImplID; mTargetImplID = media_impl->getMediaTextureID(); mTargetObjectID = objectp->getID(); mTargetObjectFace = face; mTargetObjectNormal = pick_normal; mClearFaceOnFade = false; + + if (prev_id != mTargetImplID) + mVolumeSliderCtrl->setValue(media_impl->getVolume()); } else { @@ -308,13 +316,12 @@ void LLPanelPrimMediaControls::updateShape() enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL); mini_controls = (LLMediaEntry::MINI == media_data->getControls()); } - const bool is_hud = objectp->isHUDAttachment(); // // Set the state of the buttons // - + // XXX RSP: TODO: FIXME: clean this up so that it is clearer what mode we are in, // and that only the proper controls get made visible/enabled according to that mode. mBackCtrl->setVisible(has_focus); @@ -343,7 +350,7 @@ void LLPanelPrimMediaControls::updateShape() mStopCtrl->setEnabled(has_focus && can_navigate); mHomeCtrl->setEnabled(has_focus && can_navigate); LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE; - + if(media_plugin && media_plugin->pluginSupportsMediaTime()) { mReloadCtrl->setEnabled(false); @@ -360,14 +367,14 @@ void LLPanelPrimMediaControls::updateShape() mSkipFwdCtrl->setEnabled(has_focus && !mini_controls); mSkipBackCtrl->setVisible(has_focus && !mini_controls); mSkipBackCtrl->setEnabled(has_focus && !mini_controls); - + mVolumeCtrl->setVisible(has_focus); mVolumeUpCtrl->setVisible(has_focus); mVolumeDownCtrl->setVisible(has_focus); mVolumeCtrl->setEnabled(has_focus); mVolumeSliderCtrl->setEnabled(has_focus && mVolumeSliderVisible); mVolumeSliderCtrl->setVisible(has_focus && mVolumeSliderVisible); - + mWhitelistIcon->setVisible(false); mSecureLockIcon->setVisible(false); if (mMediaPanelScroll) @@ -378,7 +385,7 @@ void LLPanelPrimMediaControls::updateShape() mScrollRightCtrl->setVisible(false); mScrollDownCtrl->setVisible(false); } - + F32 volume = media_impl->getVolume(); // movie's url changed if(mCurrentURL!=mPreviousURL) @@ -386,7 +393,7 @@ void LLPanelPrimMediaControls::updateShape() mMovieDuration = media_plugin->getDuration(); mPreviousURL = mCurrentURL; } - + if(mMovieDuration == 0) { mMovieDuration = media_plugin->getDuration(); @@ -394,7 +401,7 @@ void LLPanelPrimMediaControls::updateShape() mMediaPlaySliderCtrl->setEnabled(false); } // TODO: What if it's not fully loaded - + if(mUpdateSlider && mMovieDuration!= 0) { F64 current_time = media_plugin->getCurrentTime(); @@ -402,29 +409,27 @@ void LLPanelPrimMediaControls::updateShape() mMediaPlaySliderCtrl->setValue(percent); mMediaPlaySliderCtrl->setEnabled(true); } - + // video vloume if(volume <= 0.0) { mVolumeUpCtrl->setEnabled(TRUE); mVolumeDownCtrl->setEnabled(FALSE); - media_impl->setVolume(0.0); - mVolumeBtn->setToggleState(true); + mMuteBtn->setToggleState(true); } else if (volume >= 1.0) { mVolumeUpCtrl->setEnabled(FALSE); mVolumeDownCtrl->setEnabled(TRUE); - media_impl->setVolume(1.0); - mVolumeBtn->setToggleState(false); + mMuteBtn->setToggleState(false); } else { + mMuteBtn->setToggleState(false); mVolumeUpCtrl->setEnabled(TRUE); mVolumeDownCtrl->setEnabled(TRUE); } - mVolumeSliderCtrl->setValue(volume); - + switch(result) { case LLPluginClassMediaOwner::MEDIA_PLAYING: @@ -453,7 +458,7 @@ void LLPanelPrimMediaControls::updateShape() { mCurrentURL.clear(); } - + mPlayCtrl->setVisible(FALSE); mPauseCtrl->setVisible(FALSE); mMediaStopCtrl->setVisible(FALSE); @@ -465,7 +470,7 @@ void LLPanelPrimMediaControls::updateShape() mSkipFwdCtrl->setEnabled(FALSE); mSkipBackCtrl->setVisible(FALSE); mSkipBackCtrl->setEnabled(FALSE); - + mVolumeCtrl->setVisible(FALSE); mVolumeUpCtrl->setVisible(FALSE); mVolumeDownCtrl->setVisible(FALSE); @@ -491,13 +496,13 @@ void LLPanelPrimMediaControls::updateShape() { mSecureLockIcon->setVisible(has_focus); } - + if(mCurrentURL!=mPreviousURL) { setCurrentURL(); mPreviousURL = mCurrentURL; } - + if(result == LLPluginClassMediaOwner::MEDIA_LOADING) { mReloadCtrl->setEnabled(FALSE); @@ -513,7 +518,7 @@ void LLPanelPrimMediaControls::updateShape() mStopCtrl->setVisible(FALSE); } } - + if(media_plugin) { @@ -530,7 +535,7 @@ void LLPanelPrimMediaControls::updateShape() mMediaProgressPanel->setVisible(false); } } - + if(media_impl) { // @@ -538,62 +543,59 @@ void LLPanelPrimMediaControls::updateShape() // switch (mScrollState) { - case SCROLL_UP: - media_impl->scrollWheel(0, -1, MASK_NONE); - break; - case SCROLL_DOWN: - media_impl->scrollWheel(0, 1, MASK_NONE); - break; - case SCROLL_LEFT: - media_impl->scrollWheel(1, 0, MASK_NONE); -// media_impl->handleKeyHere(KEY_LEFT, MASK_NONE); - break; - case SCROLL_RIGHT: - media_impl->scrollWheel(-1, 0, MASK_NONE); -// media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE); - break; - case SCROLL_NONE: - default: - break; + case SCROLL_UP: + media_impl->scrollWheel(0, -1, MASK_NONE); + break; + case SCROLL_DOWN: + media_impl->scrollWheel(0, 1, MASK_NONE); + break; + case SCROLL_LEFT: + media_impl->scrollWheel(1, 0, MASK_NONE); + // media_impl->handleKeyHere(KEY_LEFT, MASK_NONE); + break; + case SCROLL_RIGHT: + media_impl->scrollWheel(-1, 0, MASK_NONE); + // media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE); + break; + case SCROLL_NONE: + default: + break; } } setVisible(enabled); - + // // Calculate position and shape of the controls // - LLVector3 min, max; - - glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview(); std::vector<LLVector3>::iterator vert_it; std::vector<LLVector3>::iterator vert_end; std::vector<LLVector3> vect_face; - + LLVolume* volume = objectp->getVolume(); - + if (volume) { const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace); - + const LLVector3* ext = vf.mExtents; - + LLVector3 center = (ext[0]+ext[1])*0.5f; LLVector3 size = (ext[1]-ext[0])*0.5f; LLVector3 vert[] = - { - center + size.scaledVec(LLVector3(1,1,1)), - center + size.scaledVec(LLVector3(-1,1,1)), - center + size.scaledVec(LLVector3(1,-1,1)), - center + size.scaledVec(LLVector3(-1,-1,1)), - center + size.scaledVec(LLVector3(1,1,-1)), - center + size.scaledVec(LLVector3(-1,1,-1)), - center + size.scaledVec(LLVector3(1,-1,-1)), - center + size.scaledVec(LLVector3(-1,-1,-1)), - }; - + { + center + size.scaledVec(LLVector3(1,1,1)), + center + size.scaledVec(LLVector3(-1,1,1)), + center + size.scaledVec(LLVector3(1,-1,1)), + center + size.scaledVec(LLVector3(-1,-1,1)), + center + size.scaledVec(LLVector3(1,1,-1)), + center + size.scaledVec(LLVector3(-1,1,-1)), + center + size.scaledVec(LLVector3(1,-1,-1)), + center + size.scaledVec(LLVector3(-1,-1,-1)), + }; + LLVOVolume* vo = (LLVOVolume*) objectp; - + for (U32 i = 0; i < 8; i++) { vect_face.push_back(vo->volumePositionToAgent(vert[i])); @@ -601,27 +603,37 @@ void LLPanelPrimMediaControls::updateShape() } vert_it = vect_face.begin(); vert_end = vect_face.end(); - - min = LLVector3(1,1,1); - max = LLVector3(-1,-1,-1); + + glh::matrix4f mat; + if (!is_hud) + { + mat = glh_get_current_projection() * glh_get_current_modelview(); + } + else { + glh::matrix4f proj, modelview; + if (get_hud_matrices(proj, modelview)) + mat = proj * modelview; + } + LLVector3 min = LLVector3(1,1,1); + LLVector3 max = LLVector3(-1,-1,-1); for(; vert_it != vert_end; ++vert_it) { // project silhouette vertices into screen space glh::vec3f screen_vert = glh::vec3f(vert_it->mV); mat.mult_matrix_vec(screen_vert); - + // add to screenspace bounding box update_min_max(min, max, LLVector3(screen_vert.v)); } - + LLCoordGL screen_min; screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (min.mV[VX] + 1.f) * 0.5f); screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (min.mV[VY] + 1.f) * 0.5f); - + LLCoordGL screen_max; screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (max.mV[VX] + 1.f) * 0.5f); screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (max.mV[VY] + 1.f) * 0.5f); - + // grow panel so that screenspace bounding box fits inside "media_region" element of HUD LLRect media_controls_rect; S32 volume_slider_height = mVolumeSliderCtrl->getRect().getHeight() - /*fudge*/ 2; @@ -632,23 +644,28 @@ void LLPanelPrimMediaControls::updateShape() media_controls_rect.mRight += getRect().getWidth() - mMediaRegion->getRect().mRight; // keep all parts of HUD on-screen - media_controls_rect.intersectWith(getParent()->getLocalRect()); + LLRect window_rect = getParent()->getLocalRect(); + media_controls_rect.intersectWith(window_rect); + + // clamp to minimum size, keeping rect inside window + S32 centerX = media_controls_rect.getCenterX(); + S32 centerY = media_controls_rect.getCenterY(); + window_rect.stretch(-mMinWidth/2, -mMinHeight/2); + window_rect.clampPointToRect(centerX, centerY); + media_controls_rect.setCenterAndSize(centerX, centerY, + llmax(mMinWidth, media_controls_rect.getWidth()), llmax(mMinHeight, media_controls_rect.getHeight())); - // clamp to minimum size, keeping centered - media_controls_rect.setCenterAndSize(media_controls_rect.getCenterX(), media_controls_rect.getCenterY(), - llmax(mMinWidth, media_controls_rect.getWidth()), llmax(mMinHeight, media_controls_rect.getHeight())); - setShape(media_controls_rect, true); - + // Test mouse position to see if the cursor is stationary LLCoordWindow cursor_pos_window; getWindow()->getCursorPosition(&cursor_pos_window); - + // If last pos is not equal to current pos, the mouse has moved // We need to reset the timer, and make sure the panel is visible if(cursor_pos_window.mX != mLastCursorPos.mX || - cursor_pos_window.mY != mLastCursorPos.mY || - mScrollState != SCROLL_NONE) + cursor_pos_window.mY != mLastCursorPos.mY || + mScrollState != SCROLL_NONE) { mInactivityTimer.start(); mLastCursorPos = cursor_pos_window; @@ -673,7 +690,7 @@ void LLPanelPrimMediaControls::updateShape() else { // I don't think this is correct anymore. This is done in draw() after the fade has completed. -// setVisible(FALSE); + // setVisible(FALSE); } } } @@ -1193,7 +1210,7 @@ void LLPanelPrimMediaControls::onCommitVolumeUp() } media_impl->setVolume(volume); - mVolumeBtn->setToggleState(false); + mMuteBtn->setToggleState(false); } } @@ -1213,7 +1230,7 @@ void LLPanelPrimMediaControls::onCommitVolumeDown() } media_impl->setVolume(volume); - mVolumeBtn->setToggleState(false); + mMuteBtn->setToggleState(false); } } @@ -1243,7 +1260,7 @@ void LLPanelPrimMediaControls::onToggleMute() } else { - media_impl->setVolume(0.5); + media_impl->setVolume(mVolumeSliderCtrl->getValueF32()); } } } diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 06163051a5..17e65b8b0c 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -153,7 +153,7 @@ private: LLUICtrl *mMediaPlaySliderPanel; LLUICtrl *mMediaPlaySliderCtrl; LLUICtrl *mVolumeCtrl; - LLButton *mVolumeBtn; + LLButton *mMuteBtn; LLUICtrl *mVolumeUpCtrl; LLUICtrl *mVolumeDownCtrl; LLSliderCtrl *mVolumeSliderCtrl; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 3274820174..c73ade53c8 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -144,6 +144,7 @@ BOOL LLPanelProfile::postBuild() void LLPanelProfile::onOpen(const LLSD& key) { + // open the desired panel if (key.has("open_tab_name")) { getTabContainer()[PANEL_PICKS]->onClosePanel(); @@ -155,6 +156,33 @@ void LLPanelProfile::onOpen(const LLSD& key) { getTabCtrl()->getCurrentPanel()->onOpen(getAvatarId()); } + + // support commands to open further pieces of UI + if (key.has("show_tab_panel")) + { + std::string panel = key["show_tab_panel"].asString(); + if (panel == "create_classified") + { + LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); + if (picks) + { + picks->createNewClassified(); + } + } + else if (panel == "classified_details") + { + LLUUID classified_id = key["classified_id"].asUUID(); + LLUUID avatar_id = key["classified_avatar_id"].asUUID(); + LLUUID snapshot_id = key["classified_snapshot_id"].asUUID(); + std::string name = key["classified_name"].asString(); + std::string desc = key["classified_desc"].asString(); + LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); + if (picks) + { + picks->openClassifiedInfo(classified_id, avatar_id, snapshot_id, name, desc); + } + } + } } //*TODO redo panel toggling diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 43f80f6d6a..596bd2909a 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -505,7 +505,7 @@ void LLTeleportHistoryPanel::refresh() tab->setVisible(true); // Expand all accordion tabs when filtering - if(!mFilterSubString.empty()) + if(!sFilterSubString.empty()) { tab->setDisplayChildren(true); } @@ -521,7 +521,7 @@ void LLTeleportHistoryPanel::refresh() if (curr_flat_view) { - LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, mFilterSubString); + LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, sFilterSubString); curr_flat_view->addItem(item); if (mLastSelectedItemIndex == mCurrentItem) @@ -569,7 +569,7 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index) LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(history_items.size(), // index will be decremented inside loop below &mContextMenu, history_items[history_items.size() - 1].mTitle, // Most recent item, it was - mFilterSubString); + sFilterSubString); // added instead of removed fv->addItem(item, LLUUID::null, ADD_TOP); diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index f646fea355..0c0f891f32 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -109,7 +109,6 @@ private: S32 mLastSelectedItemIndex; bool mDirty; S32 mCurrentItem; - std::string mFilterSubString; typedef LLDynamicArray<LLAccordionCtrlTab*> item_containers_t; item_containers_t mItemContainers; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 13f195a1be..2c5f1b094e 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -42,11 +42,50 @@ #include "llavatarlist.h" #include "llspeakers.h" #include "llviewermenu.h" +#include "llvoiceclient.h" //LLParticipantList retrieves add, clear and remove events and updates view accordingly #if LL_MSVC #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally #endif + +class ModerationResponder : public LLHTTPClient::Responder +{ +public: + ModerationResponder(const LLUUID& session_id) + { + mSessionID = session_id; + } + + virtual void error(U32 status, const std::string& reason) + { + llwarns << status << ": " << reason << llendl; + + if ( gIMMgr ) + { + //403 == you're not a mod + //should be disabled if you're not a moderator + if ( 403 == status ) + { + gIMMgr->showSessionEventError( + "mute", + "not_a_mod_error", + mSessionID); + } + else + { + gIMMgr->showSessionEventError( + "mute", + "generic_request_error", + mSessionID); + } + } + } + +private: + LLUUID mSessionID; +}; + LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/): mSpeakerMgr(data_source), mAvatarList(avatar_list), @@ -57,6 +96,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av mSpeakerRemoveListener = new SpeakerRemoveListener(*this); mSpeakerClearListener = new SpeakerClearListener(*this); mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this); + mSpeakerMuteListener = new SpeakerMuteListener(*this); mSpeakerMgr->addListener(mSpeakerAddListener, "add"); mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove"); @@ -87,6 +127,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) { const LLPointer<LLSpeaker>& speakerp = *it; + addAvatarIDExceptAgent(group_members, speakerp->mID); if ( speakerp->mIsModerator ) { @@ -103,6 +144,14 @@ LLParticipantList::~LLParticipantList() mAvatarListRefreshConnection.disconnect(); mAvatarListReturnConnection.disconnect(); + // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged() + // See ticket EXT-3427 + // hide menu before deleting it to stop enable and check handlers from triggering. + if(mParticipantListMenu) + { + mParticipantListMenu->hide(); + } + delete mParticipantListMenu; mParticipantListMenu = NULL; } @@ -184,6 +233,27 @@ void LLParticipantList::setSortOrder(EParticipantSortOrder order) } } +void LLParticipantList::refreshVoiceState() +{ + LLSpeakerMgr::speaker_list_t speakers; + mSpeakerMgr->getSpeakerList(&speakers, TRUE); + + for (LLSpeakerMgr::speaker_list_t::iterator iter = speakers.begin(); + iter != speakers.end(); ++iter) + { + LLSpeaker* speakerp = (*iter).get(); + const LLUUID& speaker_id = speakerp->mID; + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (mAvatarList->getItemByValue(speaker_id)); + if ( item ) + { + // if voice is disabled for this speaker show non voice speakers as disabled + bool is_in_voice = speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE + && speakerp->mStatus != LLSpeaker::STATUS_MUTED; + item->setOnline(!is_in_voice); + } + } +} + bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); @@ -248,6 +318,24 @@ bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> e return true; } +bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + LLPointer<LLSpeaker> speakerp = (LLSpeaker*)event->getSource(); + if (speakerp.isNull()) return false; + + // update UI on confirmation of moderator mutes + if (event->getValue().asString() == "voice") + { + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mAvatarList->getItemByValue(speakerp->mID)); + if (item) + { + LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); + indicator->setIsMuted(speakerp->mModeratorMutedVoice); + } + } + return true; +} + void LLParticipantList::sort() { if ( !mAvatarList ) @@ -264,13 +352,21 @@ void LLParticipantList::sort() } } -// static void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id) { - if (gAgent.getID() != avatar_id) - { - existing_list.push_back(avatar_id); - } + if (gAgent.getID() == avatar_id) return; + + existing_list.push_back(avatar_id); + adjustParticipant(avatar_id); +} + +void LLParticipantList::adjustParticipant(const LLUUID& speaker_id) +{ + LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id); + if (speakerp.isNull()) return; + + // add listener to process moderation changes + speakerp->addListener(mSpeakerMuteListener); } // @@ -278,6 +374,16 @@ void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_lis // bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { + /** + * We need to filter speaking objects. These objects shouldn't appear in the list + * @c LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy + */ + const LLUUID& speaker_id = event->getValue().asUUID(); + LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id); + if(speaker.isNull() || speaker->mType == LLSpeaker::SPEAKER_OBJECT) + { + return false; + } return mParent.onAddItemEvent(event, userdata); } @@ -305,6 +411,11 @@ bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LL return mParent.onModeratorUpdateEvent(event, userdata); } +bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + return mParent.onSpeakerMuteEvent(event, userdata); +} + LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() { // set up the callbacks for all of the avatar menu items @@ -314,12 +425,48 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2)); registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2)); + registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, mUUIDs.front())); + registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, mUUIDs.front())); + registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs.front())); + registrar.add("Avatar.BlockUnblock", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteVoice, this, _2)); + registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, mUUIDs.front())); + registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs.front())); + registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, mUUIDs.front())); + + registrar.add("ParticipantList.ModerateVoice", boost::bind(&LLParticipantList::LLParticipantListMenu::moderateVoice, this, _2)); + enable_registrar.add("ParticipantList.EnableItem", boost::bind(&LLParticipantList::LLParticipantListMenu::enableContextMenuItem, this, _2)); enable_registrar.add("ParticipantList.CheckItem", boost::bind(&LLParticipantList::LLParticipantListMenu::checkContextMenuItem, this, _2)); // create the context menu from the XUI - return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( + LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( "menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); + + main_menu->setItemVisible("Moderator Options", isGroupModerator()); + main_menu->arrangeAndClear(); + + return main_menu; +} + +void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y) +{ + LLPanelPeopleMenus::ContextMenu::show(spawning_view, uuids, x, y); + + if (uuids.size() == 0) return; + + const LLUUID speaker_id = mUUIDs.front(); + BOOL is_muted = isMuted(speaker_id); + + if (is_muted) + { + LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteSelected", false); + LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteOthers", false); + } + else + { + LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false); + LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false); + } } void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata) @@ -336,53 +483,16 @@ void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& u //current value represents ability to type, so invert data["params"]["mute_info"]["text"] = !mParent.mSpeakerMgr->findSpeaker(speaker_id)->mModeratorMutedText; - class MuteTextResponder : public LLHTTPClient::Responder - { - public: - MuteTextResponder(const LLUUID& session_id) - { - mSessionID = session_id; - } - - virtual void error(U32 status, const std::string& reason) - { - llwarns << status << ": " << reason << llendl; - - if ( gIMMgr ) - { - //403 == you're not a mod - //should be disabled if you're not a moderator - if ( 403 == status ) - { - gIMMgr->showSessionEventError( - "mute", - "not_a_moderator", - mSessionID); - } - else - { - gIMMgr->showSessionEventError( - "mute", - "generic", - mSessionID); - } - } - } - - private: - LLUUID mSessionID; - }; - LLHTTPClient::post( url, data, - new MuteTextResponder(mParent.mSpeakerMgr->getSessionID())); + new ModerationResponder(mParent.mSpeakerMgr->getSessionID())); } -void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata) +void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, U32 flags) { const LLUUID speaker_id = mUUIDs.front(); - BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, LLMute::flagTextChat); + BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, flags); std::string name; //fill in name using voice client's copy of name cache @@ -398,11 +508,104 @@ void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userda if (!is_muted) { - LLMuteList::getInstance()->add(mute, LLMute::flagTextChat); + LLMuteList::getInstance()->add(mute, flags); + } + else + { + LLMuteList::getInstance()->remove(mute, flags); + } +} + +void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata) +{ + toggleMute(userdata, LLMute::flagTextChat); +} + +void LLParticipantList::LLParticipantListMenu::toggleMuteVoice(const LLSD& userdata) +{ + toggleMute(userdata, LLMute::flagVoiceChat); +} + +bool LLParticipantList::LLParticipantListMenu::isGroupModerator() +{ + // Agent is in Group Call + if(gAgent.isInGroup(mParent.mSpeakerMgr->getSessionID())) + { + // Agent is Moderator + return mParent.mSpeakerMgr->findSpeaker(gAgentID)->mIsModerator; + } + return false; +} + +bool LLParticipantList::LLParticipantListMenu::isMuted(const LLUUID& avatar_id) +{ + LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(avatar_id); + if (!selected_speakerp) return true; + + return selected_speakerp->mStatus == LLSpeaker::STATUS_MUTED; +} + +void LLParticipantList::LLParticipantListMenu::moderateVoice(const LLSD& userdata) +{ + if (!gAgent.getRegion()) return; + + bool moderate_selected = userdata.asString() == "selected"; + const LLUUID& selected_avatar_id = mUUIDs.front(); + bool is_muted = isMuted(selected_avatar_id); + + if (moderate_selected) + { + moderateVoiceParticipant(selected_avatar_id, is_muted); } else { - LLMuteList::getInstance()->remove(mute, LLMute::flagTextChat); + moderateVoiceOtherParticipants(selected_avatar_id, is_muted); + } +} + +void LLParticipantList::LLParticipantListMenu::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute) +{ + if (gAgentID == avatar_id) return; // do not process myself + + LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(avatar_id); + if (!speakerp) return; + + // *NOTE: mantipov: probably this condition will be incorrect when avatar will be blocked for + // text chat via moderation (LLSpeaker::mModeratorMutedText == TRUE) + bool is_in_voice = speakerp->mStatus <= LLSpeaker::STATUS_VOICE_ACTIVE || speakerp->mStatus == LLSpeaker::STATUS_MUTED; + + // do not send voice moderation changes for avatars not in voice channel + if (!is_in_voice) return; + + std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); + LLSD data; + data["method"] = "mute update"; + data["session-id"] = mParent.mSpeakerMgr->getSessionID(); + data["params"] = LLSD::emptyMap(); + data["params"]["agent_id"] = avatar_id; + data["params"]["mute_info"] = LLSD::emptyMap(); + data["params"]["mute_info"]["voice"] = !unmute; + + LLHTTPClient::post( + url, + data, + new ModerationResponder(mParent.mSpeakerMgr->getSessionID())); +} + +void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute) +{ + LLSpeakerMgr::speaker_list_t speakers; + mParent.mSpeakerMgr->getSpeakerList(&speakers, FALSE); + + for (LLSpeakerMgr::speaker_list_t::iterator iter = speakers.begin(); + iter != speakers.end(); ++iter) + { + LLSpeaker* speakerp = (*iter).get(); + LLUUID speaker_id = speakerp->mID; + + if (excluded_avatar_id == speaker_id) continue; + + moderateVoiceParticipant(speaker_id, unmute); } } @@ -414,11 +617,37 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& return mUUIDs.front() != gAgentID; } else - if (item == "can_allow_text_chat") + if (item == "can_allow_text_chat" || "can_moderate_voice" == item) + { + return isGroupModerator(); + } + else if (item == std::string("can_add")) { - LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mParent.mSpeakerMgr->getSessionID()); - return im_session->mType == IM_SESSION_GROUP_START && mParent.mSpeakerMgr->findSpeaker(gAgentID)->mIsModerator; + // We can add friends if: + // - there are selected people + // - and there are no friends among selection yet. + + bool result = (mUUIDs.size() > 0); + + std::vector<LLUUID>::const_iterator + id = mUUIDs.begin(), + uuids_end = mUUIDs.end(); + + for (;id != uuids_end; ++id) + { + if ( LLAvatarActions::isFriend(*id) ) + { + result = false; + break; + } + } + return result; } + else if (item == "can_call") + { + return LLVoiceClient::voiceEnabled(); + } + return true; } @@ -426,17 +655,26 @@ bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD& { std::string item = userdata.asString(); const LLUUID& id = mUUIDs.front(); + if (item == "is_muted") - return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat); - else - if (item == "is_allowed_text_chat") - { - LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id); + { + return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat); + } + else if (item == "is_allowed_text_chat") + { + LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id); - if (selected_speakerp.notNull()) - { - return !selected_speakerp->mModeratorMutedText; - } + if (selected_speakerp.notNull()) + { + return !selected_speakerp->mModeratorMutedText; } + } + else if(item == "is_blocked") + { + return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); + } + return false; } + +//EOF diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 86b38f5f1e..bc6c6c2b50 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -52,10 +52,16 @@ class LLParticipantList } EParticipantSortOrder; /** - * Set and sort Avatarlist by given order - */ + * Set and sort Avatarlist by given order + */ void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); + /** + * Refreshes participants to display ones not in voice as disabled. + * TODO: mantipov: probably should be moved into derived class for LLFloaterCall + */ + void refreshVoiceState(); + protected: /** * LLSpeakerMgr event handlers @@ -64,6 +70,7 @@ class LLParticipantList bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); /** * Sorts the Avatarlist by stored order @@ -109,6 +116,14 @@ class LLParticipantList /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); }; + class SpeakerMuteListener : public BaseSpeakerListner + { + public: + SpeakerMuteListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} + + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; + /** * Menu used in the participant list. */ @@ -117,6 +132,7 @@ class LLParticipantList public: LLParticipantListMenu(LLParticipantList& parent):mParent(parent){}; /*virtual*/ LLContextMenu* createMenu(); + /*virtual*/ void show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y); protected: LLParticipantList& mParent; private: @@ -124,8 +140,59 @@ class LLParticipantList bool checkContextMenuItem(const LLSD& userdata); void toggleAllowTextChat(const LLSD& userdata); + void toggleMute(const LLSD& userdata, U32 flags); void toggleMuteText(const LLSD& userdata); + void toggleMuteVoice(const LLSD& userdata); + /** + * Return true if Agent is group moderator(and moderator of group call). + */ + bool isGroupModerator(); + + // Voice moderation support + /** + * Check whether specified by argument avatar is muted for group chat or not. + */ + bool isMuted(const LLUUID& avatar_id); + + /** + * Processes Voice moderation menu items. + * + * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on + * passed parameter. + * + * @param userdata can be "selected" or "others". + * + * @see moderateVoiceParticipant() + * @see moderateVoiceOtherParticipants() + */ + void moderateVoice(const LLSD& userdata); + + /** + * Mutes/Unmutes avatar for current group voice chat. + * + * It only marks avatar as muted for session and does not use local Agent's Block list. + * It does not mute Agent itself. + * + * @param[in] avatar_id UUID of avatar to be processed + * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted. + * + * @see moderateVoiceOtherParticipants() + */ + void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); + + /** + * Mutes/Unmutes all avatars except specified for current group voice chat. + * + * It only marks avatars as muted for session and does not use local Agent's Block list. + * It based call moderateVoiceParticipant() for each avatar should be muted/unmuted. + * + * @param[in] excluded_avatar_id UUID of avatar NOT to be processed + * @param[in] unmute if true - avatars will be muted, otherwise - unmuted. + * + * @see moderateVoiceParticipant() + */ + void moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute); }; private: @@ -134,8 +201,18 @@ class LLParticipantList /** * Adds specified avatar ID to the existing list if it is not Agent's ID + * + * @param[in, out] existing_list - vector with avatars' UUIDs already in the list + * @param[in] avatar_id - Avatar UUID to be added into the list + */ + void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id); + + /** + * Adjusts passed participant to work properly. + * + * Adds SpeakerMuteListener to process moderation actions. */ - static void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id); + void adjustParticipant(const LLUUID& speaker_id); LLSpeakerMgr* mSpeakerMgr; LLAvatarList* mAvatarList; @@ -147,6 +224,7 @@ class LLParticipantList LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener; LLPointer<SpeakerClearListener> mSpeakerClearListener; LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; + LLPointer<SpeakerMuteListener> mSpeakerMuteListener; LLParticipantListMenu* mParticipantListMenu; diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 30cb21c83c..f1891aa421 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -59,7 +59,6 @@ #include "llinventorymodel.h" #include "llkeyboard.h" #include "lllineeditor.h" -#include "llnotify.h" #include "llradiogroup.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index 9d26539453..19fa1dcc37 100644 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -33,8 +33,9 @@ #ifndef LL_LLPREVIEWGESTURE_H #define LL_LLPREVIEWGESTURE_H -#include "llpreview.h" +#include "llassettype.h" #include "llmultigesture.h" +#include "llpreview.h" class LLMultiGesture; class LLLineEditor; @@ -46,6 +47,7 @@ class LLScrollListItem; class LLButton; class LLGestureStep; class LLRadioGroup; +class LLVFS; class LLPreviewGesture : public LLPreview { diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 5d675fcda6..95756ac5f3 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -44,7 +44,6 @@ #include "llinventorymodel.h" #include "lllineeditor.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llresmgr.h" #include "roles_constants.h" #include "llscrollbar.h" diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 0362fdbf56..646c9fb6a4 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -54,13 +54,13 @@ #include "llscrolllistcell.h" #include "llslider.h" #include "lscript_rt_interface.h" +#include "lscript_library.h" #include "lscript_export.h" #include "lltextbox.h" #include "lltooldraganddrop.h" #include "llvfile.h" #include "llagent.h" -#include "llnotify.h" #include "llmenugl.h" #include "roles_constants.h" #include "llselectmgr.h" diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 28a409d3ee..9d194c5557 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -51,6 +51,7 @@ struct LLEntryAndEdCore; class LLMenuBarGL; class LLFloaterScriptSearch; class LLKeywordToken; +class LLVFS; class LLViewerInventoryItem; // Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these. diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 698f6152b4..26694ac433 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -76,29 +76,12 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key) mAspectRatio(0.f), mPreviewToSave(FALSE) { - const LLInventoryItem *item = getItem(); + const LLViewerInventoryItem *item = static_cast<const LLViewerInventoryItem*>(getItem()); if(item) { mShowKeepDiscard = item->getPermissions().getCreator() != gAgent.getID(); mImageID = item->getAssetUUID(); - const LLPermissions& perm = item->getPermissions(); - U32 mask = PERM_NONE; - if(perm.getOwner() == gAgent.getID()) - { - mask = perm.getMaskBase(); - } - else if(gAgent.isInGroup(perm.getGroup())) - { - mask = perm.getMaskGroup(); - } - else - { - mask = perm.getMaskEveryone(); - } - if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - { - mIsCopyable = TRUE; - } + mIsCopyable = item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); } else // not an item, assume it's an asset id { @@ -145,6 +128,9 @@ BOOL LLPreviewTexture::postBuild() childSetVisible("Discard", false); } + childSetAction("save_tex_btn", LLPreviewTexture::onSaveAsBtn, this); + childSetVisible("save_tex_btn", canSaveAs()); + if (!mCopyToInv) { const LLInventoryItem* item = getItem(); @@ -164,6 +150,13 @@ BOOL LLPreviewTexture::postBuild() return LLPreview::postBuild(); } +// static +void LLPreviewTexture::onSaveAsBtn(void* data) +{ + LLPreviewTexture* self = (LLPreviewTexture*)data; + self->saveAs(); +} + void LLPreviewTexture::draw() { if (mUpdateDimensions) @@ -576,6 +569,7 @@ void LLPreviewTexture::loadAsset() mImage->forceToSaveRawImage(0) ; mAssetStatus = PREVIEW_ASSET_LOADING; updateDimensions(); + childSetVisible("save_tex_btn", canSaveAs()); } LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus() diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index 9b3c91d831..980aecee6d 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -58,7 +58,6 @@ public: virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual void onFocusReceived(); - static void saveToFile(void* userdata); static void onFileLoadedForSave( BOOL success, LLViewerFetchedTexture *src_vi, @@ -68,6 +67,8 @@ public: BOOL final, void* userdata ); void openToSave(); + + static void onSaveAsBtn(void* data); protected: void init(); /* virtual */ BOOL postBuild(); diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h index 3a16e25ef6..c04f6b1858 100644 --- a/indra/newview/llremoteparcelrequest.h +++ b/indra/newview/llremoteparcelrequest.h @@ -38,6 +38,7 @@ #include "llhttpclient.h" #include "llpanel.h" +class LLMessageSystem; class LLRemoteParcelInfoObserver; class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 4f0c873c61..bd256ec9c2 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -78,6 +78,22 @@ LLScreenChannelBase::~LLScreenChannelBase() { mWorldViewRectConnection.disconnect(); } + +bool LLScreenChannelBase::isHovering() +{ + bool res = mHoveredToast != NULL; + if (!res) + { + return res; + } + + S32 x, y; + mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(), + gViewerWindow->getCurrentMouseY(), &x, &y); + res = mHoveredToast->pointInView(x, y) == TRUE; + return res; +} + void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) { S32 top_delta = old_world_rect.mTop - new_world_rect.mTop; @@ -125,6 +141,8 @@ LLScreenChannelBase(id) void LLScreenChannel::init(S32 channel_left, S32 channel_right) { LLScreenChannelBase::init(channel_left, channel_right); + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); + updatePositionAndSize(world_rect, world_rect); } //-------------------------------------------------------------------------- @@ -133,10 +151,54 @@ LLScreenChannel::~LLScreenChannel() } +std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) +{ + std::list<LLToast*> res; + + // collect stored toasts + for (std::vector<ToastElem>::iterator it = mStoredToastList.begin(); it + != mStoredToastList.end(); it++) + { + if (matcher.matches(it->toast->getNotification())) + { + res.push_back(it->toast); + } + } + + // collect displayed toasts + for (std::vector<ToastElem>::iterator it = mToastList.begin(); it + != mToastList.end(); it++) + { + if (matcher.matches(it->toast->getNotification())) + { + res.push_back(it->toast); + } + } + + return res; +} + //-------------------------------------------------------------------------- void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) { - LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect); + S32 right_delta = old_world_rect.mRight - new_world_rect.mRight; + LLRect this_rect = getRect(); + + switch(mChannelAlignment) + { + case CA_LEFT : + this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio()); + break; + case CA_CENTRE : + LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect); + return; + case CA_RIGHT : + this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio()); + this_rect.mLeft -= right_delta; + this_rect.mRight -= right_delta; + } + setRect(this_rect); + redrawToasts(); } //-------------------------------------------------------------------------- @@ -169,6 +231,7 @@ void LLScreenChannel::addToast(const LLToast::Params& p) if(show_toast) { mToastList.push_back(new_toast_elem); + updateShowToastsState(); redrawToasts(); } else // store_toast @@ -224,6 +287,7 @@ void LLScreenChannel::deleteToast(LLToast* toast) if(mHoveredToast == toast) { mHoveredToast = NULL; + startFadingToasts(); } // close the toast @@ -339,6 +403,16 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) } } +void LLScreenChannel::killMatchedToasts(const Matcher& matcher) +{ + std::list<LLToast*> to_delete = findToasts(matcher); + for (std::list<LLToast*>::iterator it = to_delete.begin(); it + != to_delete.end(); it++) + { + killToastByNotificationID((*it)-> getNotificationID()); + } +} + //-------------------------------------------------------------------------- void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel) { @@ -405,26 +479,27 @@ void LLScreenChannel::showToastsBottom() { if( it != mToastList.rend()-1) { - stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastGap")) > getRect().mTop; + S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap"); + stop_showing_toasts = toast_top > getRect().mTop; } } + // at least one toast should be visible + if(it == mToastList.rbegin()) + { + stop_showing_toasts = false; + } + if(stop_showing_toasts) break; if( !(*it).toast->getVisible() ) { - if((*it).toast->isFirstLook()) - { - (*it).toast->setVisible(TRUE); - } - else - { - // HACK - // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts - (*it).toast->setVisible(TRUE); - gFloaterView->sendChildToBack((*it).toast); - } + // HACK + // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts + (*it).toast->setVisible(TRUE); + // Show toast behind floaters. (EXT-3089) + gFloaterView->sendChildToBack((*it).toast); } } @@ -566,6 +641,21 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer) mStartUpToastPanel->setVisible(TRUE); } +// static -------------------------------------------------------------------------- +F32 LLScreenChannel::getHeightRatio() +{ + F32 ratio = gSavedSettings.getF32("NotificationChannelHeightRatio"); + if(0.0f > ratio) + { + ratio = 0.0f; + } + else if(1.0f < ratio) + { + ratio = 1.0f; + } + return ratio; +} + //-------------------------------------------------------------------------- void LLScreenChannel::updateStartUpString(S32 num) { @@ -608,7 +698,7 @@ void LLNotificationsUI::LLScreenChannel::startFadingToasts() if (!mToastList.size()) return; //because onMouseLeave is processed after onMouseEnter - if (mHoveredToast) return; + if (isHovering()) return; std::vector<ToastElem>::iterator it = mToastList.begin(); while (it != mToastList.end()) @@ -685,39 +775,28 @@ void LLScreenChannel::removeToastsBySessionID(LLUUID id) //-------------------------------------------------------------------------- void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter) { - // because of LLViewerWindow::updateUI() that ALWAYS calls onMouseEnter BEFORE onMouseLeave - // we must check this to prevent incorrect setting for hovering in a channel - std::map<LLToast*, bool>::iterator it_first, it_second; - S32 stack_size = mToastEventStack.size(); - if(mouse_enter) + // because of LLViewerWindow::updateUI() that NOT ALWAYS calls onMouseEnter BEFORE onMouseLeave + // we must check hovering directly to prevent incorrect setting for hovering in a channel + S32 x,y; + if (mouse_enter) { - mHoveredToast = toast; - } - else - { - mHoveredToast = NULL; - } - - switch(stack_size) - { - case 0: - mToastEventStack.insert(std::pair<LLToast*, bool>(toast, mouse_enter)); - break; - case 1: - it_first = mToastEventStack.begin(); - if((*it_first).second && !mouse_enter && ((*it_first).first != toast) ) + toast->screenPointToLocal(gViewerWindow->getCurrentMouseX(), + gViewerWindow->getCurrentMouseY(), &x, &y); + bool hover = toast->pointInView(x, y) == TRUE; + if (hover) { - mToastEventStack.clear(); mHoveredToast = toast; } - else + } + else if (mHoveredToast != NULL) + { + mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(), + gViewerWindow->getCurrentMouseY(), &x, &y); + bool hover = mHoveredToast->pointInView(x, y) == TRUE; + if (!hover) { - mToastEventStack.clear(); - mToastEventStack.insert(std::pair<LLToast*, bool>(toast, mouse_enter)); + mHoveredToast = NULL; } - break; - default: - LL_ERRS ("LLScreenChannel::onToastHover: stack size error " ) << stack_size << llendl; } if(!isHovering()) @@ -727,7 +806,7 @@ void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter) //-------------------------------------------------------------------------- void LLScreenChannel::updateShowToastsState() { - LLFloater* floater = LLDockableFloater::getInstanceHandle().get(); + LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); if(!floater) { @@ -735,27 +814,19 @@ void LLScreenChannel::updateShowToastsState() return; } - // for IM floaters showed in a docked state - prohibit showing of ani toast - if(dynamic_cast<LLIMFloater*>(floater) - || dynamic_cast<LLScriptFloater*>(floater) ) - { - setShowToasts(!(floater->getVisible() && floater->isDocked())); - if (!getShowToasts()) - { - removeAndStoreAllStorableToasts(); - } - } - - // *TODO: mantipov: what we have to do with derived classes: LLNotificationWellWindow & LLIMWelWindow? - // See EXT-3081 for details // for Message Well floater showed in a docked state - adjust channel's height - if(dynamic_cast<LLSysWellWindow*>(floater)) + if(dynamic_cast<LLSysWellWindow*>(floater) || dynamic_cast<LLIMFloater*>(floater) + || dynamic_cast<LLScriptFloater*>(floater)) { S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");; LLRect this_rect = getRect(); if(floater->getVisible() && floater->isDocked()) { - channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastGap")); + channel_bottom += floater->getRect().getHeight(); + if(floater->getDockControl()) + { + channel_bottom += floater->getDockControl()->getTongueHeight(); + } } if(channel_bottom != this_rect.mBottom) diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 67f1c9bdc6..321fb244a1 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -95,7 +95,7 @@ public: virtual void setControlHovering(bool control) { mControlHovering = control; } - bool isHovering() { return mHoveredToast != NULL; } + bool isHovering(); void setCanStoreToasts(bool store) { mCanStoreToasts = store; } @@ -151,6 +151,16 @@ public: LLScreenChannel(LLUUID& id); virtual ~LLScreenChannel(); + class Matcher + { + public: + Matcher(){} + virtual ~Matcher() {} + virtual bool matches(const LLNotificationPtr) const = 0; + }; + + std::list<LLToast*> findToasts(const Matcher& matcher); + // Channel's outfit-functions // update channel's size and position in the World View void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect); @@ -162,6 +172,7 @@ public: void addToast(const LLToast::Params& p); // kill or modify a toast by its ID void killToastByNotificationID(LLUUID id); + void killMatchedToasts(const Matcher& matcher); void modifyToastByNotificationID(LLUUID id, LLPanel* panel); // hide all toasts from screen, but not remove them from a channel void hideToastsFromScreen(); @@ -265,6 +276,11 @@ private: // create the StartUp Toast void createStartUpToast(S32 notif_num, F32 timer); + /** + * Notification channel and World View ratio(0.0 - always show 1 notification, 1.0 - max ratio). + */ + static F32 getHeightRatio(); + // Channel's flags static bool mWasStartUpToastShown; @@ -274,7 +290,6 @@ private: std::vector<ToastElem> mToastList; std::vector<ToastElem> mStoredToastList; - std::map<LLToast*, bool> mToastEventStack; }; } diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 8de99a48aa..1962d871a6 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -39,6 +39,7 @@ #include "llfloaterreg.h" #include "llnotifications.h" #include "llscreenchannel.h" +#include "llsyswellwindow.h" #include "lltoastnotifypanel.h" #include "llviewerwindow.h" #include "llimfloater.h" @@ -65,6 +66,7 @@ LLScriptFloater::LLScriptFloater(const LLSD& key) : LLDockableFloater(NULL, true, key) , mScriptForm(NULL) { + setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this)); } bool LLScriptFloater::toggle(const LLUUID& object_id) @@ -179,6 +181,23 @@ void LLScriptFloater::setVisible(BOOL visible) hideToastsIfNeeded(); } +void LLScriptFloater::onMouseDown() +{ + if(getObjectId().notNull()) + { + // Remove new message icon + LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getObjectId()); + if (chiclet == NULL) + { + llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); + } + else + { + chiclet->setShowNewMessagesIcon(false); + } + } +} + void LLScriptFloater::hideToastsIfNeeded() { using namespace LLNotificationsUI; @@ -190,6 +209,7 @@ void LLScriptFloater::hideToastsIfNeeded() if(channel) { channel->updateShowToastsState(); + channel->redrawToasts(); } } @@ -216,11 +236,18 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) script_notification_map_t::iterator it = mNotifications.find(object_id); if(it != mNotifications.end()) { + LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(object_id); + if(chiclet) + { + // Pass the new_message icon state further. + set_new_message = chiclet->getShowNewMessagesIcon(); + } + LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->second.notification_id); if(floater) { - // Generate chiclet with a "new message" indicator if a docked window was opened. See EXT-3142. - set_new_message = floater->isShown(); + // Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142. + set_new_message |= !floater->hasFocus(); } onRemoveNotification(it->second.notification_id); @@ -240,6 +267,14 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) LLBottomTray::getInstance()->getChicletPanel()->createChiclet<LLScriptChiclet>(object_id); } + LLIMWellWindow::getInstance()->addObjectRow(object_id, set_new_message); + + LLSD data; + data["object_id"] = object_id; + data["new_message"] = set_new_message; + data["unread"] = 1; // each object has got only one floater + mNewObjectSignal(data); + toggleScriptFloater(object_id, set_new_message); } @@ -267,6 +302,8 @@ void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) // remove related chiclet LLBottomTray::getInstance()->getChicletPanel()->removeChiclet(object_id); + LLIMWellWindow::getInstance()->removeObjectRow(object_id); + // close floater LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", notification_id); if(floater) @@ -291,13 +328,6 @@ void LLScriptFloaterManager::removeNotificationByObjectId(const LLUUID& object_i void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id, bool set_new_message) { - // hide "new message" icon from chiclet - LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(object_id); - if(chiclet) - { - chiclet->setShowNewMessagesIcon(set_new_message); - } - // kill toast using namespace LLNotificationsUI; LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->findChannelByID( @@ -307,6 +337,11 @@ void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id, bool s channel->killToastByNotificationID(findNotificationToastId(object_id)); } + LLSD data; + data["object_id"] = object_id; + data["new_message"] = set_new_message; + mToggleFloaterSignal(data); + // toggle floater LLScriptFloater::toggle(object_id); } diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h index 8de7a28d0f..ed10dc5fe9 100644 --- a/indra/newview/llscriptfloater.h +++ b/indra/newview/llscriptfloater.h @@ -88,6 +88,11 @@ public: */ static void onToastButtonClick(const LLSD¬ification, const LLSD&response); + typedef boost::signals2::signal<void(const LLSD&)> object_signal_t; + + boost::signals2::connection addNewObjectCallback(const object_signal_t::slot_type& cb) { return mNewObjectSignal.connect(cb); } + boost::signals2::connection addToggleObjectFloaterCallback(const object_signal_t::slot_type& cb) { return mToggleFloaterSignal.connect(cb); } + private: struct LLNotificationData @@ -100,6 +105,9 @@ private: typedef std::map<LLUUID, LLNotificationData> script_notification_map_t; script_notification_map_t mNotifications; + + object_signal_t mNewObjectSignal; + object_signal_t mToggleFloaterSignal; }; /** @@ -161,6 +169,11 @@ protected: */ static void hideToastsIfNeeded(); + /** + * Removes chiclets new messages icon + */ + void onMouseDown(); + private: LLToastNotifyPanel* mScriptForm; LLUUID mObjectId; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 4d6c19157a..6e99d5a5f0 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -3494,7 +3494,7 @@ void LLSelectMgr::deselectAllIfTooFar() // HACK: Don't deselect when we're navigating to rate an object's // owner or creator. JC - if (gPieObject->getVisible() || gPieRate->getVisible() ) + if (gMenuObject->getVisible()) { return; } @@ -5493,11 +5493,15 @@ void dialog_refresh_all() gFloaterTools->dirty(); - gPieObject->needsArrange(); + gMenuObject->needsArrange(); - if( gPieAttachment->getVisible() ) + if( gMenuAttachmentSelf->getVisible() ) { - gPieAttachment->arrange(); + gMenuAttachmentSelf->arrange(); + } + if( gMenuAttachmentOther->getVisible() ) + { + gMenuAttachmentOther->arrange(); } LLFloaterProperties::dirtyAll(); @@ -5754,21 +5758,21 @@ void LLSelectMgr::redo() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canDoDelete() const { - bool can_delete = false;
- // This function is "logically const" - it does not change state in
- // a way visible outside the selection manager.
- LLSelectMgr* self = const_cast<LLSelectMgr*>(this);
- LLViewerObject* obj = self->mSelectedObjects->getFirstDeleteableObject();
- // Note: Can only delete root objects (see getFirstDeleteableObject() for more info)
- if (obj!= NULL)
- {
- // all the faces needs to be selected
- if(self->mSelectedObjects->contains(obj,SELECT_ALL_TES ))
- {
- can_delete = true;
- }
- }
-
+ bool can_delete = false; + // This function is "logically const" - it does not change state in + // a way visible outside the selection manager. + LLSelectMgr* self = const_cast<LLSelectMgr*>(this); + LLViewerObject* obj = self->mSelectedObjects->getFirstDeleteableObject(); + // Note: Can only delete root objects (see getFirstDeleteableObject() for more info) + if (obj!= NULL) + { + // all the faces needs to be selected + if(self->mSelectedObjects->contains(obj,SELECT_ALL_TES )) + { + can_delete = true; + } + } + return can_delete; } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index eb3695a371..30b0075c4b 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -113,9 +113,6 @@ BOOL LLSidepanelAppearance::postBuild() mEditAppearanceBtn = getChild<LLButton>("editappearance_btn"); mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this)); - mWearBtn = getChild<LLButton>("wear_btn"); - mWearBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onWearButtonClicked, this)); - mEditBtn = getChild<LLButton>("edit_btn"); mEditBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditButtonClicked, this)); @@ -199,14 +196,6 @@ void LLSidepanelAppearance::onFilterEdit(const std::string& search_string) } } -void LLSidepanelAppearance::onWearButtonClicked() -{ - if (!mLookInfo->getVisible()) - { - mPanelOutfitsInventory->onWear(); - } -} - void LLSidepanelAppearance::onOpenOutfitButtonClicked() { const LLViewerInventoryItem *outfit_link = LLAppearanceManager::getInstance()->getCurrentOutfitLink(); @@ -284,7 +273,6 @@ void LLSidepanelAppearance::toggleLookInfoPanel(BOOL visible) mLookInfo->setVisible(visible); mPanelOutfitsInventory->setVisible(!visible); mFilterEditor->setVisible(!visible); - mWearBtn->setVisible(!visible); mEditBtn->setVisible(!visible); mNewOutfitBtn->setVisible(!visible); mCurrOutfitPanel->setVisible(!visible); @@ -314,12 +302,10 @@ void LLSidepanelAppearance::updateVerbs() { const bool is_correct_type = (mPanelOutfitsInventory->getCorrectListenerForAction() != NULL); mEditBtn->setEnabled(is_correct_type); - mWearBtn->setEnabled(is_correct_type); } else { mEditBtn->setEnabled(FALSE); - mWearBtn->setEnabled(FALSE); } } diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 9c870f631a..8ef2088eda 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -67,7 +67,6 @@ private: void onOpenOutfitButtonClicked(); void onEditAppearanceButtonClicked(); - void onWearButtonClicked(); void onEditButtonClicked(); void onNewOutfitButtonClicked(); void onBackButtonClicked(); @@ -82,7 +81,6 @@ private: LLButton* mOpenOutfitBtn; LLButton* mEditAppearanceBtn; - LLButton* mWearBtn; LLButton* mEditBtn; LLButton* mNewOutfitBtn; LLPanel* mCurrOutfitPanel; diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index ca7a3b663a..5383158cd3 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -235,8 +235,10 @@ void LLSidepanelInventory::updateVerbs() if (!item) return; - mInfoBtn->setEnabled(TRUE); - mShareBtn->setEnabled(TRUE); + bool is_single_selection = getSelectedCount() == 1; + + mInfoBtn->setEnabled(is_single_selection); + mShareBtn->setEnabled(is_single_selection); switch(item->getInventoryType()) { @@ -274,6 +276,14 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem() return item; } +U32 LLSidepanelInventory::getSelectedCount() +{ + LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory"); + std::set<LLUUID> selection_list; + panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList(selection_list); + return selection_list.size(); +} + LLInventoryPanel *LLSidepanelInventory::getActivePanel() { if (!getVisible()) diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index 231cdac9e1..ee11fb6b54 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -56,6 +56,7 @@ public: protected: // Tracks highlighted (selected) item in inventory panel. LLInventoryItem *getSelectedItem(); + U32 getSelectedCount(); void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); // "wear", "teleport", etc. void performActionOnSelection(const std::string &action); diff --git a/indra/newview/llsidepanelinventorysubpanel.cpp b/indra/newview/llsidepanelinventorysubpanel.cpp index 23931defdd..56e342c3ce 100644 --- a/indra/newview/llsidepanelinventorysubpanel.cpp +++ b/indra/newview/llsidepanelinventorysubpanel.cpp @@ -57,7 +57,6 @@ LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel() : LLPanel(), mIsDirty(TRUE), mIsEditing(FALSE), - mEditBtn(NULL), mCancelBtn(NULL), mSaveBtn(NULL) { @@ -71,9 +70,6 @@ LLSidepanelInventorySubpanel::~LLSidepanelInventorySubpanel() // virtual BOOL LLSidepanelInventorySubpanel::postBuild() { - mEditBtn = getChild<LLButton>("edit_btn"); - mEditBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onEditButtonClicked, this)); - mSaveBtn = getChild<LLButton>("save_btn"); mSaveBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onSaveButtonClicked, this)); @@ -99,7 +95,9 @@ void LLSidepanelInventorySubpanel::setIsEditing(BOOL edit) BOOL LLSidepanelInventorySubpanel::getIsEditing() const { - return mIsEditing; + + return TRUE; // Default everything to edit mode since we're not using an edit button anymore. + // return mIsEditing; } void LLSidepanelInventorySubpanel::reset() @@ -111,9 +109,9 @@ void LLSidepanelInventorySubpanel::draw() { if (mIsDirty) { - mIsDirty = FALSE; refresh(); updateVerbs(); + mIsDirty = FALSE; } LLPanel::draw(); @@ -127,7 +125,6 @@ void LLSidepanelInventorySubpanel::dirty() void LLSidepanelInventorySubpanel::updateVerbs() { - mEditBtn->setVisible(!mIsEditing); mSaveBtn->setVisible(mIsEditing); mCancelBtn->setVisible(mIsEditing); } diff --git a/indra/newview/llsidepanelinventorysubpanel.h b/indra/newview/llsidepanelinventorysubpanel.h index a74f4fdee6..b7bee6809f 100644 --- a/indra/newview/llsidepanelinventorysubpanel.h +++ b/indra/newview/llsidepanelinventorysubpanel.h @@ -70,7 +70,6 @@ protected: void onEditButtonClicked(); void onSaveButtonClicked(); void onCancelButtonClicked(); - LLButton* mEditBtn; LLButton* mSaveBtn; LLButton* mCancelBtn; diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index ad6428e515..1965e634b6 100644 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -109,19 +109,30 @@ BOOL LLSidepanelItemInfo::postBuild() { LLSidepanelInventorySubpanel::postBuild(); - // build the UI - // item name & description childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidateASCIIPrintableNoPipe); - //getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this)); + getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this)); childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidateASCIIPrintableNoPipe); - //getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this)); - + getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this)); // Creator information getChild<LLUICtrl>("BtnCreator")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickCreator,this)); - // owner information getChild<LLUICtrl>("BtnOwner")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickOwner,this)); - + // acquired date + // owner permissions + // Permissions debug text + // group permissions + getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this)); + // everyone permissions + getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this)); + // next owner permissions + getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this)); + getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this)); + getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this)); + // Mark for sale or not, and sale info + getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this)); + getChild<LLUICtrl>("RadioSaleType")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleType, this)); + // "Price" label for edit + getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this)); refresh(); return TRUE; } @@ -159,10 +170,9 @@ void LLSidepanelItemInfo::refresh() setIsEditing(FALSE); return; } - mEditBtn->setEnabled(FALSE); } - if (!getIsEditing()) + if (!getIsEditing() || !item) { const std::string no_item_names[]={ "LabelItemName", @@ -859,25 +869,6 @@ LLInventoryItem* LLSidepanelItemInfo::findItem() const } // virtual -void LLSidepanelItemInfo::updateVerbs() -{ - LLSidepanelInventorySubpanel::updateVerbs(); - - const LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem(); - if (item) - { - const LLPermissions& perm = item->getPermissions(); - BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm, - GP_OBJECT_MANIPULATE); - - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - bool item_in_trash = item->getUUID() == trash_id || gInventory.isObjectDescendentOf(item->getUUID(), trash_id); - mEditBtn->setEnabled(is_modifiable && !item_in_trash); - - } -} - -// virtual void LLSidepanelItemInfo::save() { onCommitName(); diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h index 4bfbd56ea7..21002327bc 100644 --- a/indra/newview/llsidepaneliteminfo.h +++ b/indra/newview/llsidepaneliteminfo.h @@ -62,7 +62,6 @@ public: protected: /*virtual*/ void refresh(); /*virtual*/ void save(); - /*virtual*/ void updateVerbs(); LLInventoryItem* findItem() const; LLViewerObject* findObject() const; diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 464546cc77..50cec3184d 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -101,13 +101,25 @@ BOOL LLSidepanelTaskInfo::postBuild() mBuyBtn = getChild<LLButton>("buy_btn"); mBuyBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onBuyButtonClicked, this)); - childSetPrevalidate("Object Name",LLLineEditor::prevalidateASCIIPrintableNoPipe); - childSetPrevalidate("Object Description",LLLineEditor::prevalidateASCIIPrintableNoPipe); - mLabelGroupName = getChild<LLNameBox>("Group Name Proxy"); - childSetCommitCallback("checkbox for sale",onClickForSale,this); - + childSetCommitCallback("Object Name", LLSidepanelTaskInfo::onCommitName,this); + childSetPrevalidate("Object Name", LLLineEditor::prevalidateASCIIPrintableNoPipe); + childSetCommitCallback("Object Description", LLSidepanelTaskInfo::onCommitDesc,this); + childSetPrevalidate("Object Description", LLLineEditor::prevalidateASCIIPrintableNoPipe); + getChild<LLUICtrl>("button set group")->setCommitCallback(boost::bind(&LLSidepanelTaskInfo::onClickGroup,this)); + childSetCommitCallback("checkbox share with group", &LLSidepanelTaskInfo::onCommitGroupShare,this); + childSetAction("button deed", &LLSidepanelTaskInfo::onClickDeedToGroup,this); + childSetCommitCallback("checkbox allow everyone move", &LLSidepanelTaskInfo::onCommitEveryoneMove,this); + childSetCommitCallback("checkbox allow everyone copy", &LLSidepanelTaskInfo::onCommitEveryoneCopy,this); + childSetCommitCallback("checkbox for sale", &LLSidepanelTaskInfo::onCommitSaleInfo,this); + childSetCommitCallback("sale type", &LLSidepanelTaskInfo::onCommitSaleType,this); + childSetCommitCallback("Edit Cost", &LLSidepanelTaskInfo::onCommitSaleInfo, this); + childSetCommitCallback("checkbox next owner can modify", &LLSidepanelTaskInfo::onCommitNextOwnerModify,this); + childSetCommitCallback("checkbox next owner can copy", &LLSidepanelTaskInfo::onCommitNextOwnerCopy,this); + childSetCommitCallback("checkbox next owner can transfer", &LLSidepanelTaskInfo::onCommitNextOwnerTransfer,this); + childSetCommitCallback("clickaction", &LLSidepanelTaskInfo::onCommitClickAction,this); + childSetCommitCallback("search_check", &LLSidepanelTaskInfo::onCommitIncludeInSearch,this); return TRUE; } @@ -860,7 +872,7 @@ static bool callback_deed_to_group(const LLSD& notification, const LLSD& respons return FALSE; } -void LLSidepanelTaskInfo::onClickDeedToGroup() +void LLSidepanelTaskInfo::onClickDeedToGroup(void *data) { LLNotificationsUtil::add("DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group); } @@ -869,121 +881,149 @@ void LLSidepanelTaskInfo::onClickDeedToGroup() /// Permissions checkboxes ///---------------------------------------------------------------------------- -void LLSidepanelTaskInfo::onCommitPerm(LLCheckBoxCtrl *ctrl, U8 field, U32 perm) +// static +void LLSidepanelTaskInfo::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm) { - const LLViewerObject* object = mObjectSelection->getFirstRootObject(); - if (!object) return; + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); + if(!object) return; - BOOL new_state = ctrl->get(); + // Checkbox will have toggled itself + // LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data; + LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; + BOOL new_state = check->get(); + LLSelectMgr::getInstance()->selectionSetObjectPermissions(field, new_state, perm); } -void LLSidepanelTaskInfo::onCommitGroupShare() +// static +void LLSidepanelTaskInfo::onCommitGroupShare(LLUICtrl *ctrl, void *data) { - LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox share with group"); - onCommitPerm(ctrl, PERM_GROUP, PERM_MODIFY | PERM_MOVE | PERM_COPY); + onCommitPerm(ctrl, data, PERM_GROUP, PERM_MODIFY | PERM_MOVE | PERM_COPY); } -void LLSidepanelTaskInfo::onCommitEveryoneMove() +// static +void LLSidepanelTaskInfo::onCommitEveryoneMove(LLUICtrl *ctrl, void *data) { - LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox allow everyone move"); - onCommitPerm(ctrl, PERM_EVERYONE, PERM_MOVE); + onCommitPerm(ctrl, data, PERM_EVERYONE, PERM_MOVE); } -void LLSidepanelTaskInfo::onCommitEveryoneCopy() +// static +void LLSidepanelTaskInfo::onCommitEveryoneCopy(LLUICtrl *ctrl, void *data) { - LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox allow everyone copy"); - onCommitPerm(ctrl, PERM_EVERYONE, PERM_COPY); + onCommitPerm(ctrl, data, PERM_EVERYONE, PERM_COPY); } -void LLSidepanelTaskInfo::onCommitNextOwnerModify() +// static +void LLSidepanelTaskInfo::onCommitNextOwnerModify(LLUICtrl* ctrl, void* data) { - LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can modify"); - onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_MODIFY); + //llinfos << "LLSidepanelTaskInfo::onCommitNextOwnerModify" << llendl; + onCommitPerm(ctrl, data, PERM_NEXT_OWNER, PERM_MODIFY); } -void LLSidepanelTaskInfo::onCommitNextOwnerCopy() +// static +void LLSidepanelTaskInfo::onCommitNextOwnerCopy(LLUICtrl* ctrl, void* data) { - LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can copy"); - onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_COPY); + //llinfos << "LLSidepanelTaskInfo::onCommitNextOwnerCopy" << llendl; + onCommitPerm(ctrl, data, PERM_NEXT_OWNER, PERM_COPY); } -void LLSidepanelTaskInfo::onCommitNextOwnerTransfer() +// static +void LLSidepanelTaskInfo::onCommitNextOwnerTransfer(LLUICtrl* ctrl, void* data) { - LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can transfer"); - onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_TRANSFER); + //llinfos << "LLSidepanelTaskInfo::onCommitNextOwnerTransfer" << llendl; + onCommitPerm(ctrl, data, PERM_NEXT_OWNER, PERM_TRANSFER); } -void LLSidepanelTaskInfo::onCommitName() +// static +void LLSidepanelTaskInfo::onCommitName(LLUICtrl*, void* data) { - LLLineEditor* tb = getChild<LLLineEditor>("Object Name"); - LLSelectMgr::getInstance()->selectionSetObjectName(tb->getText()); + //llinfos << "LLSidepanelTaskInfo::onCommitName()" << llendl; + LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data; + LLLineEditor* tb = self->getChild<LLLineEditor>("Object Name"); + if(tb) + { + LLSelectMgr::getInstance()->selectionSetObjectName(tb->getText()); +// LLSelectMgr::getInstance()->selectionSetObjectName(self->mLabelObjectName->getText()); + } } -void LLSidepanelTaskInfo::onCommitDesc() + +// static +void LLSidepanelTaskInfo::onCommitDesc(LLUICtrl*, void* data) { - LLLineEditor* le = getChild<LLLineEditor>("Object Description"); - LLSelectMgr::getInstance()->selectionSetObjectDescription(le->getText()); + //llinfos << "LLSidepanelTaskInfo::onCommitDesc()" << llendl; + LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data; + LLLineEditor* le = self->getChild<LLLineEditor>("Object Description"); + if(le) + { + LLSelectMgr::getInstance()->selectionSetObjectDescription(le->getText()); + } } -void LLSidepanelTaskInfo::onCommitSaleInfo() +// static +void LLSidepanelTaskInfo::onCommitSaleInfo(LLUICtrl*, void* data) { - setAllSaleInfo(); + LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data; + self->setAllSaleInfo(); } -void LLSidepanelTaskInfo::onCommitSaleType() +// static +void LLSidepanelTaskInfo::onCommitSaleType(LLUICtrl*, void* data) { - setAllSaleInfo(); + LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data; + self->setAllSaleInfo(); } + void LLSidepanelTaskInfo::setAllSaleInfo() { - llinfos << "LLSidepanelTaskInfo::setAllSaleInfo()" << llendl; - LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_NOT; + LLCheckBoxCtrl *checkPurchase = getChild<LLCheckBoxCtrl>("checkbox for sale"); + // Set the sale type if the object(s) are for sale. - if (checkPurchase && checkPurchase->get()) + if(checkPurchase && checkPurchase->get()) { sale_type = static_cast<LLSaleInfo::EForSale>(getChild<LLComboBox>("sale type")->getValue().asInteger()); } S32 price = -1; - const LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost"); + + LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost"); price = (edit_price->getTentative()) ? DEFAULT_PRICE : edit_price->getValue().asInteger(); + // If somehow an invalid price, turn the sale off. if (price < 0) sale_type = LLSaleInfo::FS_NOT; - LLSaleInfo sale_info(sale_type, price); - LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(sale_info); - // If turned off for-sale, make sure click-action buy is turned - // off as well - if (sale_type == LLSaleInfo::FS_NOT) - { - U8 click_action = 0; - LLSelectMgr::getInstance()->selectionGetClickAction(&click_action); - if (click_action == CLICK_ACTION_BUY) - { - LLSelectMgr::getInstance()->selectionSetClickAction(CLICK_ACTION_TOUCH); - } - } -} + LLSaleInfo old_sale_info; + LLSelectMgr::getInstance()->selectGetSaleInfo(old_sale_info); -// static -void LLSidepanelTaskInfo::onClickForSale(LLUICtrl* ctrl, void* data) -{ - LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data; - self->updateUIFromSaleInfo(); -} + LLSaleInfo new_sale_info(sale_type, price); + LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(new_sale_info); + + U8 old_click_action = 0; + LLSelectMgr::getInstance()->selectionGetClickAction(&old_click_action); -void LLSidepanelTaskInfo::updateUIFromSaleInfo() -{ - /* - TODO: Update sale button enable/disable state and default - sale button settings when this sale button is enabled/disabled. - */ + if (old_sale_info.isForSale() + && !new_sale_info.isForSale() + && old_click_action == CLICK_ACTION_BUY) + { + // If turned off for-sale, make sure click-action buy is turned + // off as well + LLSelectMgr::getInstance()-> + selectionSetClickAction(CLICK_ACTION_TOUCH); + } + else if (new_sale_info.isForSale() + && !old_sale_info.isForSale() + && old_click_action == CLICK_ACTION_TOUCH) + { + // If just turning on for-sale, preemptively turn on one-click buy + // unless user have a different click action set + LLSelectMgr::getInstance()-> + selectionSetClickAction(CLICK_ACTION_BUY); + } } struct LLSelectionPayable : public LLSelectedObjectFunctor @@ -997,8 +1037,35 @@ struct LLSelectionPayable : public LLSelectedObjectFunctor } }; +static U8 string_value_to_click_action(std::string p_value) +{ + if (p_value == "Touch") + return CLICK_ACTION_TOUCH; + if (p_value == "Sit") + return CLICK_ACTION_SIT; + if (p_value == "Buy") + return CLICK_ACTION_BUY; + if (p_value == "Pay") + return CLICK_ACTION_PAY; + if (p_value == "Open") + return CLICK_ACTION_OPEN; + if (p_value == "Zoom") + return CLICK_ACTION_ZOOM; + return CLICK_ACTION_TOUCH; +} + +// static +void LLSidepanelTaskInfo::onCommitClickAction(LLUICtrl* ctrl, void*) +{ + LLComboBox* box = (LLComboBox*)ctrl; + if (!box) return; + std::string value = box->getValue().asString(); + U8 click_action = string_value_to_click_action(value); + doClickAction(click_action); +} + // static -void LLSidepanelTaskInfo::onCommitClickAction(U8 click_action) +void LLSidepanelTaskInfo::doClickAction(U8 click_action) { if (click_action == CLICK_ACTION_BUY) { @@ -1020,7 +1087,7 @@ void LLSidepanelTaskInfo::onCommitClickAction(U8 click_action) { // Verify object has script with money() handler LLSelectionPayable payable; - const BOOL can_pay = mObjectSelection->applyToObjects(&payable); + bool can_pay = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&payable); if (!can_pay) { // Warn, but do it anyway. @@ -1031,10 +1098,11 @@ void LLSidepanelTaskInfo::onCommitClickAction(U8 click_action) } // static -void LLSidepanelTaskInfo::onCommitIncludeInSearch() +void LLSidepanelTaskInfo::onCommitIncludeInSearch(LLUICtrl* ctrl, void* data) { - LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("search_check"); - LLSelectMgr::getInstance()->selectionSetIncludeInSearch(ctrl->get()); + LLCheckBoxCtrl* box = (LLCheckBoxCtrl*)ctrl; + llassert(box); + LLSelectMgr::getInstance()->selectionSetIncludeInSearch(box->get()); } // virtual @@ -1042,13 +1110,15 @@ void LLSidepanelTaskInfo::updateVerbs() { LLSidepanelInventorySubpanel::updateVerbs(); + /* mOpenBtn->setVisible(!getIsEditing()); mPayBtn->setVisible(!getIsEditing()); mBuyBtn->setVisible(!getIsEditing()); + //const LLViewerObject *obj = getFirstSelectedObject(); + //mEditBtn->setEnabled(obj && obj->permModify()); + */ mOpenBtn->setEnabled(enable_object_open()); - const LLViewerObject *obj = getFirstSelectedObject(); - mEditBtn->setEnabled(obj && obj->permModify()); } void LLSidepanelTaskInfo::onOpenButtonClicked() @@ -1061,28 +1131,28 @@ void LLSidepanelTaskInfo::onOpenButtonClicked() void LLSidepanelTaskInfo::onPayButtonClicked() { - onCommitClickAction(CLICK_ACTION_PAY); + doClickAction(CLICK_ACTION_PAY); } void LLSidepanelTaskInfo::onBuyButtonClicked() { - onCommitClickAction(CLICK_ACTION_BUY); + doClickAction(CLICK_ACTION_BUY); } // virtual void LLSidepanelTaskInfo::save() { - onCommitGroupShare(); - onCommitEveryoneMove(); - onCommitEveryoneCopy(); - onCommitNextOwnerModify(); - onCommitNextOwnerCopy(); - onCommitNextOwnerTransfer(); - onCommitName(); - onCommitDesc(); - onCommitSaleInfo(); - onCommitSaleType(); - onCommitIncludeInSearch(); + onCommitGroupShare(getChild<LLCheckBoxCtrl>("checkbox share with group"), this); + onCommitEveryoneMove(getChild<LLCheckBoxCtrl>("checkbox allow everyone move"), this); + onCommitEveryoneCopy(getChild<LLCheckBoxCtrl>("checkbox allow everyone copy"), this); + onCommitNextOwnerModify(getChild<LLCheckBoxCtrl>("checkbox next owner can modify"), this); + onCommitNextOwnerCopy(getChild<LLCheckBoxCtrl>("checkbox next owner can copy"), this); + onCommitNextOwnerTransfer(getChild<LLCheckBoxCtrl>("checkbox next owner can transfer"), this); + onCommitName(getChild<LLLineEditor>("Object Name"), this); + onCommitDesc(getChild<LLLineEditor>("Object Description"), this); + onCommitSaleInfo(NULL, this); + onCommitSaleType(NULL, this); + onCommitIncludeInSearch(getChild<LLCheckBoxCtrl>("search_check"), this); } void LLSidepanelTaskInfo::setObjectSelection(LLObjectSelectionHandle selection) diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h index 7c6d9983ae..cf36c20767 100644 --- a/indra/newview/llsidepaneltaskinfo.h +++ b/indra/newview/llsidepaneltaskinfo.h @@ -72,28 +72,30 @@ protected: static void onClickRelease(void*); void onClickGroup(); void cbGroupID(LLUUID group_id); + static void onClickDeedToGroup(void*); - void onClickDeedToGroup(); - void onCommitPerm(LLCheckBoxCtrl* ctrl, U8 field, U32 perm); - void onCommitGroupShare(); - void onCommitEveryoneMove(); - void onCommitEveryoneCopy(); - void onCommitNextOwnerModify(); - void onCommitNextOwnerCopy(); - void onCommitNextOwnerTransfer(); - void onCommitName(); - void onCommitDesc(); - void onCommitSaleInfo(); - void onCommitSaleType(); - - void onCommitClickAction(U8 click_action); - void onCommitIncludeInSearch(); + static void onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm); + static void onCommitGroupShare(LLUICtrl *ctrl, void *data); + + static void onCommitEveryoneMove(LLUICtrl *ctrl, void *data); + static void onCommitEveryoneCopy(LLUICtrl *ctrl, void *data); + + static void onCommitNextOwnerModify(LLUICtrl* ctrl, void* data); + static void onCommitNextOwnerCopy(LLUICtrl* ctrl, void* data); + static void onCommitNextOwnerTransfer(LLUICtrl* ctrl, void* data); + + static void onCommitName(LLUICtrl* ctrl, void* data); + static void onCommitDesc(LLUICtrl* ctrl, void* data); + + static void onCommitSaleInfo(LLUICtrl* ctrl, void* data); + static void onCommitSaleType(LLUICtrl* ctrl, void* data); void setAllSaleInfo(); - static void onClickForSale(LLUICtrl* ctrl, void *data); - void updateUIFromSaleInfo(); + static void onCommitClickAction(LLUICtrl* ctrl, void* data); + static void onCommitIncludeInSearch(LLUICtrl* ctrl, void*); + static void doClickAction(U8 click_action); void disableAll(); private: diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index a1af2e5411..608165022f 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -354,8 +354,7 @@ LLButton* LLSideTray::createButton (const std::string& name,const std::string& i button->setLabel(name); button->setClickedCallback(callback); - if(tooltip!="Home") - button->setToolTip(tooltip); + button->setToolTip(tooltip); if(image.length()) { diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index d8d1760c38..539673ab9e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -121,7 +121,6 @@ #include "lllogininstance.h" // Host the login module. #include "llpanellogin.h" #include "llmutelist.h" -#include "llnotify.h" #include "llpanelavatar.h" #include "llavatarpropertiesprocessor.h" #include "llpanelevent.h" @@ -2695,12 +2694,15 @@ std::string LLStartUp::startupStateToString(EStartupState state) #define RTNENUM(E) case E: return #E switch(state){ RTNENUM( STATE_FIRST ); + RTNENUM( STATE_BROWSER_INIT ); RTNENUM( STATE_LOGIN_SHOW ); RTNENUM( STATE_LOGIN_WAIT ); RTNENUM( STATE_LOGIN_CLEANUP ); RTNENUM( STATE_LOGIN_AUTH_INIT ); RTNENUM( STATE_LOGIN_PROCESS_RESPONSE ); RTNENUM( STATE_WORLD_INIT ); + RTNENUM( STATE_MULTIMEDIA_INIT ); + RTNENUM( STATE_FONT_INIT ); RTNENUM( STATE_SEED_GRANTED_WAIT ); RTNENUM( STATE_SEED_CAP_GRANTED ); RTNENUM( STATE_WORLD_WAIT ); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 4915720036..9e72464237 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -50,7 +50,6 @@ #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" -#include "llnotify.h" #include "llimview.h" #include "llsd.h" #include "lltextbox.h" diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index bef7f5d6aa..ea49f9c32e 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -34,10 +34,12 @@ #include "llflatlistview.h" #include "llfloaterreg.h" +#include "llnotifications.h" #include "llsyswellwindow.h" #include "llbottomtray.h" +#include "llscriptfloater.h" #include "llviewercontrol.h" #include "llviewerwindow.h" @@ -49,6 +51,7 @@ LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key), mChannel(NULL), mMessageList(NULL), + mSysWellChiclet(NULL), mSeparator(NULL), NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"), IM_WELL_ANCHOR_NAME("im_well_panel") @@ -78,6 +81,10 @@ BOOL LLSysWellWindow::postBuild() mMessageList->addItem(mSeparator); + // click on SysWell Window should clear "new message" state (and 'Lit' status). EXT-3147. + // mouse up callback is not called in this case. + setMouseDownCallback(boost::bind(&LLSysWellWindow::releaseNewMessagesState, this)); + return LLDockableFloater::postBuild(); } @@ -170,6 +177,12 @@ void LLSysWellWindow::setVisible(BOOL visible) if(mChannel) { mChannel->updateShowToastsState(); + mChannel->redrawToasts(); + } + + if (visible) + { + releaseNewMessagesState(); } } @@ -188,6 +201,7 @@ void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock) if(mChannel) { mChannel->updateShowToastsState(); + mChannel->redrawToasts(); } } @@ -223,6 +237,14 @@ void LLSysWellWindow::reshapeWindow() } } +void LLSysWellWindow::releaseNewMessagesState() +{ + if (NULL != mSysWellChiclet) + { + mSysWellChiclet->setNewMessagesState(false); + } +} + //--------------------------------------------------------------------------------- bool LLSysWellWindow::isWindowEmpty() { @@ -242,6 +264,24 @@ void LLSysWellWindow::handleItemAdded(EItemType added_item_type) // refresh list to recalculate mSeparator position mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight()); } + + //fix for EXT-3254 + //set limits for min_height. + S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight(); + + std::vector<LLPanel*> items; + mMessageList->getItems(items); + + if(items.size()>1)//first item is separator + { + S32 min_height; + S32 min_width; + getResizeLimits(&min_width,&min_height); + + min_height = items[1]->getRect().getHeight() + 2 * mMessageList->getBorderWidth() + parent_list_delta_height; + + setResizeLimits(min_width,min_height); + } } void LLSysWellWindow::handleItemRemoved(EItemType removed_item_type) @@ -356,7 +396,148 @@ BOOL LLIMWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask) return LLPanel::handleMouseDown(x, y, mask); } +/************************************************************************/ +/* ObjectRowPanel implementation */ +/************************************************************************/ + +LLIMWellWindow::ObjectRowPanel::ObjectRowPanel(const LLUUID& object_id, bool new_message/* = false*/) + : LLPanel() + , mChiclet(NULL) +{ + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_active_object_row.xml", NULL); + + initChiclet(object_id); + + LLTextBox* obj_name = getChild<LLTextBox>("object_name"); + obj_name->setValue(getObjectName(object_id)); + + mCloseBtn = getChild<LLButton>("hide_btn"); + mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::ObjectRowPanel::onClosePanel, this)); +} + +//--------------------------------------------------------------------------------- +LLIMWellWindow::ObjectRowPanel::~ObjectRowPanel() +{ +} + +std::string LLIMWellWindow::ObjectRowPanel::getObjectName(const LLUUID& object_id) +{ + using namespace LLNotificationsUI; + LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id); + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); + if(!notification) + { + llwarns << "Invalid notification" << llendl; + return LLStringUtil::null; + } + std::string text; + + switch(getObjectType(notification)) + { + case OBJ_SCRIPT: + text = notification->getSubstitutions()["TITLE"].asString(); + break; + case OBJ_LOAD_URL: + text = notification->getSubstitutions()["OBJECTNAME"].asString(); + break; + case OBJ_GIVE_INVENTORY: + text = notification->getSubstitutions()["NAME"].asString(); + break; + default: + text = getString("unknown_obj"); + break; + } + + return text; +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onClosePanel() +{ + LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(mChiclet->getSessionId()); +} + +//static +LLIMWellWindow::ObjectRowPanel::object_type_map LLIMWellWindow::ObjectRowPanel::initObjectTypeMap() +{ + object_type_map type_map; + type_map["ScriptDialog"] = OBJ_SCRIPT; + type_map["LoadWebPage"] = OBJ_LOAD_URL; + type_map["ObjectGiveItem"] = OBJ_GIVE_INVENTORY; + return type_map; +} + +// static +LLIMWellWindow::ObjectRowPanel::EObjectType LLIMWellWindow::ObjectRowPanel::getObjectType(const LLNotificationPtr& notification) +{ + if(!notification) + { + llwarns << "Invalid notification" << llendl; + return OBJ_UNKNOWN; + } + + static object_type_map type_map = initObjectTypeMap(); + std::string name = notification->getName(); + object_type_map::const_iterator it = type_map.find(name); + if(it != type_map.end()) + { + return it->second; + } + + llwarns << "Unknown object type" << llendl; + return OBJ_UNKNOWN; +} + +void LLIMWellWindow::ObjectRowPanel::initChiclet(const LLUUID& object_id, bool new_message/* = false*/) +{ + using namespace LLNotificationsUI; + LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id); + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); + if(!notification) + { + llwarns << "Invalid notification" << llendl; + return; + } + + // Choose which of the pre-created chiclets to use. + switch(getObjectType(notification)) + { + case OBJ_GIVE_INVENTORY: + mChiclet = getChild<LLInvOfferChiclet>("inv_offer_chiclet"); + break; + default: + mChiclet = getChild<LLScriptChiclet>("object_chiclet"); + break; + } + + mChiclet->setVisible(true); + mChiclet->setSessionId(object_id); +// mChiclet->setShowNewMessagesIcon(new_message); +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onMouseEnter(S32 x, S32 y, MASK mask) +{ + setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onMouseLeave(S32 x, S32 y, MASK mask) +{ + setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); +} + +//--------------------------------------------------------------------------------- +// virtual +BOOL LLIMWellWindow::ObjectRowPanel::handleMouseDown(S32 x, S32 y, MASK mask) +{ + // Pass the mouse down event to the chiclet (EXT-596). + if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown() + mChiclet->onMouseDown(); + + return LLPanel::handleMouseDown(x, y, mask); +} /************************************************************************/ /* LLNotificationWellWindow implementation */ @@ -503,6 +684,7 @@ LLIMWellWindow::LLIMWellWindow(const LLSD& key) { LLIMMgr::getInstance()->addSessionObserver(this); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findIMChiclet, this, _1)); + LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findObjectChiclet, this, _1)); } LLIMWellWindow::~LLIMWellWindow() @@ -557,6 +739,18 @@ void LLIMWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID } } +LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& object_id) +{ + LLChiclet* res = NULL; + ObjectRowPanel* panel = mMessageList->getTypedItemByValue<ObjectRowPanel>(object_id); + if (panel != NULL) + { + res = panel->mChiclet; + } + + return res; +} + ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS LLChiclet* LLIMWellWindow::findIMChiclet(const LLUUID& sessionId) @@ -594,6 +788,13 @@ void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, //--------------------------------------------------------------------------------- void LLIMWellWindow::delIMRow(const LLUUID& sessionId) { + //fix for EXT-3252 + //without this line LLIMWellWindow receive onFocusLost + //and hide itself. It was becaue somehow LLIMChicklet was in focus group for + //LLIMWellWindow... + //But I didn't find why this happen.. + gFocusMgr.clearLastFocusForGroup(this); + if (mMessageList->removeItemByValue(sessionId)) { handleItemRemoved(IT_INSTANT_MESSAGE); @@ -613,6 +814,47 @@ void LLIMWellWindow::delIMRow(const LLUUID& sessionId) { setVisible(FALSE); } + else + { + setFocus(true); + } +} + +void LLIMWellWindow::addObjectRow(const LLUUID& object_id, bool new_message/* = false*/) +{ + if (mMessageList->getItemByValue(object_id) == NULL) + { + ObjectRowPanel* item = new ObjectRowPanel(object_id, new_message); + if (mMessageList->insertItemAfter(mSeparator, item, object_id)) + { + handleItemAdded(IT_INSTANT_MESSAGE); + } + else + { + llwarns << "Unable to add Object Row into the list, objectID: " << object_id << llendl; + item->die(); + } + reshapeWindow(); + } +} + +void LLIMWellWindow::removeObjectRow(const LLUUID& object_id) +{ + if (mMessageList->removeItemByValue(object_id)) + { + handleItemRemoved(IT_INSTANT_MESSAGE); + } + else + { + llwarns << "Unable to remove Object Row from the list, objectID: " << object_id << llendl; + } + + reshapeWindow(); + // hide chiclet window if there are no items left + if(isWindowEmpty()) + { + setVisible(FALSE); + } } // EOF diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index adbc83677d..fea145a17e 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -46,7 +46,8 @@ class LLFlatListView; class LLChiclet; class LLIMChiclet; - +class LLScriptChiclet; +class LLSysWellChiclet; class LLSysWellWindow : public LLDockableFloater @@ -78,6 +79,8 @@ public: void onStartUpToastClick(S32 x, S32 y, MASK mask); + void setSysWellChiclet(LLSysWellChiclet* chiclet) { mSysWellChiclet = chiclet; } + // size constants for the window and for its elements static const S32 MAX_WINDOW_HEIGHT = 200; static const S32 MIN_WINDOW_WIDTH = 318; @@ -104,12 +107,18 @@ protected: virtual const std::string& getAnchorViewName() = 0; void reshapeWindow(); + void releaseNewMessagesState(); // pointer to a corresponding channel's instance LLNotificationsUI::LLScreenChannel* mChannel; LLFlatListView* mMessageList; /** + * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147 + */ + LLSysWellChiclet* mSysWellChiclet; + + /** * Special panel which is used as separator of Notifications & IM Rows. * It is always presents in the list and shown when it is necessary. * It should be taken into account when reshaping and checking list size @@ -126,14 +135,12 @@ protected: * * It contains a list of notifications that have not been responded to. */ -class LLNotificationWellWindow : public LLSysWellWindow, public LLInitClass<LLNotificationWellWindow> +class LLNotificationWellWindow : public LLSysWellWindow { public: LLNotificationWellWindow(const LLSD& key); static LLNotificationWellWindow* getInstance(const LLSD& key = LLSD()); - static void initClass() { getInstance(); } - /*virtual*/ BOOL postBuild(); /*virtual*/ void setVisible(BOOL visible); @@ -181,11 +188,16 @@ public: /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); + void addObjectRow(const LLUUID& object_id, bool new_message = false); + void removeObjectRow(const LLUUID& object_id); + protected: /*virtual*/ const std::string& getAnchorViewName() { return IM_WELL_ANCHOR_NAME; } private: LLChiclet * findIMChiclet(const LLUUID& sessionId); + LLChiclet* findObjectChiclet(const LLUUID& object_id); + void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId); void delIMRow(const LLUUID& sessionId); @@ -210,6 +222,37 @@ private: LLButton* mCloseBtn; const LLSysWellWindow* mParent; }; + + class ObjectRowPanel: public LLPanel + { + typedef enum e_object_type + { + OBJ_UNKNOWN, + + OBJ_SCRIPT, + OBJ_GIVE_INVENTORY, + OBJ_LOAD_URL + }EObjectType; + + public: + ObjectRowPanel(const LLUUID& object_id, bool new_message = false); + virtual ~ObjectRowPanel(); + /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + private: + void onClosePanel(); + static EObjectType getObjectType(const LLNotificationPtr& notification); + void initChiclet(const LLUUID& object_id, bool new_message = false); + std::string getObjectName(const LLUUID& object_id); + + typedef std::map<std::string, EObjectType> object_type_map; + static object_type_map initObjectTypeMap(); + public: + LLIMChiclet* mChiclet; + private: + LLButton* mCloseBtn; + }; }; #endif // LL_LLSYSWELLWINDOW_H diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 8d3dcf8a99..72ef383be9 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -31,8 +31,14 @@ */ #include "llviewerprecompiledheaders.h" -#include "llagent.h" + #include "lltexlayer.h" + +#include "llagent.h" +#include "llimagej2c.h" +#include "llimagetga.h" +#include "llvfile.h" +#include "llvfs.h" #include "llviewerstats.h" #include "llviewerregion.h" #include "llvoavatar.h" diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp index 0c7e61d00e..d55468841d 100644 --- a/indra/newview/lltexlayerparams.cpp +++ b/indra/newview/lltexlayerparams.cpp @@ -30,11 +30,14 @@ */ #include "llviewerprecompiledheaders.h" + +#include "lltexlayerparams.h" + #include "llagent.h" +#include "llimagetga.h" #include "lltexlayer.h" #include "llvoavatarself.h" #include "llwearable.h" -#include "lltexlayerparams.h" #include "llui.h" //----------------------------------------------------------------------------- diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index 2b80dbdba4..93d01352d4 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -34,7 +34,11 @@ #include "llviewervisualparam.h" +class LLImageRaw; +class LLImageTGA; class LLTexLayer; +class LLTexLayerInterface; +class LLViewerTexture; class LLVOAvatar; class LLWearable; diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index bc9c988648..4203cbbc43 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -40,6 +40,7 @@ #include "llworkerthread.h" +class LLImageFormatted; class LLTextureCacheWorker; class LLTextureCache : public LLWorkerThread diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 67007629c0..9f69ed3964 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -43,8 +43,10 @@ #include "llhttpclient.h" #include "llhttpstatuscodes.h" #include "llimage.h" +#include "llimagej2c.h" #include "llimageworker.h" #include "llworkerthread.h" +#include "message.h" #include "llagent.h" #include "lltexturecache.h" @@ -311,10 +313,10 @@ public: { bool success = false; bool partial = false; - if (200 <= status && status < 300) + if (HTTP_OK <= status && status < HTTP_MULTIPLE_CHOICES) { success = true; - if (203 == status) // partial information (i.e. last block) + if (HTTP_PARTIAL_CONTENT == status) // partial information (i.e. last block) { partial = true; } @@ -885,6 +887,8 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { + // mFormattedImage gauranteed to not be NULL since cur_size != 0 + mLoadedDiscard = mFormattedImage->getDiscardLevel(); mState = DECODE_IMAGE; return false; // use what we have } diff --git a/indra/newview/lltexturestatsuploader.cpp b/indra/newview/lltexturestatsuploader.cpp index e0358e1fca..1df73db9b0 100644 --- a/indra/newview/lltexturestatsuploader.cpp +++ b/indra/newview/lltexturestatsuploader.cpp @@ -34,6 +34,8 @@ #include "lltexturestatsuploader.h" +#include "llhttpclient.h" + LLTextureStatsUploader::LLTextureStatsUploader() { } diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index fc7c029a17..2a56b2cd3a 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -67,10 +67,13 @@ LLToast::LLToast(const LLToast::Params& p) mHideBtn(NULL), mNotification(p.notification), mIsHidden(false), - mHideBtnPressed(false) + mHideBtnPressed(false), + mIsTip(p.is_tip) { LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL); + setCanDrag(FALSE); + if(mPanel) { insertPanel(mPanel); @@ -98,10 +101,30 @@ BOOL LLToast::postBuild() mTimer.stop(); } + if (mIsTip) + { + mTextEditor = mPanel->getChild<LLTextEditor>("text_editor_box"); + + if (mTextEditor) + { + mTextEditor->setMouseUpCallback(boost::bind(&LLToast::hide,this)); + mPanel->setMouseUpCallback(boost::bind(&LLToast::handleTipToastClick, this, _2, _3, _4)); + } + } + return TRUE; } //-------------------------------------------------------------------------- +void LLToast::handleTipToastClick(S32 x, S32 y, MASK mask) +{ + if (!mTextEditor->getRect().pointInRect(x, y)) + { + hide(); + } +} + +//-------------------------------------------------------------------------- void LLToast::setHideButtonEnabled(bool enabled) { if(mHideBtn) diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index d08e46e160..3d25fd4f02 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -40,6 +40,7 @@ #include "llnotificationptr.h" #include "llviewercontrol.h" +#include "lltexteditor.h" #define MOUSE_LEAVE false #define MOUSE_ENTER true @@ -138,6 +139,7 @@ public: // set whether this toast considered as hidden or not void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; } + const LLNotificationPtr& getNotification() { return mNotification;} // Registers signals/callbacks for events toast_signal_t mOnFadeSignal; @@ -155,6 +157,8 @@ public: private: + void handleTipToastClick(S32 x, S32 y, MASK mask); + // check timer bool lifetimeHasExpired(); // on timer finished function @@ -169,8 +173,9 @@ private: F32 mToastLifetime; // in seconds F32 mToastFadingTime; // in seconds - LLPanel* mPanel; - LLButton* mHideBtn; + LLPanel* mPanel; + LLButton* mHideBtn; + LLTextEditor* mTextEditor; LLColor4 mBgColor; bool mCanFade; @@ -178,6 +183,7 @@ private: bool mHideBtnEnabled; bool mHideBtnPressed; bool mIsHidden; // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849) + bool mIsTip; }; } diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index a4f5164a8d..c48301fa1e 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -30,10 +30,6 @@ * $/LicenseInfo$ */ -// *NOTE: this module is a copy-paste of llui/llalertdialog.h -// Can we re-implement this as a subclass of LLAlertDialog and -// avoid all this code duplication? It already caused EXT-2232. - #include "llviewerprecompiledheaders.h" // must be first include #include "linden_common.h" @@ -60,7 +56,7 @@ const F32 DEFAULT_BUTTON_DELAY = 0.5f; const S32 MSG_PAD = 8; /*static*/ LLControlGroup* LLToastAlertPanel::sSettings = NULL; -/*static*/ LLAlertURLLoader* LLToastAlertPanel::sURLLoader; +/*static*/ LLToastAlertPanel::URLLoader* LLToastAlertPanel::sURLLoader; //----------------------------------------------------------------------------- // Private methods diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index 38a635e8a4..875ab82c54 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -30,10 +30,6 @@ * $/LicenseInfo$ */ -// *NOTE: this module is a copy-paste of llui/llalertdialog.h -// Can we re-implement this as a subclass of LLAlertDialog and -// avoid all this code duplication? It already caused EXT-2232. - #ifndef LL_TOASTALERTPANEL_H #define LL_TOASTALERTPANEL_H @@ -41,11 +37,9 @@ #include "llfloater.h" #include "llui.h" #include "llnotificationptr.h" -#include "llalertdialog.h" class LLButton; class LLCheckBoxCtrl; -class LLAlertDialogTemplate; class LLLineEditor; /** @@ -62,7 +56,16 @@ class LLToastAlertPanel public: typedef bool (*display_callback_t)(S32 modal); - static void setURLLoader(LLAlertURLLoader* loader) + class URLLoader + { + public: + virtual void load(const std::string& url, bool force_open_externally = 0) = 0; + virtual ~URLLoader() + { + } + }; + + static void setURLLoader(URLLoader* loader) { sURLLoader = loader; } @@ -95,7 +98,7 @@ private: BOOL hasTitleBar() const; private: - static LLAlertURLLoader* sURLLoader; + static URLLoader* sURLLoader; static LLControlGroup* sSettings; struct ButtonData diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index eacc077a65..e49044cdca 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -40,7 +40,6 @@ #include "lliconctrl.h" #include "llinventoryfunctions.h" #include "llnotifications.h" -#include "llnotify.h" #include "llviewertexteditor.h" #include "lluiconstants.h" diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index 7beba59c83..b7add03e0e 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -34,6 +34,7 @@ #include "lltoastimpanel.h" #include "llnotifications.h" +#include "llinstantmessage.h" const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6; @@ -85,7 +86,6 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif sys_msg_icon->setVisible(FALSE); mAvatar->setValue(p.avatar_id); - setMouseDownCallback(boost::bind(&LLToastIMPanel::onClickToastIM, this)); } S32 maxLinesCount; @@ -102,11 +102,13 @@ LLToastIMPanel::~LLToastIMPanel() { } -//-------------------------------------------------------------------------- -void LLToastIMPanel::onClickToastIM() +//virtual +BOOL LLToastIMPanel::handleMouseDown(S32 x, S32 y, MASK mask) { - mNotification->respond(mNotification->getResponseTemplate()); -} - -//-------------------------------------------------------------------------- + if (LLPanel::handleMouseDown(x,y,mask) == FALSE) + { + mNotification->respond(mNotification->getResponseTemplate()); + } + return TRUE; +} diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index 23f08ef610..53661f2cf6 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -57,12 +57,10 @@ public: LLToastIMPanel(LLToastIMPanel::Params &p); virtual ~LLToastIMPanel(); - + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); private: static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT; - void onClickToastIM(); - LLNotificationPtr mNotification; LLUUID mSessionID; LLAvatarIconCtrl* mAvatar; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 6b9bff7b9e..766cf83a01 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -38,6 +38,7 @@ #include "llviewercontrol.h" // library includes +#include "lldbstrings.h" #include "llnotifications.h" #include "lluiconstants.h" #include "llrect.h" diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index afb9e261b0..755e647777 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -80,7 +80,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) //Knowing the height is set to max allowed, getTextPixelHeight returns needed text height //Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape. - S32 requiredTextHeight = message->getContentsRect().getHeight(); + S32 requiredTextHeight = message->getTextBoundingRect().getHeight(); S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); //Calculate last delta height deducting previous heightDelta diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 2d0a14dc70..aa35f22930 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -772,6 +772,9 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, { LLInventoryObject* cargo = locateInventory(item, cat); + // fix for EXT-3191 + if (NULL == cargo) return; + EAcceptance item_acceptance = ACCEPT_NO; handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, mCargoTypes[mCurItemIndex], diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 5ed8dc5fb9..74fbce890d 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1243,8 +1243,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) return false; } - - // Does this face have media? const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); if(!tep) @@ -1257,11 +1255,11 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL; - if (gSavedSettings.getBOOL("MediaOnAPrimUI") - && media_impl.notNull()) + if (gSavedSettings.getBOOL("MediaOnAPrimUI")) { - if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) ) + if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull()) { + // It's okay to give this a null impl LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal); } else @@ -1445,28 +1443,29 @@ BOOL LLToolPie::pickRightMouseDownCallback() { LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal ); gMenuHolder->setParcelSelection(selection); - gPieLand->show(x, y); + gMenuLand->show(x, y); showVisualContextMenuEffect(); } else if (mPick.mObjectID == gAgent.getID() ) { - if(!gPieSelf) + if(!gMenuAvatarSelf) { //either at very early startup stage or at late quitting stage, //this event is ignored. return TRUE ; } - gPieSelf->show(x, y); + gMenuAvatarSelf->show(x, y); } else if (object) { gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection()); + bool is_other_attachment = (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner()); if (object->isAvatar() - || (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner())) + || is_other_attachment) { // Find the attachment's avatar while( object && object->isAttachment()) @@ -1477,20 +1476,30 @@ BOOL LLToolPie::pickRightMouseDownCallback() // Object is an avatar, so check for mute by id. LLVOAvatar* avatar = (LLVOAvatar*)object; std::string name = avatar->getFullname(); + std::string mute_msg; if (LLMuteList::getInstance()->isMuted(avatar->getID(), avatar->getFullname())) { - gMenuHolder->childSetText("Avatar Mute", std::string("Unmute")); // *TODO:Translate + mute_msg = LLTrans::getString("UnmuteAvatar"); } else { - gMenuHolder->childSetText("Avatar Mute", std::string("Mute")); // *TODO:Translate + mute_msg = LLTrans::getString("MuteAvatar"); } - gPieAvatar->show(x, y); + if (is_other_attachment) + { + gMenuAttachmentOther->getChild<LLUICtrl>("Avatar Mute")->setValue(mute_msg); + gMenuAttachmentOther->show(x, y); + } + else + { + gMenuAvatarOther->getChild<LLUICtrl>("Avatar Mute")->setValue(mute_msg); + gMenuAvatarOther->show(x, y); + } } else if (object->isAttachment()) { - gPieAttachment->show(x, y); + gMenuAttachmentSelf->show(x, y); } else { @@ -1501,16 +1510,18 @@ BOOL LLToolPie::pickRightMouseDownCallback() { name = node->mName; } + std::string mute_msg; if (LLMuteList::getInstance()->isMuted(object->getID(), name)) { - gMenuHolder->childSetText("Object Mute", std::string("Unmute")); // *TODO:Translate + mute_msg = LLTrans::getString("UnmuteObject"); } else { - gMenuHolder->childSetText("Object Mute", std::string("Mute")); // *TODO:Translate + mute_msg = LLTrans::getString("MuteObject"); } - gPieObject->show(x, y); + gMenuHolder->childSetText("Object Mute", mute_msg); + gMenuObject->show(x, y); showVisualContextMenuEffect(); } diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 46618d4026..0b6bd4b401 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -41,17 +41,21 @@ #include "llfloaterurldisplay.h" #include "llfloaterworldmap.h" #include "llpanellogin.h" +#include "llregionhandle.h" #include "llsidetray.h" #include "llslurl.h" #include "llstartup.h" // gStartupState #include "llurlsimstring.h" #include "llweb.h" #include "llworldmapmessage.h" +#include "llurldispatcherlistener.h" // library includes #include "llnotificationsutil.h" #include "llsd.h" +static LLURLDispatcherListener sURLDispatcherListener; + class LLURLDispatcherImpl { public: diff --git a/indra/newview/llurldispatcherlistener.cpp b/indra/newview/llurldispatcherlistener.cpp new file mode 100644 index 0000000000..fea6a769c5 --- /dev/null +++ b/indra/newview/llurldispatcherlistener.cpp @@ -0,0 +1,58 @@ +/** + * @file llurldispatcherlistener.cpp + * @author Nat Goodspeed + * @date 2009-12-10 + * @brief Implementation for llurldispatcherlistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llurldispatcherlistener.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llurldispatcher.h" + +LLURLDispatcherListener::LLURLDispatcherListener(/* LLURLDispatcher* instance */): + LLEventAPI("LLURLDispatcher", "Internal URL handling") /* , + mDispatcher(instance) */ +{ + add("dispatch", + "At startup time or on clicks in internal web browsers,\n" + "teleport, open map, or run requested command.\n" + "[\"url\"] string url to dispatch\n" + "[\"trusted\"] boolean indicating trusted browser [default true]", + &LLURLDispatcherListener::dispatch); + add("dispatchRightClick", "Dispatch [\"url\"] as if from a right-click on a hot link.", + &LLURLDispatcherListener::dispatchRightClick); + add("dispatchFromTextEditor", "Dispatch [\"url\"] as if from an edit field.", + &LLURLDispatcherListener::dispatchFromTextEditor); +} + +void LLURLDispatcherListener::dispatch(const LLSD& params) const +{ + // For most purposes, we expect callers to want to be trusted. + bool trusted_browser = true; + if (params.has("trusted")) + { + // But for testing, allow a caller to specify untrusted. + trusted_browser = params["trusted"].asBoolean(); + } + LLURLDispatcher::dispatch(params["url"], NULL, trusted_browser); +} + +void LLURLDispatcherListener::dispatchRightClick(const LLSD& params) const +{ + LLURLDispatcher::dispatchRightClick(params["url"]); +} + +void LLURLDispatcherListener::dispatchFromTextEditor(const LLSD& params) const +{ + LLURLDispatcher::dispatchFromTextEditor(params["url"]); +} diff --git a/indra/newview/llurldispatcherlistener.h b/indra/newview/llurldispatcherlistener.h new file mode 100644 index 0000000000..894afcbb51 --- /dev/null +++ b/indra/newview/llurldispatcherlistener.h @@ -0,0 +1,32 @@ +/** + * @file llurldispatcherlistener.h + * @author Nat Goodspeed + * @date 2009-12-10 + * @brief LLEventAPI for LLURLDispatcher + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLURLDISPATCHERLISTENER_H) +#define LL_LLURLDISPATCHERLISTENER_H + +#include "lleventapi.h" +class LLURLDispatcher; +class LLSD; + +class LLURLDispatcherListener: public LLEventAPI +{ +public: + LLURLDispatcherListener(/* LLURLDispatcher* instance */); // all static members + +private: + void dispatch(const LLSD& params) const; + void dispatchRightClick(const LLSD& params) const; + void dispatchFromTextEditor(const LLSD& params) const; + + //LLURLDispatcher* mDispatcher; +}; + +#endif /* ! defined(LL_LLURLDISPATCHERLISTENER_H) */ diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index a041f3ac98..bb49804aff 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -32,12 +32,13 @@ #include "llviewerprecompiledheaders.h" -#include "linden_common.h" - -#include "llagent.h" #include "llviewerassetstorage.h" + #include "llvfile.h" #include "llvfs.h" +#include "message.h" + +#include "llagent.h" LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, const LLHost &upstream_host) diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 6339d23fa7..f3db0ab170 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -63,7 +63,6 @@ #include "llviewerjoystick.h" #include "llviewerparcelmgr.h" #include "llparcel.h" -#include "llnotify.h" #include "lloverlaybar.h" #include "llkeyboard.h" #include "llerrorcontrol.h" @@ -516,34 +515,13 @@ bool toggle_show_snapshot_button(const LLSD& newvalue) bool toggle_show_navigation_panel(const LLSD& newvalue) { - LLRect floater_view_rect = gFloaterView->getRect(); - LLRect notify_view_rect = gNotifyBoxView->getRect(); - LLNavigationBar* navbar = LLNavigationBar::getInstance(); - - //if newvalue contains 0 => navbar should turn invisible, so floater_view_rect should get higher, - //and to do this pm=1, else if navbar becomes visible pm=-1 so floater_view_rect gets lower. - int pm=newvalue.asBoolean()?-1:1; - floater_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight()); - notify_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight()); - gFloaterView->setRect(floater_view_rect); - floater_view_rect = gFloaterView->getRect(); - navbar->showNavigationPanel(newvalue.asBoolean()); + LLNavigationBar::getInstance()->showNavigationPanel(newvalue.asBoolean()); return true; } bool toggle_show_favorites_panel(const LLSD& newvalue) { - LLRect floater_view_rect = gFloaterView->getRect(); - LLRect notify_view_rect = gNotifyBoxView->getRect(); - LLNavigationBar* navbar = LLNavigationBar::getInstance(); - - //if newvalue contains 0 => favbar should turn invisible, so floater_view_rect should get higher, - //and to do this pm=1, else if favbar becomes visible pm=-1 so floater_view_rect gets lower. - int pm=newvalue.asBoolean()?-1:1; - floater_view_rect.mTop += pm*navbar->getDefFavBarHeight(); - notify_view_rect.mTop += pm*navbar->getDefFavBarHeight(); - gFloaterView->setRect(floater_view_rect); - navbar->showFavoritesPanel(newvalue.asBoolean()); + LLNavigationBar::getInstance()->showFavoritesPanel(newvalue.asBoolean()); return true; } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 5b733ed817..68a5147bc7 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1009,10 +1009,10 @@ void render_hud_attachments() glh_set_current_modelview(current_mod); } -BOOL setup_hud_matrices() +LLRect get_whole_screen_region() { LLRect whole_screen = gViewerWindow->getWindowRectScaled(); - + // apply camera zoom transform (for high res screenshots) F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); @@ -1024,52 +1024,43 @@ BOOL setup_hud_matrices() int tile_y = sub_region / num_horizontal_tiles; int tile_x = sub_region - (tile_y * num_horizontal_tiles); glh::matrix4f mat; - + whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeightScaled() - (tile_y * tile_height), tile_width, tile_height); } - - return setup_hud_matrices(whole_screen); + return whole_screen; } -BOOL setup_hud_matrices(const LLRect& screen_region) +bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model) { LLVOAvatar* my_avatarp = gAgent.getAvatarObject(); if (my_avatarp && my_avatarp->hasHUDAttachment()) { F32 zoom_level = gAgent.mHUDCurZoom; LLBBox hud_bbox = my_avatarp->getHUDBBox(); - - // set up transform to keep HUD objects in front of camera - glMatrixMode(GL_PROJECTION); + F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - glh::matrix4f proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); + proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); proj.element(2,2) = -0.01f; - + F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect(); - + glh::matrix4f mat; F32 scale_x = (F32)gViewerWindow->getWindowWidthScaled() / (F32)screen_region.getWidth(); F32 scale_y = (F32)gViewerWindow->getWindowHeightScaled() / (F32)screen_region.getHeight(); mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f)); mat.set_translate( glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWindowWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), - clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeightScaled(), 0.5f * scale_y, -0.5f * scale_y), - 0.f)); + clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeightScaled(), 0.5f * scale_y, -0.5f * scale_y), + 0.f)); proj *= mat; - - glLoadMatrixf(proj.m); - glh_set_current_projection(proj); - - glMatrixMode(GL_MODELVIEW); - glh::matrix4f model((GLfloat*) OGL_TO_CFR_ROTATION); + + glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION); mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level)); mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f)); - - model *= mat; - glLoadMatrixf(model.m); - glh_set_current_modelview(model); - + + tmp_model *= mat; + model = tmp_model; return TRUE; } else @@ -1078,6 +1069,35 @@ BOOL setup_hud_matrices(const LLRect& screen_region) } } +bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model) +{ + LLRect whole_screen = get_whole_screen_region(); + return get_hud_matrices(whole_screen, proj, model); +} + +BOOL setup_hud_matrices() +{ + LLRect whole_screen = get_whole_screen_region(); + return setup_hud_matrices(whole_screen); +} + +BOOL setup_hud_matrices(const LLRect& screen_region) +{ + glh::matrix4f proj, model; + bool result = get_hud_matrices(screen_region, proj, model); + if (!result) return result; + + // set up transform to keep HUD objects in front of camera + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(proj.m); + glh_set_current_projection(proj); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(model.m); + glh_set_current_modelview(model); + return TRUE; +} + static LLFastTimer::DeclareTimer FTM_SWAP("Swap"); void render_ui(F32 zoom_factor, int subfield) diff --git a/indra/newview/llviewergenericmessage.h b/indra/newview/llviewergenericmessage.h index 6e1f0945b8..6b0a2e5d81 100644 --- a/indra/newview/llviewergenericmessage.h +++ b/indra/newview/llviewergenericmessage.h @@ -36,6 +36,7 @@ class LLUUID; class LLDispatcher; +class LLMessageSystem; void send_generic_message(const std::string& method, diff --git a/indra/newview/llviewerhelp.cpp b/indra/newview/llviewerhelp.cpp index 297c0cc111..5af79b4fd3 100644 --- a/indra/newview/llviewerhelp.cpp +++ b/indra/newview/llviewerhelp.cpp @@ -49,26 +49,39 @@ void LLViewerHelp::showTopic(const std::string &topic) { - showHelp(); - // allow overriding the help server with a local help file if( gSavedSettings.getBOOL("HelpUseLocal") ) { + showHelp(); LLFloaterHelpBrowser* helpbrowser = dynamic_cast<LLFloaterHelpBrowser*>(LLFloaterReg::getInstance("help_browser")); helpbrowser->navigateToLocalPage( "help-offline" , "index.html" ); return; } - // use a special login topic before the user logs in + // if the help topic is empty, use the default topic std::string help_topic = topic; - if (! LLLoginInstance::getInstance()->authSuccess()) + if (help_topic.empty()) { - help_topic = preLoginTopic(); + help_topic = defaultTopic(); + } + + // f1 help topic means: if user not logged in yet, show the + // pre-login topic, otherwise show help for the focused item + if (help_topic == f1HelpTopic()) + { + if (! LLLoginInstance::getInstance()->authSuccess()) + { + help_topic = preLoginTopic(); + } + else + { + help_topic = getTopicFromFocus(); + } } // work out the URL for this topic and display it - const LLOSInfo& osinfo = LLAppViewer::instance()->getOSInfo(); - std::string helpURL = LLViewerHelpUtil::buildHelpURL( help_topic, gSavedSettings, osinfo ); + showHelp(); + std::string helpURL = LLViewerHelpUtil::buildHelpURL( help_topic ); setRawURL( helpURL ); } @@ -84,6 +97,12 @@ std::string LLViewerHelp::preLoginTopic() return "pre_login_help"; } +std::string LLViewerHelp::f1HelpTopic() +{ + // *hack: to be done properly + return "f1_help"; +} + ////////////////////////////// // our own interfaces diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h index dcb5ae32c9..07971a593e 100644 --- a/indra/newview/llviewerhelp.h +++ b/indra/newview/llviewerhelp.h @@ -51,14 +51,17 @@ class LLViewerHelp : public LLHelp, public LLSingleton<LLViewerHelp> /// display the specified help topic in the help viewer /*virtual*/ void showTopic(const std::string &topic); - /// return default (fallback) topic name suitable for showTopic() - /*virtual*/ std::string defaultTopic(); - // return topic derived from viewer UI focus, else default topic std::string getTopicFromFocus(); + /// return default (fallback) topic name suitable for showTopic() + /*virtual*/ std::string defaultTopic(); + // return topic to use before the user logs in - std::string preLoginTopic(); + /*virtual*/ std::string preLoginTopic(); + + // return topic to use for the top-level help, invoked by F1 + /*virtual*/ std::string f1HelpTopic(); private: static void showHelp(); // make sure help UI is visible & raised diff --git a/indra/newview/llviewerhelputil.cpp b/indra/newview/llviewerhelputil.cpp index df08470518..5ba4fc834c 100644 --- a/indra/newview/llviewerhelputil.cpp +++ b/indra/newview/llviewerhelputil.cpp @@ -34,12 +34,11 @@ #include "llviewerprecompiledheaders.h" #include "llviewerhelputil.h" -#include "llcontrol.h" +#include "llsd.h" #include "llstring.h" -#include "llsys.h" #include "lluri.h" -#include "llversioninfo.h" - +#include "llweb.h" +#include "llviewercontrol.h" ////////////////////////////////////////////// // Build a help URL from a topic and formatter @@ -59,40 +58,14 @@ std::string LLViewerHelpUtil::helpURLEncode( const std::string &component ) return escaped; } -static std::string buildHelpVersion( const U32 ver_int ) -{ - std::ostringstream ver_str; - ver_str << ver_int; - return ver_str.str(); // not encoded - numbers are rfc3986-safe -} - //static -std::string LLViewerHelpUtil::buildHelpURL( const std::string &topic, - LLControlGroup &savedSettings, - const LLOSInfo &osinfo ) +std::string LLViewerHelpUtil::buildHelpURL( const std::string &topic) { - std::string helpURL = savedSettings.getString("HelpURLFormat"); LLSD substitution; substitution["TOPIC"] = helpURLEncode(topic); - substitution["CHANNEL"] = helpURLEncode(savedSettings.getString("VersionChannelName")); - - substitution["VERSION"] = helpURLEncode(LLVersionInfo::getVersion()); - substitution["VERSION_MAJOR"] = buildHelpVersion(LLVersionInfo::getMajor()); - substitution["VERSION_MINOR"] = buildHelpVersion(LLVersionInfo::getMinor()); - substitution["VERSION_PATCH"] = buildHelpVersion(LLVersionInfo::getPatch()); - substitution["VERSION_BUILD"] = buildHelpVersion(LLVersionInfo::getBuild()); - - substitution["OS"] = helpURLEncode(osinfo.getOSStringSimple()); - - std::string language = savedSettings.getString("Language"); - if( language.empty() || language == "default" ) - { - language = savedSettings.getString("SystemLanguage"); - } - substitution["LANGUAGE"] = helpURLEncode(language); - - LLStringUtil::format(helpURL, substitution); - - return helpURL; + // get the help URL and expand all of the substitutions + // (also adds things like [LANGUAGE], [VERSION], [OS], etc.) + std::string helpURL = gSavedSettings.getString("HelpURLFormat"); + return LLWeb::expandURLSubstitutions(helpURL, substitution); } diff --git a/indra/newview/llviewerhelputil.h b/indra/newview/llviewerhelputil.h index 8ee0d96023..95e6744842 100644 --- a/indra/newview/llviewerhelputil.h +++ b/indra/newview/llviewerhelputil.h @@ -41,9 +41,7 @@ class LLViewerHelpUtil { public: static std::string helpURLEncode( const std::string &component ); - static std::string buildHelpURL( const std::string &topic, - LLControlGroup &savedSettings, - const LLOSInfo &osinfo); + static std::string buildHelpURL( const std::string &topic ); }; #endif // header guard diff --git a/indra/newview/llviewerhome.cpp b/indra/newview/llviewerhome.cpp index 58630978c4..6299b4fabd 100644 --- a/indra/newview/llviewerhome.cpp +++ b/indra/newview/llviewerhome.cpp @@ -35,12 +35,11 @@ #include "llviewerhome.h" #include "lllogininstance.h" +#include "llsd.h" #include "llui.h" #include "lluri.h" -#include "llsd.h" -#include "llversioninfo.h" #include "llviewercontrol.h" -#include "llviewernetwork.h" +#include "llweb.h" //static std::string LLViewerHome::getHomeURL() @@ -49,16 +48,12 @@ std::string LLViewerHome::getHomeURL() // this value from settings.xml and support various substitutions LLSD substitution; - substitution["VERSION"] = LLVersionInfo::getVersion(); - substitution["CHANNEL"] = LLURI::escape(gSavedSettings.getString("VersionChannelName")); - substitution["LANGUAGE"] = LLUI::getLanguage(); - substitution["AUTH_KEY"] = LLURI::escape(getAuthKey()); - substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel(); + substitution["AUTH_TOKEN"] = LLURI::escape(getAuthKey()); + // get the home URL and expand all of the substitutions + // (also adds things like [LANGUAGE], [VERSION], [OS], etc.) std::string homeURL = gSavedSettings.getString("HomeSidePanelURL"); - LLStringUtil::format(homeURL, substitution); - - return homeURL; + return LLWeb::expandURLSubstitutions(homeURL, substitution); } //static @@ -67,7 +62,13 @@ std::string LLViewerHome::getAuthKey() // return the value of the (optional) auth token returned by login.cgi // this lets the server provide an authentication token that we can // blindly pass to the Home web page for it to perform authentication. - static const std::string authKeyName("home_sidetray_token"); - return LLLoginInstance::getInstance()->getResponse(authKeyName); + // We use "home_sidetray_token", and fallback to "auth_token" if not + // present. + LLSD auth_token = LLLoginInstance::getInstance()->getResponse("home_sidetray_token"); + if (auth_token.asString().empty()) + { + auth_token = LLLoginInstance::getInstance()->getResponse("auth_token"); + } + return auth_token.asString(); } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 9856cb2b7f..5605f425e0 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -43,7 +43,6 @@ #include "llviewercontrol.h" #include "llconsole.h" #include "llinventorymodel.h" -#include "llnotify.h" #include "llgesturemgr.h" #include "llinventorybridge.h" @@ -519,7 +518,7 @@ bool LLViewerInventoryCategory::fetchDescendents() std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); if (!url.empty()) //Capability found. Build up LLSD and use it. { - LLInventoryModel::startBackgroundFetch(mUUID); + gInventory.startBackgroundFetch(mUUID); } else { //Deprecated, but if we don't have a capability, use the old system. @@ -1379,6 +1378,25 @@ LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const return NULL; } +bool LLViewerInventoryItem::checkPermissionsSet(PermissionMask mask) const +{ + const LLPermissions& perm = getPermissions(); + PermissionMask curr_mask = PERM_NONE; + if(perm.getOwner() == gAgent.getID()) + { + curr_mask = perm.getMaskBase(); + } + else if(gAgent.isInGroup(perm.getGroup())) + { + curr_mask = perm.getMaskGroup(); + } + else + { + curr_mask = perm.getMaskEveryone(); + } + return ((curr_mask & mask) == mask); +} + //---------- void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 0156e7dab1..412a2c66e6 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -158,6 +158,9 @@ public: bool getIsBrokenLink() const; // true if the baseitem this points to doesn't exist in memory. LLViewerInventoryItem *getLinkedItem() const; LLViewerInventoryCategory *getLinkedCategory() const; + + // Checks the items permissions (for owner, group, or everyone) and returns true if all mask bits are set. + bool checkPermissionsSet(PermissionMask mask) const; // callback void onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name); diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h index 0e993a2ebe..08c4ec36fd 100644 --- a/indra/newview/llviewerjoint.h +++ b/indra/newview/llviewerjoint.h @@ -37,7 +37,6 @@ // Header Files //----------------------------------------------------------------------------- #include "lljoint.h" -#include "llapr.h" class LLFace; class LLViewerJointMesh; diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index 543679c44b..d62b0ada85 100644 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -37,7 +37,6 @@ #include "llviewertexture.h" #include "llpolymesh.h" #include "v4color.h" -#include "llapr.h" class LLDrawable; class LLFace; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index ef8f63484e..103a70e032 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -172,6 +172,11 @@ public: completeAny(status, "text/html"); } else + if(status == 403) + { + completeAny(status, "text/html"); + } + else if(status == 404) { // 404 is content not found - sites often have bespoke 404 pages so @@ -240,9 +245,11 @@ public: bool mInitialized; }; static LLViewerMedia::impl_list sViewerMediaImplList; +static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap; static LLTimer sMediaCreateTimer; static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f; static F32 sGlobalVolume = 1.0f; +static F64 sLowestLoadableImplInterest = 0.0f; ////////////////////////////////////////////////////////////////////////////////////////// static void add_media_impl(LLViewerMediaImpl* media) @@ -297,7 +304,7 @@ viewer_media_t LLViewerMedia::newMediaImpl( else { media_impl->unload(); - media_impl->mTextureId = texture_id; + media_impl->setTextureID(texture_id); media_impl->mMediaWidth = media_width; media_impl->mMediaHeight = media_height; media_impl->mMediaAutoScale = media_auto_scale; @@ -412,18 +419,16 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s // static LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id) { - impl_list::iterator iter = sViewerMediaImplList.begin(); - impl_list::iterator end = sViewerMediaImplList.end(); - - for(; iter != end; iter++) + LLViewerMediaImpl* result = NULL; + + // Look up the texture ID in the texture id->impl map. + impl_id_map::iterator iter = sViewerMediaTextureIDMap.find(texture_id); + if(iter != sViewerMediaTextureIDMap.end()) { - LLViewerMediaImpl* media_impl = *iter; - if(media_impl->getMediaTextureID() == texture_id) - { - return media_impl; - } + result = iter->second; } - return NULL; + + return result; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -554,6 +559,37 @@ bool LLViewerMedia::getInWorldMediaDisabled() return sInWorldMediaDisabled; } +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest) +{ + bool result = false; + + if (NULL == object) + { + result = false; + } + // Focused? Then it is interesting! + else if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == object->getID()) + { + result = true; + } + // Selected? Then it is interesting! + // XXX Sadly, 'contains()' doesn't take a const :( + else if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(object))) + { + result = true; + } + else + { + llinfos << "object interest = " << object_interest << ", lowest loadable = " << sLowestLoadableImplInterest << llendl; + if(object_interest > sLowestLoadableImplInterest) + result = true; + } + + return result; +} + LLViewerMedia::impl_list &LLViewerMedia::getPriorityList() { return sViewerMediaImplList; @@ -626,7 +662,22 @@ bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLView static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2) { - return (i1->getProximityDistance() < i2->getProximityDistance()); + if(i1->getProximityDistance() < i2->getProximityDistance()) + { + return true; + } + else if(i1->getProximityDistance() > i2->getProximityDistance()) + { + return false; + } + else + { + // Both objects have the same distance. This most likely means they're two faces of the same object. + // They may also be faces on different objects with exactly the same distance (like HUD objects). + // We don't actually care what the sort order is for this case, as long as it's stable and doesn't change when you enable/disable media. + // Comparing the impl pointers gives a completely arbitrary ordering, but it will be stable. + return (i1 < i2); + } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -664,6 +715,8 @@ void LLViewerMedia::updateMedia(void *dummy_arg) // Setting max_cpu to 0.0 disables CPU usage checking. bool check_cpu_usage = (max_cpu != 0.0f); + LLViewerMediaImpl* lowest_interest_loadable = NULL; + // Notes on tweakable params: // max_instances must be set high enough to allow the various instances used in the UI (for the help browser, search, etc.) to be loaded. // If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow. @@ -750,6 +803,9 @@ void LLViewerMedia::updateMedia(void *dummy_arg) if(!pimpl->getUsedInUI() && (new_priority != LLPluginClassMedia::PRIORITY_UNLOADED)) { + // This is a loadable inworld impl -- the last one in the list in this class defines the lowest loadable interest. + lowest_interest_loadable = pimpl; + impl_count_total++; } @@ -780,6 +836,22 @@ void LLViewerMedia::updateMedia(void *dummy_arg) total_cpu += pimpl->getCPUUsage(); } + + // Re-calculate this every time. + sLowestLoadableImplInterest = 0.0f; + + // Only do this calculation if we've hit the impl count limit -- up until that point we always need to load media data. + if(lowest_interest_loadable && (impl_count_total >= (int)max_instances)) + { + // Get the interest value of this impl's object for use by isInterestingEnough + LLVOVolume *object = lowest_interest_loadable->getSomeObject(); + if(object) + { + // NOTE: Don't use getMediaInterest() here. We want the pixel area, not the total media interest, + // so that we match up with the calculation done in LLMediaDataClient. + sLowestLoadableImplInterest = object->getPixelArea(); + } + } if(gSavedSettings.getBOOL("MediaPerformanceManagerDebug")) { @@ -827,7 +899,6 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, : mMediaSource( NULL ), mMovieImageHasMips(false), - mTextureId(texture_id), mMediaWidth(media_width), mMediaHeight(media_height), mMediaAutoScale(media_auto_scale), @@ -857,6 +928,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mProximityDistance(0.0f), mMimeTypeProbe(NULL), mMediaAutoPlay(false), + mInNearbyMediaList(false), mIsUpdated(false) { @@ -868,6 +940,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, } add_media_impl(this); + + setTextureID(texture_id); // connect this media_impl to the media texture, creating it if it doesn't exist.0 // This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded. @@ -891,6 +965,7 @@ LLViewerMediaImpl::~LLViewerMediaImpl() LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ; + setTextureID(); remove_media_impl(this); } @@ -2421,6 +2496,26 @@ LLVOVolume *LLViewerMediaImpl::getSomeObject() return result; } +void LLViewerMediaImpl::setTextureID(LLUUID id) +{ + if(id != mTextureId) + { + if(mTextureId.notNull()) + { + // Remove this item's entry from the map + sViewerMediaTextureIDMap.erase(mTextureId); + } + + if(id.notNull()) + { + sViewerMediaTextureIDMap.insert(LLViewerMedia::impl_id_map::value_type(id, this)); + } + + mTextureId = id; + } +} + + ////////////////////////////////////////////////////////////////////////////////////////// //static void LLViewerMedia::toggleMusicPlay(void*) diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 713eb2710b..7151186089 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -79,6 +79,8 @@ class LLViewerMedia typedef std::vector<LLViewerMediaImpl*> impl_list; + typedef std::map<LLUUID, LLViewerMediaImpl*> impl_id_map; + // Special case early init for just web browser component // so we can show login screen. See .cpp file for details. JC @@ -110,6 +112,8 @@ class LLViewerMedia static void setInWorldMediaDisabled(bool disabled); static bool getInWorldMediaDisabled(); + static bool isInterestingEnough(const LLVOVolume* object, const F64 &object_interest); + // Returns the priority-sorted list of all media impls. static impl_list &getPriorityList(); @@ -287,6 +291,8 @@ public: LLPluginClassMedia::EPriority getPriority() { return mPriority; }; void setLowPrioritySizeLimit(int size); + + void setTextureID(LLUUID id = LLUUID::null); typedef enum { @@ -348,6 +354,7 @@ public: LLMimeDiscoveryResponder *mMimeTypeProbe; bool mMediaAutoPlay; std::string mMediaEntryURL; + bool mInNearbyMediaList; // used by LLFloaterNearbyMedia::refreshList() for performance reasons private: BOOL mIsUpdated ; diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index f639c841e7..e04a54fbd6 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -144,9 +144,19 @@ void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 fac } mFocusedImplID = LLUUID::null; - mFocusedObjectID = LLUUID::null; - mFocusedObjectFace = 0; + if (objectp.notNull()) + { + // Still record the focused object...it may mean we need to load media data. + // This will aid us in determining this object is "important enough" + mFocusedObjectID = objectp->getID(); + mFocusedObjectFace = face; + } + else { + mFocusedObjectID = LLUUID::null; + mFocusedObjectFace = 0; + } } + } void LLViewerMediaFocus::clearFocus() @@ -336,7 +346,7 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks) void LLViewerMediaFocus::update() { - if(mFocusedImplID.notNull() || mFocusedObjectID.notNull()) + if(mFocusedImplID.notNull()) { // We have a focused impl/face. if(!getFocus()) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 78322dda75..dfa775c292 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -59,6 +59,7 @@ #include "llfloaterland.h" #include "llfloaterpay.h" #include "llfloaterreporter.h" +#include "llfloatersearch.h" #include "llfloaterscriptdebug.h" #include "llfloatertools.h" #include "llfloaterworldmap.h" @@ -133,11 +134,12 @@ LLMenuGL *gPopupMenuView = NULL; LLMenuBarGL *gLoginMenuBarView = NULL; // Pie menus -LLContextMenu *gPieSelf = NULL; -LLContextMenu *gPieAvatar = NULL; -LLContextMenu *gPieObject = NULL; -LLContextMenu *gPieAttachment = NULL; -LLContextMenu *gPieLand = NULL; +LLContextMenu *gMenuAvatarSelf = NULL; +LLContextMenu *gMenuAvatarOther = NULL; +LLContextMenu *gMenuObject = NULL; +LLContextMenu *gMenuAttachmentSelf = NULL; +LLContextMenu *gMenuAttachmentOther = NULL; +LLContextMenu *gMenuLand = NULL; const std::string SAVE_INTO_INVENTORY("Save Object Back to My Inventory"); const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents"); @@ -145,7 +147,6 @@ const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents" LLMenuGL* gAttachSubMenu = NULL; LLMenuGL* gDetachSubMenu = NULL; LLMenuGL* gTakeOffClothes = NULL; -LLContextMenu* gPieRate = NULL; LLContextMenu* gAttachScreenPieMenu = NULL; LLContextMenu* gAttachPieMenu = NULL; LLContextMenu* gAttachBodyPartPieMenus[8]; @@ -375,25 +376,31 @@ void init_menus() gMenuHolder->addChild( gPopupMenuView ); /// - /// Pie menus + /// Context menus /// - gPieSelf = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_self.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + const widget_registry_t& registry = + LLViewerMenuHolderGL::child_registry_t::instance(); + gMenuAvatarSelf = LLUICtrlFactory::createFromFile<LLContextMenu>( + "menu_avatar_self.xml", gMenuHolder, registry); + gMenuAvatarOther = LLUICtrlFactory::createFromFile<LLContextMenu>( + "menu_avatar_other.xml", gMenuHolder, registry); - // TomY TODO: what shall we do about these? gDetachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach HUD", true); gDetachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach", true); - gPieAvatar = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_avatar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - - gPieObject = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_object.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + gMenuObject = LLUICtrlFactory::createFromFile<LLContextMenu>( + "menu_object.xml", gMenuHolder, registry); gAttachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach HUD"); gAttachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach"); - gPieRate = gMenuHolder->getChild<LLContextMenu>("Rate Menu"); - gPieAttachment = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_attachment.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + gMenuAttachmentSelf = LLUICtrlFactory::createFromFile<LLContextMenu>( + "menu_attachment_self.xml", gMenuHolder, registry); + gMenuAttachmentOther = LLUICtrlFactory::createFromFile<LLContextMenu>( + "menu_attachment_other.xml", gMenuHolder, registry); - gPieLand = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_land.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + gMenuLand = LLUICtrlFactory::createFromFile<LLContextMenu>( + "menu_land.xml", gMenuHolder, registry); /// /// set up the colors @@ -402,12 +409,13 @@ void init_menus() LLColor4 context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor"); - gPieSelf->setBackgroundColor( context_menu_color ); - gPieAvatar->setBackgroundColor( context_menu_color ); - gPieObject->setBackgroundColor( context_menu_color ); - gPieAttachment->setBackgroundColor( context_menu_color ); + gMenuAvatarSelf->setBackgroundColor( context_menu_color ); + gMenuAvatarOther->setBackgroundColor( context_menu_color ); + gMenuObject->setBackgroundColor( context_menu_color ); + gMenuAttachmentSelf->setBackgroundColor( context_menu_color ); + gMenuAttachmentOther->setBackgroundColor( context_menu_color ); - gPieLand->setBackgroundColor( context_menu_color ); + gMenuLand->setBackgroundColor( context_menu_color ); color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" ); gPopupMenuView->setBackgroundColor( color ); @@ -2262,20 +2270,23 @@ void cleanup_menus() delete gMenuParcelObserver; gMenuParcelObserver = NULL; - delete gPieSelf; - gPieSelf = NULL; + delete gMenuAvatarSelf; + gMenuAvatarSelf = NULL; + + delete gMenuAvatarOther; + gMenuAvatarOther = NULL; - delete gPieAvatar; - gPieAvatar = NULL; + delete gMenuObject; + gMenuObject = NULL; - delete gPieObject; - gPieObject = NULL; + delete gMenuAttachmentSelf; + gMenuAttachmentSelf = NULL; - delete gPieAttachment; - gPieAttachment = NULL; + delete gMenuAttachmentOther; + gMenuAttachmentSelf = NULL; - delete gPieLand; - gPieLand = NULL; + delete gMenuLand; + gMenuLand = NULL; delete gMenuBarView; gMenuBarView = NULL; @@ -2518,8 +2529,6 @@ void handle_object_edit() void handle_object_inspect() { - // Disable sidepanel inspector - /* LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); LLViewerObject* selected_objectp = selection->getFirstRootObject(); if (selected_objectp) @@ -2528,9 +2537,11 @@ void handle_object_inspect() key["task"] = "task"; LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); } - */ + /* + // Old floater properties LLFloaterReg::showInstance("inspect", LLSD()); + */ } //--------------------------------------------------------------------------- @@ -3408,6 +3419,13 @@ void set_god_level(U8 god_level) // changing god-level can affect which menus we see show_debug_menus(); + + // changing god-level can invalidate search results + LLFloaterSearch *search = dynamic_cast<LLFloaterSearch*>(LLFloaterReg::getInstance("search")); + if (search) + { + search->godLevelChanged(god_level); + } } #ifdef TOGGLE_HACKED_GODLIKE_VIEWER @@ -4903,7 +4921,7 @@ class LLEditDelete : public view_listener_t // When deleting an object we may not actually be done // Keep selection so we know what to delete when confirmation is needed about the delete - gPieObject->hide(); + gMenuObject->hide(); return true; } }; @@ -4936,7 +4954,7 @@ void handle_object_delete() // When deleting an object we may not actually be done // Keep selection so we know what to delete when confirmation is needed about the delete - gPieObject->hide(); + gMenuObject->hide(); return; } @@ -5567,17 +5585,8 @@ class LLShowHelp : public view_listener_t bool handleEvent(const LLSD& userdata) { std::string help_topic = userdata.asString(); - LLViewerHelp* vhelp = LLViewerHelp::getInstance(); - if (help_topic.empty()) - { - vhelp->showTopic(vhelp->getTopicFromFocus()); - } - else - { - vhelp->showTopic(help_topic); - } - + vhelp->showTopic(help_topic); return true; } }; @@ -6007,7 +6016,7 @@ public: protected: virtual void done() { - gPieAttachment->buildDrawLabels(); + gMenuAttachmentSelf->buildDrawLabels(); gInventory.removeObserver(this); delete this; } diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 01a6b34170..d3c34f0de4 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -36,6 +36,7 @@ #include "llmenugl.h" #include "llsafehandle.h" +class LLMessageSystem; class LLSD; class LLUICtrl; class LLView; @@ -160,21 +161,13 @@ extern LLMenuGL* gPopupMenuView; extern LLViewerMenuHolderGL* gMenuHolder; extern LLMenuBarGL* gLoginMenuBarView; -// Pie menus -extern LLContextMenu *gPieSelf; -extern LLContextMenu *gPieAvatar; -extern LLContextMenu *gPieObject; -extern LLContextMenu *gPieAttachment; - -extern LLContextMenu *gPieLand; -extern LLContextMenu *gPieRate; - -// Pie menus -extern LLContextMenu *gPieSelfSimple; -extern LLContextMenu *gPieAvatarSimple; -extern LLContextMenu *gPieObjectSimple; -extern LLContextMenu *gPieAttachmentSimple; -extern LLContextMenu *gPieLandSimple; +// Context menus in 3D scene +extern LLContextMenu *gMenuAvatarSelf; +extern LLContextMenu *gMenuAvatarOther; +extern LLContextMenu *gMenuObject; +extern LLContextMenu *gMenuAttachmentSelf; +extern LLContextMenu *gMenuAttachmentOther; +extern LLContextMenu *gMenuLand; // Needed to build menus when attachment site list available extern LLMenuGL* gAttachSubMenu; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 4b0dc8f668..48794bbc1a 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -40,6 +40,12 @@ #include "llfloaterreg.h" #include "llfloaterbuycurrency.h" #include "llfloatersnapshot.h" +#include "llimage.h"
+#include "llimagebmp.h"
+#include "llimagepng.h"
+#include "llimagej2c.h"
+#include "llimagejpeg.h"
+#include "llimagetga.h"
#include "llinventorymodel.h" // gInventory #include "llresourcedata.h" #include "llfloaterperms.h" @@ -47,6 +53,8 @@ #include "llviewercontrol.h" // gSavedSettings #include "llviewertexturelist.h" #include "lluictrlfactory.h" +#include "llvfile.h" +#include "llvfs.h" #include "llviewerinventory.h" #include "llviewermenu.h" // gMenuHolder #include "llviewerregion.h" @@ -67,19 +75,11 @@ #include "lltransactiontypes.h" #include "lluuid.h" #include "llvorbisencode.h" +#include "message.h" // system libraries #include <boost/tokenizer.hpp> -class LLFileEnableSaveAs : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - bool new_value = gFloaterView->getFrontmost() && gFloaterView->getFrontmost()->canSaveAs(); - return new_value; - } -}; - class LLFileEnableUpload : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -386,19 +386,6 @@ class LLFileCloseAllWindows : public view_listener_t } }; -class LLFileSaveTexture : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLFloater* top = gFloaterView->getFrontmost(); - if (top) - { - top->saveAs(); - } - return true; - } -}; - class LLFileTakeSnapshotToDisk : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -1050,10 +1037,10 @@ void init_menu_file() view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows"); view_listener_t::addEnable(new LLFileEnableCloseWindow(), "File.EnableCloseWindow"); view_listener_t::addEnable(new LLFileEnableCloseAllWindows(), "File.EnableCloseAllWindows"); - view_listener_t::addCommit(new LLFileSaveTexture(), "File.SaveTexture"); view_listener_t::addCommit(new LLFileTakeSnapshotToDisk(), "File.TakeSnapshotToDisk"); view_listener_t::addCommit(new LLFileQuit(), "File.Quit"); view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload"); - view_listener_t::addEnable(new LLFileEnableSaveAs(), "File.EnableSaveAs"); + + // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled. } diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index da78537a29..1e6d13f1c6 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -34,6 +34,7 @@ #define LLVIEWERMENUFILE_H #include "llfoldertype.h" +#include "llassetstorage.h" #include "llinventorytype.h" class LLTransactionID; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8c0529e344..ea40f2aae1 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -38,8 +38,14 @@ #include "lleconomy.h" #include "llfloaterreg.h" #include "llfollowcamparams.h" +#include "llregionhandle.h" #include "llsdserialize.h" +#include "llteleportflags.h" #include "lltransactionflags.h" +#include "llvfile.h" +#include "llvfs.h" +#include "llxfermanager.h" +#include "mean_collision_data.h" #include "llagent.h" #include "llcallingcard.h" @@ -59,7 +65,6 @@ #include "llnearbychat.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llpanelgrouplandmoney.h" #include "llpanelplaces.h" #include "llrecentpeople.h" @@ -926,34 +931,40 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f void inventory_offer_mute_callback(const LLUUID& blocked_id, const std::string& first_name, const std::string& last_name, - BOOL is_group) + BOOL is_group, LLOfferInfo* offer = NULL) { std::string from_name; LLMute::EType type; - if (is_group) { type = LLMute::GROUP; from_name = first_name; } + else if(offer && offer->mFromObject) + { + //we have to block object by name because blocked_id is an id of owner + type = LLMute::BY_NAME; + from_name = offer->mFromName; + } else { type = LLMute::AGENT; from_name = first_name + " " + last_name; } - LLMute mute(blocked_id, from_name, type); + // id should be null for BY_NAME mute, see LLMuteList::add for details + LLMute mute(type == LLMute::BY_NAME ? LLUUID::null : blocked_id, from_name, type); if (LLMuteList::getInstance()->add(mute)) { LLPanelBlockedList::showPanelAndSelect(blocked_id); } // purge the message queue of any previously queued inventory offers from the same source. - class OfferMatcher : public LLNotifyBoxView::Matcher + class OfferMatcher : public LLNotificationsUI::LLScreenChannel::Matcher { public: OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {} - BOOL matches(const LLNotificationPtr notification) const + bool matches(const LLNotificationPtr notification) const { if(notification->getName() == "ObjectGiveItem" || notification->getName() == "ObjectGiveItemUnknownUser" @@ -966,7 +977,9 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, private: const LLUUID& blocked_id; }; - gNotifyBoxView->purgeMessagesMatching(OfferMatcher(blocked_id)); + + LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID( + gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(blocked_id)); } LLOfferInfo::LLOfferInfo(const LLSD& sd) @@ -1062,7 +1075,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // * we can't build two messages at once. if (2 == button) { - gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback); + gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this)); } std::string from_string; // Used in the pop-up. @@ -1196,7 +1209,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const // * we can't build two messages at once. if (2 == button) { - gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback); + gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this)); } LLMessageSystem* msg = gMessageSystem; @@ -1473,6 +1486,8 @@ void inventory_offer_handler(LLOfferInfo* info) // Note: sets inventory_task_offer_callback as the callback p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_task_offer_callback, info, _1, _2)); p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser"; + // Pop up inv offer chiclet and let the user accept (keep), or reject (and silently delete) the inventory. + LLNotifications::instance().add(p); } else // Agent -> Agent Inventory Offer { @@ -1496,18 +1511,14 @@ void inventory_offer_handler(LLOfferInfo* info) // In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages). info->send_auto_receive_response(); - } - - // Pop up inv offer notification and let the user accept (keep), or reject (and silently delete) the inventory. - LLNotifications::instance().add(p); - // TODO(EM): Recheck this after we will know how script notifications should look like. - // Inform user that there is a script floater via toast system - // { - // payload["give_inventory_notification"] = TRUE; - // LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload)); - // LLScriptFloaterManager::getInstance()->setNotificationToastId(object_id, notification->getID()); - // } + // Inform user that there is a script floater via toast system + { + payload["give_inventory_notification"] = TRUE; + LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload)); + LLScriptFloaterManager::getInstance()->setNotificationToastId(object_id, notification->getID()); + } + } } bool lure_callback(const LLSD& notification, const LLSD& response) @@ -2096,8 +2107,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLSD payload; payload["object_id"] = session_id; payload["owner_id"] = from_id; + payload["from_id"] = from_id; payload["slurl"] = location; payload["name"] = name; + std::string session_name; + gCacheName->getFullName(from_id, session_name); + payload["SESSION_NAME"] = session_name; if (from_group) { payload["groupowned"] = "true"; @@ -4827,24 +4842,25 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) LLMuteList::getInstance()->add(LLMute(item_id, notification["payload"]["object_name"].asString(), LLMute::OBJECT)); // purge the message queue of any previously queued requests from the same source. DEV-4879 - class OfferMatcher : public LLNotifyBoxView::Matcher + class OfferMatcher : public LLNotificationsUI::LLScreenChannel::Matcher { public: OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {} - BOOL matches(const LLNotificationPtr notification) const + bool matches(const LLNotificationPtr notification) const { if (notification->getName() == "ScriptQuestionCaution" || notification->getName() == "ScriptQuestion") { return (notification->getPayload()["item_id"].asUUID() == blocked_id); } - return FALSE; + return false; } private: const LLUUID& blocked_id; }; - // should do this via the channel - gNotifyBoxView->purgeMessagesMatching(OfferMatcher(item_id)); + + LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID( + gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(item_id)); } if (response["Details"]) @@ -5288,6 +5304,7 @@ void send_group_notice(const LLUUID& group_id, bool handle_lure_callback(const LLSD& notification, const LLSD& response) { std::string text = response["message"].asString(); + text.append("\r\n").append(LLAgentUI::buildSLURL()); S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(0 == option) diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 1a98828010..8404d6fde0 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -33,10 +33,12 @@ #ifndef LL_LLVIEWERMESSAGE_H #define LL_LLVIEWERMESSAGE_H +#include "llassettype.h" #include "llinstantmessage.h" #include "llpointer.h" #include "lltransactiontypes.h" #include "lluuid.h" +#include "message.h" #include "stdenums.h" // @@ -47,6 +49,7 @@ class LLInventoryObject; class LLInventoryItem; class LLMeanCollisionData; class LLMessageSystem; +class LLVFS; class LLViewerObject; class LLViewerRegion; diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 801c46035a..d7b55d7e97 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -34,8 +34,11 @@ #include "llviewerprecompiledheaders.h" #include "llviewernetwork.h" -#include "llviewercontrol.h" + #include "llevents.h" +#include "net.h" + +#include "llviewercontrol.h" #include "lllogin.h" struct LLGridData diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 2fae78cdfb..be68a2ef42 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -54,7 +54,6 @@ #include "llfloatergroups.h" #include "llfloatersellland.h" #include "llfloatertools.h" -#include "llnotify.h" #include "llparcelselection.h" #include "llresmgr.h" #include "llsdutil.h" @@ -2525,7 +2524,8 @@ boost::signals2::connection LLViewerParcelMgr::setTeleportFailedCallback(parcel_ */ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos) { - if (local) + // Treat only teleports within the same parcel as local (EXT-3139). + if (local && LLViewerParcelMgr::getInstance()->inAgentParcel(new_pos)) { // Local teleport. We already have the agent parcel data. // Emit the signal immediately. @@ -2533,7 +2533,7 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos } else { - // Non-local teleport. + // Non-local teleport (inter-region or between different parcels of the same region). // The agent parcel data has not been updated yet. // Let's wait for the update and then emit the signal. mTeleportInProgress = TRUE; diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index 6a0ad5757f..50f905416c 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -41,17 +41,6 @@ #include "linden_common.h" -// We may want to take the windows.h include out, but it used to be in -// linden_common.h, and hence in all the libraries. This is better. JC -#if LL_WINDOWS - // Limit Windows API to small and manageable set. - // If you get undefined symbols, find the appropriate - // Windows header file and include that in your .cpp file. - #define WIN32_LEAN_AND_MEAN - #include <winsock2.h> - #include <windows.h> -#endif - // Work around stupid Microsoft STL warning #ifdef LL_WINDOWS #pragma warning (disable : 4702) // warning C4702: unreachable code @@ -76,21 +65,14 @@ //#include "llpreprocessor.h" #include "llallocator.h" #include "llapp.h" -#include "llapr.h" #include "llcriticaldamp.h" -//#include "lldarray.h" -//#include "lldarrayptr.h" #include "lldefs.h" #include "lldepthstack.h" -//#include "lldqueueptr.h" -#include "llendianswizzle.h" #include "llerror.h" #include "llfasttimer.h" #include "llframetimer.h" #include "llhash.h" #include "lllocalidhashmap.h" -#include "llmap.h" -//#include "llmemory.h" #include "llnametable.h" #include "llpointer.h" #include "llpriqueuemap.h" @@ -100,7 +82,6 @@ //#include "llsecondlifeurls.h" #include "llsd.h" #include "llsingleton.h" -#include "llstack.h" #include "llstat.h" #include "llstl.h" #include "llstrider.h" @@ -117,19 +98,7 @@ #include "timing.h" #include "u64.h" -// Library includes from llimage -//#include "llblockdata.h" -#include "llimage.h" -#include "llimagebmp.h" -#include "llimagepng.h" -#include "llimagej2c.h" -#include "llimagejpeg.h" -#include "llimagetga.h" -#include "llmapimagetype.h" - // Library includes from llmath project -//#include "camera.h" -//#include "coordframe.h" #include "llmath.h" #include "llbboxlocal.h" #include "llcamera.h" @@ -157,80 +126,11 @@ ////#include "vmath.h" #include "xform.h" -// Library includes from llmessage project -//#include "llassetstorage.h" -#include "llcachename.h" -#include "llcircuit.h" -#include "lldatapacker.h" -#include "lldbstrings.h" -#include "lldispatcher.h" -#include "lleventflags.h" -#include "llhost.h" -#include "llinstantmessage.h" -#include "llinvite.h" -//#include "llloginflags.h" -#include "llmail.h" -#include "llmessagethrottle.h" -#include "llnamevalue.h" -#include "llpacketack.h" -#include "llpacketbuffer.h" -#include "llpacketring.h" -#include "llpartdata.h" -//#include "llqueryflags.h" -//#include "llregionflags.h" -#include "llregionhandle.h" -#include "lltaskname.h" -#include "llteleportflags.h" -#include "llthrottle.h" -#include "lltransfermanager.h" -#include "lltransfersourceasset.h" -#include "lltransfersourcefile.h" -#include "lltransfertargetfile.h" -#include "lltransfertargetvfile.h" -#include "lluseroperation.h" -#include "llvehicleparams.h" -#include "llxfer.h" -#include "llxfer_file.h" -#include "llxfer_mem.h" -#include "llxfer_vfile.h" -#include "llxfermanager.h" -#include "machine.h" -#include "mean_collision_data.h" -#include "message.h" -#include "message_prehash.h" -#include "net.h" -//#include "network.h" -#include "partsyspacket.h" -#include "patch_code.h" -#include "patch_dct.h" -#include "sound_ids.h" - -// Builds work with all headers below commented out as of 2009-09-10 JC - -// Library includes from llprimitive -#include "imageids.h" -#include "legacy_object_types.h" -#include "llmaterialtable.h" -//#include "llprimitive.h" -#include "lltextureanim.h" -//#include "lltextureentry.h" -#include "lltreeparams.h" -//#include "llvolume.h" -#include "llvolumemgr.h" -#include "material_codes.h" - // Library includes from llvfs -#include "llassettype.h" #include "lldir.h" -//#include "lldir_linux.h" -//#include "lldir_mac.h" -//#include "lldir_win32.h" -#include "llvfile.h" -#include "llvfs.h" -// Library includes from llui -// In skinning-7, llui.h dependencies are changing too often. -//#include "llui.h" +// Library includes from llmessage project +#include "llcachename.h" // llxuixml #include "llinitparam.h" diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 939d5e3970..a1a3bc6d6a 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -39,6 +39,7 @@ #include "llfloaterreg.h" #include "llmemory.h" #include "lltimer.h" +#include "llvfile.h" #include "llappviewer.h" diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index e0091145ce..300aea1620 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -51,7 +51,6 @@ #include "llmenugl.h" #include "llnotecard.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llpanelplaces.h" #include "llpreview.h" #include "llpreviewnotecard.h" diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 0d29efaedf..b45148a186 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -108,6 +108,19 @@ const F64 log_2 = log(2.0); //---------------------------------------------------------------------------------------------- //namespace: LLViewerTextureAccess //---------------------------------------------------------------------------------------------- + +LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb, + S32 discard_level, + BOOL need_imageraw, // Needs image raw for the callback + void* userdata ) + : mCallback(cb), + mLastUsedDiscard(MAX_DISCARD_LEVEL+1), + mDesiredDiscard(discard_level), + mNeedsImageRaw(need_imageraw), + mUserData(userdata) +{ +} + LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &media_id, BOOL usemipmaps, LLImageGL* gl_image) { return new LLViewerMediaTexture(media_id, usemipmaps, gl_image) ; @@ -2879,7 +2892,8 @@ BOOL LLViewerMediaTexture::findFaces() } S32 face_id = -1 ; - while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1) + S32 num_faces = obj->mDrawable->getNumFaces() ; + while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1 && face_id < num_faces) { LLFace* facep = obj->mDrawable->getFace(face_id) ; if(facep) diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 141979052d..d6fbd5d570 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -49,12 +49,14 @@ class LLFace; class LLImageGL ; +class LLImageRaw; class LLViewerObject; class LLViewerTexture; class LLViewerFetchedTexture ; class LLViewerMediaTexture ; class LLTexturePipelineTester ; + typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); class LLVFile; @@ -68,14 +70,7 @@ public: LLLoadedCallbackEntry(loaded_callback_func cb, S32 discard_level, BOOL need_imageraw, // Needs image raw for the callback - void* userdata ) - : mCallback(cb), - mLastUsedDiscard(MAX_DISCARD_LEVEL+1), - mDesiredDiscard(discard_level), - mNeedsImageRaw(need_imageraw), - mUserData(userdata) - { - } + void* userdata ); loaded_callback_func mCallback; S32 mLastUsedDiscard; diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 028f8441ab..ab55bfd04d 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -53,6 +53,7 @@ const BOOL GL_TEXTURE_NO = FALSE; const BOOL IMMEDIATE_YES = TRUE; const BOOL IMMEDIATE_NO = FALSE; +class LLImageJ2C; class LLMessageSystem; class LLTextureView; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8529a93527..9cacdaa3f9 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -32,6 +32,8 @@ #include "llviewerprecompiledheaders.h" +#include "llviewerwindow.h" + #if LL_WINDOWS #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally #endif @@ -46,7 +48,6 @@ #include "llpanellogin.h" #include "llviewerkeyboard.h" #include "llviewermenu.h" -#include "llviewerwindow.h" #include "llviewquery.h" #include "llxmltree.h" @@ -82,7 +83,6 @@ // newview includes #include "llagent.h" -#include "llalertdialog.h" #include "llbox.h" #include "llconsole.h" #include "llviewercontrol.h" @@ -129,7 +129,6 @@ #include "llmorphview.h" #include "llmoveview.h" #include "llnavigationbar.h" -#include "llnotify.h" #include "lloverlaybar.h" #include "llpreviewtexture.h" #include "llprogressview.h" @@ -259,19 +258,21 @@ public: virtual void recordMessage(LLError::ELevel level, const std::string& message) { - // only log warnings to chat console - if (level == LLError::LEVEL_WARN) - { - LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat"); - if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat")) - { - LLChat chat; - chat.mText = message; - chat.mSourceType = CHAT_SOURCE_SYSTEM; + //FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread - chat_floater->addChat(chat, FALSE, FALSE); - } - } + // only log warnings to chat console + //if (level == LLError::LEVEL_WARN) + //{ + //LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat"); + //if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat")) + //{ + // LLChat chat; + // chat.mText = message; + // chat.mSourceType = CHAT_SOURCE_SYSTEM; + + // chat_floater->addChat(chat, FALSE, FALSE); + //} + //} } }; @@ -1450,7 +1451,6 @@ void LLViewerWindow::initBase() gDebugView = getRootView()->getChild<LLDebugView>("DebugView"); gDebugView->init(); - gNotifyBoxView = getRootView()->getChild<LLNotifyBoxView>("notify_container"); gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view"); // Add the progress bar view (startup view), which overrides everything @@ -1529,12 +1529,12 @@ void LLViewerWindow::initWorldUI() if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel")) { - toggle_show_navigation_panel(LLSD(0)); + navbar->showNavigationPanel(FALSE); } if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel")) { - toggle_show_favorites_panel(LLSD(0)); + navbar->showFavoritesPanel(FALSE); } if (!gSavedSettings.getBOOL("ShowCameraButton")) @@ -1628,8 +1628,6 @@ void LLViewerWindow::shutdownViews() gMorphView = NULL; gHUDView = NULL; - - gNotifyBoxView = NULL; } void LLViewerWindow::shutdownGL() @@ -1997,9 +1995,6 @@ void LLViewerWindow::draw() #if LL_DEBUG LLView::sIsDrawing = FALSE; #endif - - // UI post-draw Updates - gNotifyBoxView->updateNotifyBoxView(); } // Takes a single keydown event, usually when UI is visible @@ -2595,7 +2590,6 @@ void LLViewerWindow::updateUI() else if (dynamic_cast<LLUICtrl*>(viewp) && viewp != gMenuHolder && viewp != gFloaterView - && viewp != gNotifyBoxView && viewp != gConsole) { if (dynamic_cast<LLFloater*>(viewp)) @@ -3140,7 +3134,6 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback return; } - // push back pick info object BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) { @@ -3149,27 +3142,8 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback pick_transparent = TRUE; } - // center initial pick frame buffer region under mouse cursor - // since that area is guaranteed to be onscreen and hence a valid - // part of the framebuffer - if (mPicks.empty()) - { - mPickScreenRegion.setCenterAndSize(x, y_from_bot, PICK_DIAMETER, PICK_DIAMETER); - - if (mPickScreenRegion.mLeft < mWorldViewRectScaled.mLeft) mPickScreenRegion.translate(mWorldViewRectScaled.mLeft - mPickScreenRegion.mLeft, 0); - if (mPickScreenRegion.mBottom < mWorldViewRectScaled.mBottom) mPickScreenRegion.translate(0, mWorldViewRectScaled.mBottom - mPickScreenRegion.mBottom); - if (mPickScreenRegion.mRight > mWorldViewRectScaled.mRight ) mPickScreenRegion.translate(mWorldViewRectScaled.mRight - mPickScreenRegion.mRight, 0); - if (mPickScreenRegion.mTop > mWorldViewRectScaled.mTop ) mPickScreenRegion.translate(0, mWorldViewRectScaled.mTop - mPickScreenRegion.mTop); - } - - // set frame buffer region for picking results - // stack multiple picks left to right - LLRect screen_region = mPickScreenRegion; - screen_region.translate(mPicks.size() * PICK_DIAMETER, 0); - - LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, TRUE, callback); - - schedulePick(pick); + LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback); + schedulePick(pick_info); } void LLViewerWindow::schedulePick(LLPickInfo& pick_info) @@ -3184,10 +3158,11 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info) return; } - llassert_always(pick_info.mScreenRegion.notEmpty()); mPicks.push_back(pick_info); // delay further event processing until we receive results of pick + // only do this for async picks so that handleMouseUp won't be called + // until the pick triggered in handleMouseDown has been processed, for example mWindow->delayInputProcessing(); } @@ -3235,20 +3210,18 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans return LLPickInfo(); } - pickAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent); - // assume that pickAsync put the results in the back of the mPicks list - if(mPicks.size() != 0) - { - mLastPick = mPicks.back(); - mLastPick.fetchResults(); - mPicks.pop_back(); - } - else + BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); + if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) { - lldebugs << "List of last picks is empty: Using stub pick" << llendl; - mLastPick = LLPickInfo(); + // build mode allows interaction with all transparent objects + // "Show Debug Alpha" means no object actually transparent + pick_transparent = TRUE; } + // shortcut queueing in mPicks and just update mLastPick in place + mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), gKeyboard->currentMask(TRUE), pick_transparent, TRUE, NULL); + mLastPick.fetchResults(); + return mLastPick; } @@ -4895,13 +4868,11 @@ LLPickInfo::LLPickInfo() } LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, - const LLRect& screen_region, MASK keyboard_mask, BOOL pick_transparent, BOOL pick_uv_coords, void (*pick_callback)(const LLPickInfo& pick_info)) : mMousePt(mouse_pos), - mScreenRegion(screen_region), mKeyMask(keyboard_mask), mPickCallback(pick_callback), mPickType(PICK_INVALID), diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 1d564a1338..b488276a18 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -50,6 +50,7 @@ #include "llmousehandler.h" #include "llcursortypes.h" #include "llhandle.h" +#include "llimage.h" #include <boost/function.hpp> #include <boost/signals2.hpp> @@ -88,7 +89,6 @@ public: public: LLPickInfo(); LLPickInfo(const LLCoordGL& mouse_pos, - const LLRect& screen_region, MASK keyboard_mask, BOOL pick_transparent, BOOL pick_surface_info, @@ -120,7 +120,6 @@ public: LLVector3 mNormal; LLVector3 mBinormal; BOOL mPickTransparent; - LLRect mScreenRegion; void getSurfaceInfo(); private: @@ -345,7 +344,6 @@ public: void performPick(); void returnEmptyPicks(); - void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info), BOOL pick_transparent = FALSE); LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent); LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, @@ -397,7 +395,7 @@ public: private: bool shouldShowToolTipFor(LLMouseHandler *mh); static bool onAlert(const LLSD& notify); - + void switchToolByMask(MASK mask); void destroyWindow(); void drawMouselookInstructions(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 93b0ad4a5b..6e93bf1bf2 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -45,6 +45,7 @@ #include "llaudioengine.h" #include "noise.h" +#include "sound_ids.h" #include "llagent.h" // Get state values from here #include "llagentwearables.h" @@ -64,7 +65,6 @@ #include "llkeyframewalkmotion.h" #include "llmutelist.h" #include "llmoveview.h" -#include "llnotify.h" #include "llquantize.h" #include "llregionhandle.h" #include "llresmgr.h" @@ -5994,7 +5994,7 @@ void LLVOAvatar::updateMeshTextures() else { mBakedTextureDatas[i].mIsLoaded = FALSE; - if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) ) + if ( (baked_img->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); } @@ -6464,7 +6464,7 @@ void LLVOAvatar::onFirstTEMessageReceived() LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; mBakedTextureDatas[i].mLastTextureIndex = image->getID(); // If we have more than one texture for the other baked layers, we'll want to call this for them too. - if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) ) + if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); } @@ -7651,6 +7651,9 @@ void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& di void LLVOAvatar::idleUpdateRenderCost() { + static const U32 ARC_BODY_PART_COST = 20; + static const U32 ARC_LIMIT = 2048; + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) { return; @@ -7667,7 +7670,7 @@ void LLVOAvatar::idleUpdateRenderCost() { if (isTextureVisible(tex_index)) { - cost +=20; + cost +=ARC_BODY_PART_COST; } } } @@ -7687,7 +7690,6 @@ void LLVOAvatar::idleUpdateRenderCost() const LLDrawable* drawable = attached_object->mDrawable; if (drawable) { - cost += 10; const LLVOVolume* volume = drawable->getVOVolume(); if (volume) { @@ -7698,11 +7700,11 @@ void LLVOAvatar::idleUpdateRenderCost() } } - cost += textures.size() * 5; + cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST; setDebugText(llformat("%d", cost)); - F32 green = 1.f-llclamp(((F32) cost-1024.f)/1024.f, 0.f, 1.f); - F32 red = llmin((F32) cost/1024.f, 1.f); + F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); + F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f); mText->setColor(LLColor4(red,green,0,1)); } diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 175b6f1d10..fd4e7bb91f 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -122,6 +122,7 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& sess mSessionID(session_id), mState(STATE_NO_CHANNEL_INFO), mSessionName(session_name), + mCallDirection(OUTGOING_CALL), mIgnoreNextSessionLeave(FALSE) { mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName; @@ -405,7 +406,7 @@ void LLVoiceChannel::doSetState(const EState& new_state) EState old_state = mState; mState = new_state; if (!mStateChangedCallback.empty()) - mStateChangedCallback(old_state, mState); + mStateChangedCallback(old_state, mState, mCallDirection); } //static diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 1bed329ba2..77801142cb 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -52,7 +52,13 @@ public: STATE_CONNECTED } EState; - typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state)> state_changed_signal_t; + typedef enum e_voice_channel_direction + { + INCOMING_CALL, + OUTGOING_CALL + } EDirection; + + typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state, const EDirection& direction)> state_changed_signal_t; // on current channel changed signal typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t; @@ -87,6 +93,9 @@ public: void updateSessionID(const LLUUID& new_session_id); const LLSD& getNotifyArgs() { return mNotifyArgs; } + void setCallDirection(EDirection direction) {mCallDirection = direction;} + EDirection getCallDirection() {return mCallDirection;} + static LLVoiceChannel* getChannelByID(const LLUUID& session_id); static LLVoiceChannel* getChannelByURI(std::string uri); static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; } @@ -103,6 +112,9 @@ protected: void doSetState(const EState& state); void setURI(std::string uri); + // there can be two directions ICOMING and OUTGOING + EDirection mCallDirection; + std::string mURI; std::string mCredentials; LLUUID mSessionID; @@ -175,9 +187,6 @@ public: void setSessionHandle(const std::string& handle, const std::string &inURI); - // returns TRUE if call is incoming and FALSE otherwise - BOOL isIncomingCall() { return mReceivedCall; } - protected: virtual void setState(EState state); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 7e1e7c940f..cfa1f05ec0 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -113,31 +113,15 @@ static void setUUIDFromStringHash(LLUUID &uuid, const std::string &str) static int scale_mic_volume(float volume) { // incoming volume has the range [0.0 ... 2.0], with 1.0 as the default. - // Map it as follows: 0.0 -> 40, 1.0 -> 44, 2.0 -> 75 - - volume -= 1.0f; // offset volume to the range [-1.0 ... 1.0], with 0 at the default. - int scaled_volume = 44; // offset scaled_volume by its default level - if(volume < 0.0f) - scaled_volume += ((int)(volume * 4.0f)); // (44 - 40) - else - scaled_volume += ((int)(volume * 31.0f)); // (75 - 44) - - return scaled_volume; + // Map it to Vivox levels as follows: 0.0 -> 30, 1.0 -> 50, 2.0 -> 70 + return 30 + (int)(volume * 20.0f); } static int scale_speaker_volume(float volume) { // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default. - // Map it as follows: 0.0 -> 0, 0.5 -> 62, 1.0 -> 75 - - volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default. - int scaled_volume = 62; // offset scaled_volume by its default level - if(volume < 0.0f) - scaled_volume += ((int)(volume * 124.0f)); // (62 - 0) * 2 - else - scaled_volume += ((int)(volume * 26.0f)); // (75 - 62) * 2 - - return scaled_volume; + // Map it to Vivox levels as follows: 0.0 -> 30, 0.5 -> 50, 1.0 -> 70 + return 30 + (int)(volume * 40.0f); } class LLViewerVoiceAccountProvisionResponder : diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index cf61994fea..f98aa361e0 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -68,6 +68,7 @@ #include "llmediaentry.h" #include "llmediadataclient.h" #include "llagent.h" +#include "llviewermediafocus.h" const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; @@ -92,7 +93,7 @@ static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes"); class LLMediaDataClientObjectImpl : public LLMediaDataClientObject { public: - LLMediaDataClientObjectImpl(LLVOVolume *obj) : mObject(obj) {} + LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) {} LLMediaDataClientObjectImpl() { mObject = NULL; } virtual U8 getMediaDataCount() const @@ -128,14 +129,18 @@ public: virtual bool hasMedia() const { return mObject->hasMedia(); } - virtual void updateObjectMediaData(LLSD const &data) - { mObject->updateObjectMediaData(data); } - - virtual F64 getDistanceFromAvatar() const - { return mObject->getRenderPosition().length(); } + virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) + { mObject->updateObjectMediaData(data, version_string); } - virtual F64 getTotalMediaInterest() const - { return mObject->getTotalMediaInterest(); } + virtual F64 getMediaInterest() const + { + F64 tmp = mObject->getTotalMediaInterest(); + return (tmp < 0.0) ? mObject->getPixelArea() : tmp; + } + virtual bool isInterestingEnough() const + { + return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); + } virtual std::string getCapabilityUrl(const std::string &name) const { return mObject->getRegion()->getCapability(name); } @@ -143,8 +148,15 @@ public: virtual bool isDead() const { return mObject->isDead(); } + virtual U32 getMediaVersion() const + { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } + + virtual bool isNew() const + { return mNew; } + private: LLPointer<LLVOVolume> mObject; + bool mNew; }; @@ -165,6 +177,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mSpotLightPriority = 0.f; mMediaImplList.resize(getNumTEs()); + mLastFetchedMediaVersion = -1; } LLVOVolume::~LLVOVolume() @@ -190,7 +203,9 @@ void LLVOVolume::markDead() { if (!mDead) { - // TODO: tell LLMediaDataClient to remove this object from its queue + LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false); + if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); + if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); // Detach all media impls from this object for(U32 i = 0 ; i < mMediaImplList.size() ; i++) @@ -207,11 +222,18 @@ void LLVOVolume::markDead() void LLVOVolume::initClass() { // gSavedSettings better be around - const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); - const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); - const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); - sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries); - sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, max_retries); + if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) + { + const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); + const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); + const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); + const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); + const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); + sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, + max_sorted_queue_size, max_round_robin_queue_size); + sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, + max_retries, max_sorted_queue_size, max_round_robin_queue_size); + } } // static @@ -406,7 +428,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, // If the media changed at all, request new media data LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; - requestMediaDataUpdate(); + requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); } else { LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " << @@ -1698,16 +1720,17 @@ LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) return result; } -void LLVOVolume::requestMediaDataUpdate() +void LLVOVolume::requestMediaDataUpdate(bool isNew) { - sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this)); + if (sObjectMediaClient) + sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); } bool LLVOVolume::isMediaDataBeingFetched() const { // I know what I'm doing by const_casting this away: this is just // a wrapper class that is only going to do a lookup. - return sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this))); + return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false)) : false; } void LLVOVolume::cleanUpMediaImpls() @@ -1725,18 +1748,25 @@ void LLVOVolume::cleanUpMediaImpls() } } -void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array) +void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version) { // media_data_array is an array of media entry maps + // media_version is the version string in the response. + U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); - //llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl; - - LLSD::array_const_iterator iter = media_data_array.beginArray(); - LLSD::array_const_iterator end = media_data_array.endArray(); - U8 texture_index = 0; - for (; iter != end; ++iter, ++texture_index) + // Only update it if it is newer! + if ( (S32)fetched_version > mLastFetchedMediaVersion) { - syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); + mLastFetchedMediaVersion = fetched_version; + //llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl; + + LLSD::array_const_iterator iter = media_data_array.beginArray(); + LLSD::array_const_iterator end = media_data_array.endArray(); + U8 texture_index = 0; + for (; iter != end; ++iter, ++texture_index) + { + syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); + } } } @@ -1899,12 +1929,12 @@ void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plu // "bounce back" to the current URL from the media entry mediaNavigateBounceBack(face_index); } - else + else if (sObjectMediaNavigateClient) { llinfos << "broadcasting navigate with URI " << new_location << llendl; - sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this), face_index, new_location); + sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); } } @@ -1968,7 +1998,8 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, void LLVOVolume::sendMediaDataUpdate() { - sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this)); + if (sObjectMediaClient) + sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); } void LLVOVolume::removeMediaImpl(S32 texture_index) @@ -2063,7 +2094,10 @@ viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const F64 LLVOVolume::getTotalMediaInterest() const { - F64 interest = (F64)0.0; + if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) + return F64_MAX; + + F64 interest = (F64)-1.0; // means not interested; int i = 0; const int end = getNumTEs(); for ( ; i < end; ++i) @@ -2071,6 +2105,7 @@ F64 LLVOVolume::getTotalMediaInterest() const const viewer_media_t &impl = getMediaImpl(i); if (!impl.isNull()) { + if (interest == (F64)-1.0) interest = (F64)0.0; interest += impl->getInterest(); } } @@ -2587,7 +2622,22 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const // children, and cost should only be increased for unique textures -Nyx U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const { - U32 shame = 0; + // base cost of each prim should be 10 points + static const U32 ARC_PRIM_COST = 10; + // per-prim costs + static const U32 ARC_INVISI_COST = 1; + static const U32 ARC_SHINY_COST = 1; + static const U32 ARC_GLOW_COST = 1; + static const U32 ARC_FLEXI_COST = 8; + static const U32 ARC_PARTICLE_COST = 16; + static const U32 ARC_BUMP_COST = 4; + + // per-face costs + static const U32 ARC_PLANAR_COST = 1; + static const U32 ARC_ANIM_TEX_COST = 4; + static const U32 ARC_ALPHA_COST = 4; + + U32 shame = ARC_PRIM_COST; U32 invisi = 0; U32 shiny = 0; @@ -2663,7 +2713,17 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const } } - shame += invisi + shiny + glow + alpha*4 + flexi*8 + animtex*4 + particles*16+bump*4+scale+planar; + + shame += invisi * ARC_INVISI_COST; + shame += shiny * ARC_SHINY_COST; + shame += glow * ARC_GLOW_COST; + shame += alpha * ARC_ALPHA_COST; + shame += flexi * ARC_FLEXI_COST; + shame += animtex * ARC_ANIM_TEX_COST; + shame += particles * ARC_PARTICLE_COST; + shame += bump * ARC_BUMP_COST; + shame += planar * ARC_PLANAR_COST; + shame += scale; LLViewerObject::const_child_list_t& child_list = getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 06e214b41e..a287d34402 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -37,7 +37,6 @@ #include "llviewertexture.h" #include "llviewermedia.h" #include "llframetimer.h" -#include "llapr.h" #include "m3math.h" // LLMatrix3 #include "m4math.h" // LLMatrix4 #include <map> @@ -238,7 +237,7 @@ public: // Update this object's media data with the given media data array // (typically this is only called upon a response from a server request) - void updateObjectMediaData(const LLSD &media_data_array); + void updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version); // Bounce back media at the given index to its current URL (or home URL, if current URL is empty) void mediaNavigateBounceBack(U8 texture_index); @@ -270,13 +269,16 @@ public: // Returns 'true' iff the media data for this object is in flight bool isMediaDataBeingFetched() const; + // Returns the "last fetched" media version, or -1 if not fetched yet + S32 getLastFetchedMediaVersion() const { return mLastFetchedMediaVersion; } + protected: S32 computeLODDetail(F32 distance, F32 radius); BOOL calcLOD(); LLFace* addFace(S32 face_index); void updateTEData(); - void requestMediaDataUpdate(); + void requestMediaDataUpdate(bool isNew); void cleanUpMediaImpls(); void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ; void removeMediaImpl(S32 texture_index) ; @@ -300,6 +302,7 @@ private: LLPointer<LLViewerFetchedTexture> mSculptTexture; LLPointer<LLViewerFetchedTexture> mLightTexture; media_list_t mMediaImplList; + S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1 // statics public: @@ -310,6 +313,8 @@ public: static LLPointer<LLObjectMediaDataClient> sObjectMediaClient; static LLPointer<LLObjectMediaNavigateClient> sObjectMediaNavigateClient; + static const U32 ARC_TEXTURE_COST = 5; + protected: static S32 sNumLODChanges; diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index c8cc6a3d8e..8be8f494da 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -51,16 +51,13 @@ #include "llsdserialize.h" #include "v4math.h" -#include "llviewerdisplay.h" #include "llviewercontrol.h" -#include "llviewerwindow.h" #include "lldrawpoolwater.h" #include "llagent.h" #include "llviewerregion.h" #include "llwlparammanager.h" #include "llwaterparamset.h" -#include "llpostprocess.h" #include "llfloaterwater.h" #include "curl/curl.h" @@ -91,7 +88,7 @@ LLWaterParamManager::~LLWaterParamManager() void LLWaterParamManager::loadAllPresets(const std::string& file_name) { std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", "")); - LL_INFOS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL; + LL_DEBUGS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL; bool found = true; while(found) @@ -117,7 +114,7 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name) // And repeat for user presets, note the user presets will modify any system presets already loaded std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", "")); - LL_INFOS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL; + LL_DEBUGS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL; found = true; while(found) @@ -152,7 +149,7 @@ void LLWaterParamManager::loadPreset(const std::string & name,bool propagate) escaped_filename += ".xml"; std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", escaped_filename)); - llinfos << "Loading water settings from " << pathName << llendl; + LL_DEBUGS2("AppInit", "Shaders") << "Loading water settings from " << pathName << LL_ENDL; llifstream presetsXML; presetsXML.open(pathName.c_str()); @@ -161,7 +158,7 @@ void LLWaterParamManager::loadPreset(const std::string & name,bool propagate) if(!presetsXML) { pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", escaped_filename); - llinfos << "Loading User water setting from " << pathName << llendl; + LL_DEBUGS2("AppInit", "Shaders") << "Loading User water setting from " << pathName << LL_ENDL; presetsXML.clear(); presetsXML.open(pathName.c_str()); } diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 31047413ef..bd7619f7e5 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -41,7 +41,6 @@ #include "llviewerinventory.h" #include "llviewerstats.h" #include "llnotificationsutil.h" -#include "llnotify.h" #include "llinventorymodel.h" #include "lltrans.h" diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 72431bd22f..f8bb7336db 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -38,14 +38,20 @@ // Library includes #include "llwindow.h" // spawnWebBrowser() -#include "llviewerwindow.h" -#include "llviewercontrol.h" +#include "llappviewer.h" #include "llfloatermediabrowser.h" #include "llfloaterreg.h" -#include "llalertdialog.h" +#include "lllogininstance.h" +#include "llsd.h" #include "lltoastalertpanel.h" +#include "llui.h" +#include "lluri.h" +#include "llversioninfo.h" +#include "llviewercontrol.h" +#include "llviewernetwork.h" +#include "llviewerwindow.h" -class URLLoader : public LLAlertURLLoader +class URLLoader : public LLToastAlertPanel::URLLoader { virtual void load(const std::string& url , bool force_open_externally) { @@ -65,7 +71,6 @@ static URLLoader sAlertURLLoader; // static void LLWeb::initClass() { - LLAlertDialog::setURLLoader(&sAlertURLLoader); LLToastAlertPanel::setURLLoader(&sAlertURLLoader); } @@ -124,3 +129,24 @@ std::string LLWeb::escapeURL(const std::string& url) } return escaped_url; } + +//static +std::string LLWeb::expandURLSubstitutions(const std::string &url, + const LLSD &default_subs) +{ + LLSD substitution = default_subs; + substitution["VERSION"] = LLVersionInfo::getVersion(); + substitution["VERSION_MAJOR"] = LLVersionInfo::getMajor(); + substitution["VERSION_MINOR"] = LLVersionInfo::getMinor(); + substitution["VERSION_PATCH"] = LLVersionInfo::getPatch(); + substitution["VERSION_BUILD"] = LLVersionInfo::getBuild(); + substitution["CHANNEL"] = LLVersionInfo::getChannel(); + substitution["LANGUAGE"] = LLUI::getLanguage(); + substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel(); + substitution["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); + + std::string expanded_url = url; + LLStringUtil::format(expanded_url, substitution); + + return LLWeb::escapeURL(expanded_url); +} diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index 96a53db2ca..f4666c9280 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -57,8 +57,11 @@ public: /// Load the given url in the operating system's web browser static void loadURLExternal(const std::string& url); - // Returns escaped url (eg, " " to "%20") - used by all loadURL methods + /// Returns escaped url (eg, " " to "%20") - used by all loadURL methods static std::string escapeURL(const std::string& url); + /// Expands various strings like [LANG], [VERSION], etc. in a URL + static std::string expandURLSubstitutions(const std::string &url, + const LLSD &default_subs); }; #endif diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp index fcc43c2b1f..000d50795f 100644 --- a/indra/newview/llwldaycycle.cpp +++ b/indra/newview/llwldaycycle.cpp @@ -33,11 +33,13 @@ #include "llviewerprecompiledheaders.h" #include "llwldaycycle.h" -#include "llsdserialize.h" -#include "llwlparammanager.h" + #include "llnotificationsutil.h" +#include "llsdserialize.h" #include "llxmlnode.h" +#include "llwlparammanager.h" + #include <map> LLWLDayCycle::LLWLDayCycle() : mDayRate(120) diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index c6fd35c142..7cac564619 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -42,17 +42,12 @@ #include "llspinctrl.h" #include "llcheckboxctrl.h" #include "lluictrlfactory.h" -#include "llviewercamera.h" #include "llcombobox.h" #include "lllineeditor.h" #include "llsdserialize.h" #include "v4math.h" -#include "llviewerdisplay.h" #include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "lldrawpoolwater.h" -#include "llviewerregion.h" #include "llwlparamset.h" #include "llpostprocess.h" @@ -109,7 +104,7 @@ LLWLParamManager::~LLWLParamManager() void LLWLParamManager::loadPresets(const std::string& file_name) { std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", "")); - LL_INFOS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL; + LL_DEBUGS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL; bool found = true; while(found) @@ -135,7 +130,7 @@ void LLWLParamManager::loadPresets(const std::string& file_name) // And repeat for user presets, note the user presets will modify any system presets already loaded std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", "")); - LL_INFOS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL; + LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL; found = true; while(found) @@ -196,7 +191,7 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate) escaped_filename += ".xml"; std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", escaped_filename)); - //llinfos << "Loading WindLight sky setting from " << pathName << llendl; + LL_DEBUGS2("AppInit", "Shaders") << "Loading WindLight sky setting from " << pathName << LL_ENDL; llifstream presetsXML; presetsXML.open(pathName.c_str()); @@ -205,7 +200,7 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate) if(!presetsXML) { pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", escaped_filename); - llinfos << "Loading User WindLight sky setting from " << pathName << llendl; + LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight sky setting from " << pathName << LL_ENDL; presetsXML.clear(); presetsXML.open(pathName.c_str()); } diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp index 6a074d9697..06040a574c 100644 --- a/indra/newview/llworldmapmessage.cpp +++ b/indra/newview/llworldmapmessage.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llworldmapmessage.h" +#include "message.h" #include "llworldmap.h" #include "llagent.h" diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp index af8cb6b9fb..15417614af 100644 --- a/indra/newview/llxmlrpclistener.cpp +++ b/indra/newview/llxmlrpclistener.cpp @@ -21,13 +21,14 @@ // external library headers #include <boost/scoped_ptr.hpp> #include <boost/range.hpp> // boost::begin(), boost::end() +#include <xmlrpc-epi/xmlrpc.h> +#include "curl/curl.h" + // other Linden headers #include "llerror.h" #include "stringize.h" #include "llxmlrpctransaction.h" -#include <xmlrpc-epi/xmlrpc.h> - #if LL_WINDOWS #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally #endif diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 282eddf380..73b5222ee3 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7268,13 +7268,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) updateCull(camera, ref_result, 1); stateSort(camera, ref_result); } - else - { - gGL.setColorMask(true, true); - mWaterRef.clear(); - gGL.setColorMask(true, false); - } - + ref_mask = mRenderTypeMask; mRenderTypeMask = mask; } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index cdbeed111e..b6995d2122 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -67,7 +67,7 @@ value="0 0 1 1" /> <color name="Yellow" - value="1 1 0 1" /> + value="0.114 0.65 0.1" /> <color name="Unused?" value="1 0.5 0 1" /> @@ -513,7 +513,7 @@ reference="White" /> <color name="ObjectChatColor" - reference="0.7 0.8 0.9 1" /> + reference="EmphasisColor" /> <color name="OverdrivenColor" value="1 0 0 1" /> diff --git a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png Binary files differindex aa3898ca99..0ac5b72b8f 100644 --- a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png +++ b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png diff --git a/indra/newview/skins/default/textures/bottomtray/Unread_IM.png b/indra/newview/skins/default/textures/bottomtray/Unread_IM.png Binary files differindex 598342ea80..5c0c85b864 100644 --- a/indra/newview/skins/default/textures/bottomtray/Unread_IM.png +++ b/indra/newview/skins/default/textures/bottomtray/Unread_IM.png diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png Binary files differnew file mode 100644 index 0000000000..dd9133bcc4 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png Binary files differnew file mode 100644 index 0000000000..0080e71f41 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 607df10048..0317d55768 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -143,6 +143,7 @@ with the same filename but different name <texture name="DropDown_Over" file_name="widgets/DropDown_Over.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="DropDown_Press" file_name="widgets/DropDown_Press.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="DropDown_Selected" file_name="widgets/DropDown_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> + <texture name="DropDown_On" file_name="widgets/DropDown_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="DropDown_Off" file_name="widgets/DropDown_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="DropTarget" file_name="widgets/DropTarget.png" preload="false" /> @@ -375,7 +376,7 @@ with the same filename but different name <texture name="Parcel_PushNo_Light" file_name="icons/Parcel_PushNo_Light.png" preload="false" /> <texture name="Parcel_R_Light" file_name="icons/Parcel_R_Light.png" preload="false" /> <texture name="Parcel_Scripts_Light" file_name="icons/Parcel_Scripts_Light.png" preload="false" /> - <texture name="Parcel_ScriptsNo_Light" file_name="icons/Parcel_ScriptsNo_Light.png" preload="false" /> + <texture name="Parcel_ScriptsNo_Light" file_name="icons/Parcel_ScriptsNo_Dark.png" preload="false" /> <texture name="Parcel_Voice_Light" file_name="icons/Parcel_Voice_Light.png" preload="false" /> <texture name="Parcel_VoiceNo_Light" file_name="icons/Parcel_VoiceNo_Light.png" preload="false" /> @@ -593,6 +594,9 @@ with the same filename but different name <texture name="Unread_IM" file_name="bottomtray/Unread_IM.png" preload="false" /> <texture name="Unread_Msg" file_name="bottomtray/Unread_Msg.png" preload="false" /> + <texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" /> + <texture name="WellButton_Lit_Selected" file_name="bottomtray/WellButton_Lit_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" /> + <texture name="VoicePTT_Lvl1" file_name="bottomtray/VoicePTT_Lvl1.png" preload="false" /> <texture name="VoicePTT_Lvl2" file_name="bottomtray/VoicePTT_Lvl2.png" preload="false" /> <texture name="VoicePTT_Lvl3" file_name="bottomtray/VoicePTT_Lvl3.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index d1fd42bdd9..1239152c32 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -4,7 +4,6 @@ height="420" layout="topleft" name="floaterland" - help_topic="floaterland" save_rect="true" title="ABOUT LAND" width="490"> @@ -1562,7 +1561,7 @@ Only large parcels can be listed in search. left="10" name="at URL:" width="100"> - Home URL: + Home Page: </text> <line_editor follows="left|top" @@ -1591,7 +1590,7 @@ Only large parcels can be listed in search. left="10" name="CurrentURL:" width="100"> - Current URL: + Current Page: </text> <button follows="top|right" @@ -1857,6 +1856,10 @@ Select the thumbnail to choose a different texture. top="0" help_topic="land_access_tab" name="land_access_panel"> + <panel.string + name="access_estate_defined"> + (Defined by the Estate) + </panel.string> <panel.string name="estate_override"> One or more of these options is set at the estate level @@ -1877,7 +1880,7 @@ Select the thumbnail to choose a different texture. <check_box follows="top|left" height="16" - label="Allow Public Access" + label="Allow Public Access [MATURITY]" layout="topleft" left_delta="0" name="public_access" @@ -1893,12 +1896,12 @@ Select the thumbnail to choose a different texture. name="Only Allow" top="49" width="278"> - Block Access By: + Restrict Access to Residents verified by: </text> <check_box follows="top|left" height="16" - label="Residents who have not given payment info to Linden Lab" + label="Payment Information on File [ESTATE_PAYMENT_LIMIT]" layout="topleft" left_delta="0" name="limit_payment" @@ -1908,7 +1911,7 @@ Select the thumbnail to choose a different texture. <check_box follows="top|left" height="16" - label="Residents who are not age verified adults" + label="Age Verification [ESTATE_AGE_LIMIT]" layout="topleft" left_delta="0" name="limit_age_verified" diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml index 75711cdf89..26b003cafe 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml @@ -222,7 +222,7 @@ width="300" height="30" name="currency_links"> - [http://www.secondlife.com/ payment method] | [http://www.secondlife.com/ currency] | [http://www.secondlife.com exchange rate] + [http://www.secondlife.com/ payment method] | [http://www.secondlife.com/ currency] | [http://www.secondlife.com/my/account/exchange_rates.php exchange rate] </text> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml index 526fda90d1..81c54ae55e 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -26,6 +26,10 @@ name="VoiceInviteAdHoc"> has joined a Voice Chat call with a conference chat. </floater.string> + <floater.string + name="VoiceInviteGroup"> + has joined a Voice Chat call with the group [GROUP]. + </floater.string> <avatar_icon enabled="false" follows="left|top" @@ -36,21 +40,25 @@ top="35" width="36" /> <text + clip_partial="true" font="SansSerifLarge" - height="20" + height="37" layout="topleft" left="77" name="caller name" - top="27" + top="20" + use_ellipses="true" width="315" word_wrap="true" /> <text + clip_partial="true" font="SansSerif" - height="50" + height="30" layout="topleft" left="77" name="question" - top="52" + top_pad="5" + use_ellipses="true" width="315" word_wrap="true"> Do you want to leave [CURRENT_CHAT] and join this voice chat? diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml index d6b20c8015..4b280ac59f 100644 --- a/indra/newview/skins/default/xui/en/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml @@ -171,7 +171,7 @@ enabled="false" follows="left|top" height="20" - label="Send Current URL to Parcel" + label="Send Current Page to Parcel" layout="topleft" left="0" name="assign" diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml index 8122386fae..681731b0da 100644 --- a/indra/newview/skins/default/xui/en/floater_media_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - bottom="666" can_close="true" can_drag_on_left="false" can_minimize="true" diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index 15655a920e..2f26e5d0c1 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -7,7 +7,6 @@ height="460" layout="topleft" name="Preferences" - help_topic="preferences" single_instance="true" title="PREFERENCES" width="620"> diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml index 52a19ac6b3..abc30c335c 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml @@ -3,15 +3,15 @@ legacy_header_height="18" auto_tile="true" can_resize="true" - follows="left|bottom" - height="331" + follows="left|top" + height="313" layout="topleft" min_height="120" - min_width="300" + min_width="320" name="preview_texture" help_topic="preview_texture" - width="300"> - <floater.string + width="320"> + <floater.string name="Title"> Texture: [NAME] </floater.string> @@ -43,63 +43,38 @@ max_length="127" name="desc" width="190" /> - <button - follows="left|bottom" - height="22" - label="OK" - layout="topleft" - left="80" - name="Keep" - top="302" - width="100" /> - <button - follows="left|bottom" - height="22" - label="Cancel" - layout="topleft" - left_pad="5" - name="Discard" - top_delta="0" - width="100" /> - <text + <text type="string" + halign="right" length="1" - follows="left|bottom" + follows="right|bottom" height="16" layout="topleft" - left="13" + left="110" name="dimensions" - top="309" - width="303"> + top="255" + width="200"> [WIDTH]px x [HEIGHT]px </text> <text type="string" + halign="right" length="1" - bg_visible="false" - border_drop_shadow_visible="false" - border_visible="false" - top="309" - drop_shadow_visible="true" - enabled="true" follows="right|bottom" - font="SansSerifSmall" - h_pad="0" - halign="right" - height="14" - left="54" - mouse_opaque="true" - name="aspect_ratio" - v_pad="0" - width="110"> - Preview Aspect Ratio + height="16" + layout="topleft" + left_delta="-110" + name="dimensions" + top_pad="5" + width="200"> + Preview aspect ratio </text> <combo_box allow_text_entry="true" - top="306" + top_delta="-3" follows="right|bottom" - height="20" - left="176" + height="23" + left_pad="10" max_chars="20" mouse_opaque="true" enabled="true" @@ -131,4 +106,31 @@ 2:1 </combo_item> </combo_box> + <button + follows="right|bottom" + height="22" + label="OK" + layout="topleft" + left="6" + name="keep" + top_pad="5" + width="100" /> + <button + follows="right|bottom" + height="22" + label="Cancel" + layout="topleft" + left_pad="5" + name="discard" + top_delta="0" + width="100" /> + <button + follows="right|bottom" + height="22" + label="Save As" + layout="topleft" + left_pad="5" + name="save_tex_btn" + top_delta="0" + width="100" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index 82e4d87b28..9c1a5499db 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -13,10 +13,6 @@ title="FIND" width="670"> <floater.string - name="search_url"> - http://int.searchwww-phx0.damballah.lindenlab.com/viewer - </floater.string> - <floater.string name="loading_text"> Loading... </floater.string> @@ -55,8 +51,20 @@ layout="topleft" left_delta="0" name="status_text" - top_pad="5" + top_pad="7" width="150" /> + <text + visible="false" + follows="bottom|right" + height="16" + left_delta="0" + name="refresh_search" + left_pad="0" + right="-10" + halign="right" + width="450"> + Redo search to reflect current God level + </text> </layout_panel> </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml index 6050aede79..93aa1f0e31 100644 --- a/indra/newview/skins/default/xui/en/floater_select_key.xml +++ b/indra/newview/skins/default/xui/en/floater_select_key.xml @@ -21,7 +21,7 @@ word_wrap="true" width="220"> Press a key to set your -Speak button toggle +Speak button trigger. </text> <button height="23" diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index 113da9ea4d..695021f755 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -101,7 +101,7 @@ <filter_editor follows="left|top|right" height="23" - label="Filter textures" + label="Filter Textures" layout="topleft" left="175" name="inventory search editor" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index e3851de8e7..5e68850e30 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2669,16 +2669,15 @@ even though the user gets a free copy. top_pad="5" name="media_tex" width="260"> - Media URL + Media </text> - <line_editor + <text follows="left|top|right" height="18" layout="topleft" left="10" read_only="true" name="media_info" - select_on_focus="true" width="180" /> <button follows="top|left" diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index 1ebc51f504..c1a211967c 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -106,26 +106,6 @@ width="24" /> </layout_panel> <layout_panel - layout="topleft" - name="volume_slider_panel" - top="0" - user_resize="false" - width="138"> - <slider_bar - control_name="AudioLevelMic" - follows="left|right|top" - height="24" - increment="0.05" - layout="topleft" - left="0" - max_val="2" - name="volume_slider_bar" - tool_tip="Master Volume" - top="0" - value="0.75" - width="138" /> - </layout_panel> - <layout_panel auto_resize="false" layout="topleft" min_width="100" diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml index 89492d8abc..439d68282f 100644 --- a/indra/newview/skins/default/xui/en/floater_water.xml +++ b/indra/newview/skins/default/xui/en/floater_water.xml @@ -4,7 +4,6 @@ height="240" layout="topleft" name="Water Floater" - help_topic="water_floater" save_rect="true" title="ADVANCED WATER EDITOR" width="700"> diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml index 16f6e49092..cedf83f8b1 100644 --- a/indra/newview/skins/default/xui/en/inspect_object.xml +++ b/indra/newview/skins/default/xui/en/inspect_object.xml @@ -9,7 +9,7 @@ bg_opaque_image="Inspector_Background" can_close="false" can_minimize="false" - height="148" + height="150" layout="topleft" name="inspect_object" single_instance="true" @@ -71,13 +71,15 @@ owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about width="196"> L$300,000 </text> - <text + <text + clip_partial="true" follows="all" font="SansSerifSmall" - height="36" + height="37" left="8" name="object_description" top_pad="0" + use_ellipses="true" width="220" word_wrap="true"> This is a really long description for an object being as how it is at least 80 characters in length and maybe more like 120 at this point. Who knows, really? @@ -90,7 +92,7 @@ This is a really long description for an object being as how it is at least 80 c height="13" left_delta="0" name="object_media_url" - top_pad="0" + top_pad="-1" width="291" max_length = "50" use_ellipses="true"> @@ -102,7 +104,7 @@ This is a really long description for an object being as how it is at least 80 c label="Buy" left="8" name="buy_btn" - top="119" + top="121" width="80" /> <button follows="top|left" diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml new file mode 100644 index 0000000000..5b94645b60 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- *NOTE: See also menu_avatar_other.xml --> +<context_menu + layout="topleft" + name="Avatar Pie"> + <menu_item_call + label="View Profile" + name="Profile..."> + <menu_item_call.on_click + function="ShowAgentProfile" + parameter="hit object" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Add Friend" + name="Add Friend"> + <menu_item_call.on_click + function="Avatar.AddFriend" /> + <menu_item_call.on_enable + function="Avatar.EnableAddFriend" /> + </menu_item_call> + <menu_item_call + label="IM" + name="Send IM..."> + <menu_item_call.on_click + function="Avatar.SendIM" /> + </menu_item_call> + <menu_item_call + label="Call" + name="Call"> + <menu_item_call.on_click + function="Avatar.Call" /> + </menu_item_call> + <menu_item_call + label="Invite to Group" + name="Invite..."> + <menu_item_call.on_click + function="Avatar.InviteToGroup" /> + </menu_item_call> + <menu_item_separator /> + <menu_item_call + enabled="false" + label="Block" + name="Avatar Mute"> + <menu_item_call.on_click + function="Avatar.Mute" /> + <menu_item_call.on_enable + function="Avatar.EnableMute" /> + </menu_item_call> + <menu_item_call + label="Report" + name="abuse"> + <menu_item_call.on_click + function="Avatar.ReportAbuse" /> + </menu_item_call> + <menu_item_call + label="Freeze" + name="Freeze..."> + <menu_item_call.on_click + function="Avatar.Freeze" /> + <menu_item_call.on_visible + function="Avatar.EnableFreezeEject"/> + </menu_item_call> + <menu_item_call + label="Eject" + name="Eject..."> + <menu_item_call.on_click + function="Avatar.Eject" /> + <menu_item_call.on_visible + function="Avatar.EnableFreezeEject"/> + </menu_item_call> + <menu_item_call + label="Debug" + name="Debug..."> + <menu_item_call.on_click + function="Avatar.Debug" /> + <menu_item_call.on_visible + function="IsGodCustomerService"/> + </menu_item_call> + <menu_item_call + label="Zoom In" + name="Zoom In"> + <menu_item_call.on_click + function="Tools.LookAtSelection" + parameter="zoom" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Pay" + name="Pay..."> + <menu_item_call.on_click + function="PayObject" /> + <menu_item_call.on_enable + function="EnablePayAvatar" /> + </menu_item_call> + <menu_item_separator /> + <menu_item_call + label="Object Profile" + name="Object Inspect"> + <menu_item_call.on_click + function="Object.Inspect" /> + <menu_item_call.on_enable + function="Object.EnableInspect" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml new file mode 100644 index 0000000000..c85dbbb1bc --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Attachment Pie"> + <menu_item_call + enabled="false" + label="Touch" + layout="topleft" + name="Attachment Object Touch"> + <menu_item_call.on_click + function="Object.Touch" /> + <menu_item_call.on_enable + function="Object.EnableTouch" + name="EnableTouch" + parameter="Touch" /> + </menu_item_call> + <!--menu_item_call + label="Stand Up" + layout="topleft" + name="Stand Up"> + <menu_item_call.on_click + function="Self.StandUp" + parameter="" /> + <menu_item_call.on_enable + function="Self.EnableStandUp" /> + </menu_item_call--> + <menu_item_call + enabled="false" + label="Edit" + layout="topleft" + name="Edit..."> + <menu_item_call.on_click + function="Object.Edit" /> + <menu_item_call.on_enable + function="EnableEdit" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Detach" + layout="topleft" + name="Detach"> + <menu_item_call.on_click + function="Attachment.Detach" /> + <menu_item_call.on_enable + function="Attachment.EnableDetach" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Drop" + layout="topleft" + name="Drop"> + <menu_item_call.on_click + function="Attachment.Drop" /> + <menu_item_call.on_enable + function="Attachment.EnableDrop" /> + </menu_item_call> + <!--menu_item_call + label="My Profile" + layout="topleft" + name="Profile..."> + <menu_item_call.on_click + function="ShowAgentProfile" + parameter="agent" /> + </menu_item_call> + <menu_item_call + label="My Appearance" + layout="topleft" + name="Appearance..."> + <menu_item_call.on_click + function="ShowFloater" + parameter="appearance" /> + <menu_item_call.on_enable + function="Edit.EnableCustomizeAvatar" /> + + </menu_item_call--> + <menu_item_separator + layout="topleft" /> + + <menu_item_call + label="Stand Up" + layout="topleft" + name="Stand Up"> + <menu_item_call.on_click + function="Self.StandUp" + parameter="" /> + <menu_item_call.on_enable + function="Self.EnableStandUp" /> + </menu_item_call> + <menu_item_call + label="My Appearance" + layout="topleft" + name="Appearance..."> + <menu_item_call.on_click + function="ShowFloater" + parameter="appearance" /> + <menu_item_call.on_enable + function="Edit.EnableCustomizeAvatar" /> + </menu_item_call> + <menu_item_call + label="My Friends" + layout="topleft" + name="Friends..."> + <menu_item_call.on_click + function="SideTray.PanelPeopleTab" + parameter="friends_panel" /> + </menu_item_call> + <menu_item_call + label="My Groups" + layout="topleft" + name="Groups..."> + <menu_item_call.on_click + function="SideTray.PanelPeopleTab" + parameter="groups_panel" /> + </menu_item_call> + <menu_item_call + label="My Profile" + layout="topleft" + name="Profile..."> + <menu_item_call.on_click + function="ShowAgentProfile" + parameter="agent" /> + </menu_item_call> + +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml new file mode 100644 index 0000000000..0ad41546d2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- *NOTE: See also menu_attachment_other.xml --> +<context_menu + layout="topleft" + name="Avatar Pie"> + <menu_item_call + label="View Profile" + name="Profile..."> + <menu_item_call.on_click + function="ShowAgentProfile" + parameter="hit object" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Add Friend" + name="Add Friend"> + <menu_item_call.on_click + function="Avatar.AddFriend" /> + <menu_item_call.on_enable + function="Avatar.EnableAddFriend" /> + </menu_item_call> + <menu_item_call + label="IM" + name="Send IM..."> + <menu_item_call.on_click + function="Avatar.SendIM" /> + </menu_item_call> + <menu_item_call + label="Call" + name="Call"> + <menu_item_call.on_click + function="Avatar.Call" /> + </menu_item_call> + <menu_item_call + label="Invite to Group" + name="Invite..."> + <menu_item_call.on_click + function="Avatar.InviteToGroup" /> + </menu_item_call> + <menu_item_separator /> + <menu_item_call + enabled="false" + label="Block" + name="Avatar Mute"> + <menu_item_call.on_click + function="Avatar.Mute" /> + <menu_item_call.on_enable + function="Avatar.EnableMute" /> + </menu_item_call> + <menu_item_call + label="Report" + name="abuse"> + <menu_item_call.on_click + function="Avatar.ReportAbuse" /> + </menu_item_call> + <menu_item_call + label="Freeze" + name="Freeze..."> + <menu_item_call.on_click + function="Avatar.Freeze" /> + <menu_item_call.on_visible + function="Avatar.EnableFreezeEject"/> + </menu_item_call> + <menu_item_call + label="Eject" + name="Eject..."> + <menu_item_call.on_click + function="Avatar.Eject" /> + <menu_item_call.on_visible + function="Avatar.EnableFreezeEject"/> + </menu_item_call> + <menu_item_call + label="Debug" + name="Debug..."> + <menu_item_call.on_click + function="Avatar.Debug" /> + <menu_item_call.on_visible + function="IsGodCustomerService"/> + </menu_item_call> + <menu_item_call + label="Zoom In" + name="Zoom In"> + <menu_item_call.on_click + function="Tools.LookAtSelection" + parameter="zoom" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Pay" + name="Pay..."> + <menu_item_call.on_click + function="PayObject" /> + <menu_item_call.on_enable + function="EnablePayAvatar" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml new file mode 100644 index 0000000000..c6ce612a76 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml @@ -0,0 +1,227 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Self Pie"> + <menu_item_call + label="Stand Up" + layout="topleft" + name="Stand Up"> + <menu_item_call.on_click + function="Self.StandUp" + parameter="" /> + <menu_item_call.on_enable + function="Self.EnableStandUp" /> + </menu_item_call> + <context_menu + label="Take Off >" + layout="topleft" + name="Take Off >"> + <context_menu + label="Clothes >" + layout="topleft" + name="Clothes >"> + <menu_item_call + enabled="false" + label="Shirt" + layout="topleft" + name="Shirt"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="shirt" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="shirt" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Pants" + layout="topleft" + name="Pants"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="pants" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="pants" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Skirt" + layout="topleft" + name="Skirt"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="skirt" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="skirt" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Shoes" + layout="topleft" + name="Shoes"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="shoes" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="shoes" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Socks" + layout="topleft" + name="Socks"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="socks" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="socks" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Jacket" + layout="topleft" + name="Jacket"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="jacket" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="jacket" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Gloves" + layout="topleft" + name="Gloves"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="gloves" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="gloves" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Undershirt" + layout="topleft" + name="Self Undershirt"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="undershirt" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="undershirt" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Underpants" + layout="topleft" + name="Self Underpants"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="underpants" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="underpants" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Tattoo" + layout="topleft" + name="Self Tattoo"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="tattoo" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="tattoo" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Alpha" + layout="topleft" + name="Self Alpha"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="alpha" /> + <menu_item_call.on_enable + function="Edit.EnableTakeOff" + parameter="alpha" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="All Clothes" + layout="topleft" + name="All Clothes"> + <menu_item_call.on_click + function="Edit.TakeOff" + parameter="all" /> + </menu_item_call> + </context_menu> + <context_menu + label="HUD >" + layout="topleft" + name="Object Detach HUD" /> + <context_menu + label="Detach >" + layout="topleft" + name="Object Detach" /> + <menu_item_call + label="Detach All" + layout="topleft" + name="Detach All"> + <menu_item_call.on_click + function="Self.RemoveAllAttachments" + parameter="" /> + <menu_item_call.on_enable + function="Self.EnableRemoveAllAttachments" /> + </menu_item_call> + </context_menu> + <menu_item_call + label="My Appearance" + layout="topleft" + name="Appearance..."> + <menu_item_call.on_click + function="ShowFloater" + parameter="appearance" /> + <menu_item_call.on_enable + function="Edit.EnableCustomizeAvatar" /> + </menu_item_call> + <menu_item_call + label="My Friends" + layout="topleft" + name="Friends..."> + <menu_item_call.on_click + function="SideTray.PanelPeopleTab" + parameter="friends_panel" /> + </menu_item_call> + <!--menu_item_call + label="My Gestures" + layout="topleft" + name="Gestures..."> + <menu_item_call.on_click + function="ShowFloater" + parameter="gestures" /> + </menu_item_call--> + <menu_item_call + label="My Groups" + layout="topleft" + name="Groups..."> + <menu_item_call.on_click + function="SideTray.PanelPeopleTab" + parameter="groups_panel" /> + </menu_item_call> + <menu_item_call + label="My Profile" + layout="topleft" + name="Profile..."> + <menu_item_call.on_click + function="ShowAgentProfile" + parameter="agent" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index a36bfb8ec1..0f400777b8 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -339,6 +339,9 @@ function="Inventory.DoToSelected" parameter="open" /> </menu_item_call> + <menu_item_separator + layout="topleft" + name="Folder Wearables Separator" /> <menu_item_call label="Replace Current Outfit" layout="topleft" @@ -423,7 +426,8 @@ parameter="copy_uuid" /> </menu_item_call> <menu_item_separator - layout="topleft" /> + layout="topleft" + name="Copy Separator" /> <menu_item_call label="Copy" layout="topleft" @@ -449,7 +453,16 @@ parameter="paste_link" /> </menu_item_call> <menu_item_separator - layout="topleft" /> + layout="topleft" + name="Paste Separator" /> + <menu_item_call + label="Remove Link" + layout="topleft" + name="Remove Link"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="delete" /> + </menu_item_call> <menu_item_call label="Delete" layout="topleft" @@ -492,7 +505,8 @@ parameter="about" /> </menu_item_call> <menu_item_separator - layout="topleft" /> + layout="topleft" + name="Animation Separator" /> <menu_item_call label="Play in World" layout="topleft" @@ -510,7 +524,8 @@ parameter="playlocal" /> </menu_item_call> <menu_item_separator - layout="topleft" /> + layout="topleft" + name="Send Instant Message Separator" /> <menu_item_call label="Send Instant Message" layout="topleft" @@ -536,7 +551,8 @@ parameter="selected" /> </menu_item_call> <menu_item_separator - layout="topleft" /> + layout="topleft" + name="Gesture Separator" /> <menu_item_call label="Activate" layout="topleft" @@ -554,7 +570,8 @@ parameter="deactivate" /> </menu_item_call> <menu_item_separator - layout="topleft" /> + layout="topleft" + name="Texture Separator" /> <menu_item_call label="Save As" layout="topleft" @@ -564,7 +581,8 @@ parameter="save_as" /> </menu_item_call> <menu_item_separator - layout="topleft" /> + layout="topleft" + name="Attach Separator"/> <menu_item_call label="Detach From Yourself" layout="topleft" @@ -600,6 +618,9 @@ label="Attach To HUD" layout="topleft" name="Attach To HUD" /> + <menu_item_separator + layout="topleft" + name="Wearable Separator"/> <menu_item_call label="Edit" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_land.xml b/indra/newview/skins/default/xui/en/menu_land.xml new file mode 100644 index 0000000000..d88a2f8d25 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_land.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Land Pie"> + <menu_item_call + label="About Land" + name="Place Information..."> + <menu_item_call.on_click + function="ShowFloater" + parameter="about_land" /> + </menu_item_call> + <!-- <menu_item_call + label="Go Here" + name="Go Here"> + <menu_item_call.on_click + function="GoToObject" /> + </menu_item_call>--> + <menu_item_call + label="Sit Here" + name="Sit Here"> + <menu_item_call.on_click + function="Land.Sit" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + enabled="false" + label="Buy This Land" + name="Land Buy"> + <menu_item_call.on_click + function="ShowFloater" + parameter="buy land" /> + <menu_item_call.on_enable + function="World.EnableBuyLand" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Buy Pass" + name="Land Buy Pass"> + <menu_item_call.on_click + function="Land.BuyPass" /> + <menu_item_call.on_enable + function="Land.EnableBuyPass" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + enabled="false" + label="Build" + name="Create"> + <menu_item_call.on_click + function="Land.Build" /> + <menu_item_call.on_enable + function="EnableEdit" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Edit Terrain" + name="Edit Terrain"> + <menu_item_call.on_click + function="Land.Edit" /> + <menu_item_call.on_enable + function="EnableEdit" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 9b439c16e0..53be40d7fd 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -45,7 +45,8 @@ name="Second Life Help" shortcut="F1"> <menu_item_call.on_click - function="ShowHelp" /> + function="ShowHelp" + parameter="f1_help" /> </menu_item_call> <menu_item_separator /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml new file mode 100644 index 0000000000..62500c5116 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_object.xml @@ -0,0 +1,158 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Object Pie"> + <menu_item_call + enabled="false" + label="Touch" + name="Object Touch"> + <menu_item_call.on_click + function="Object.Touch" /> + <menu_item_call.on_enable + function="Object.EnableTouch" + name="EnableTouch" + parameter="Touch" /> + </menu_item_call> + <menu_item_call + label="Edit" + name="Edit..."> + <menu_item_call.on_click + function="Object.Edit" /> + <menu_item_call.on_visible + function="EnableEdit"/> + </menu_item_call> + <menu_item_call + label="Build" + name="Build"> + <menu_item_call.on_click + function="Object.Edit" /> + <menu_item_call.on_visible + function="VisibleBuild"/> + </menu_item_call> + <menu_item_call + enabled="false" + label="Open" + name="Open"> + <menu_item_call.on_click + function="Object.Open" /> + <menu_item_call.on_enable + function="Object.EnableOpen" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Sit Here" + name="Object Sit"> + <menu_item_call.on_click + function="Object.SitOrStand" /> + <menu_item_call.on_enable + function="Object.EnableSitOrStand" + name="EnableSitOrStand" + parameter="Sit Here,Stand Up" /> + </menu_item_call> + <menu_item_call + label="Object Profile" + name="Object Inspect"> + <menu_item_call.on_click + function="Object.Inspect" /> + <menu_item_call.on_enable + function="Object.EnableInspect" /> + </menu_item_call> +<menu_item_separator layout="topleft" /> + <context_menu + label="Put On >" + name="Put On" > + <menu_item_call + enabled="false" + label="Wear" + name="Wear"> + <menu_item_call.on_click + function="Object.AttachToAvatar" /> + <menu_item_call.on_enable + function="Object.EnableWear" /> + </menu_item_call> + <context_menu + label="Attach >" + name="Object Attach" /> + <context_menu + label="Attach HUD >" + name="Object Attach HUD" /> + </context_menu> + <context_menu + label="Remove >" + name="Remove"> + <menu_item_call + enabled="false" + label="Take" + name="Pie Object Take"> + <menu_item_call.on_click + function="Tools.BuyOrTake" /> + <menu_item_call.on_enable + function="Tools.EnableBuyOrTake" + parameter="Buy,Take" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Report Abuse" + name="Report Abuse..."> + <menu_item_call.on_click + function="Object.ReportAbuse" /> + <menu_item_call.on_enable + function="Object.EnableReportAbuse" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Block" + name="Object Mute"> + <menu_item_call.on_click + function="Object.Mute" /> + <menu_item_call.on_enable + function="Object.EnableMute" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Return" + name="Return..."> + <menu_item_call.on_click + function="Object.Return" /> + <menu_item_call.on_enable + function="Object.EnableReturn" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Delete" + name="Delete"> + <menu_item_call.on_click + function="Object.Delete" /> + <menu_item_call.on_enable + function="Object.EnableDelete" /> + </menu_item_call> + </context_menu> + <menu_item_separator layout="topleft" /> + <menu_item_call + enabled="false" + label="Take Copy" + name="Take Copy"> + <menu_item_call.on_click + function="Tools.TakeCopy" /> + <menu_item_call.on_enable + function="Tools.EnableTakeCopy" /> + </menu_item_call> + <menu_item_call + enabled="false" + label="Pay" + name="Pay..."> + <menu_item_call.on_click + function="PayObject" /> + <menu_item_call.on_enable + function="EnablePayObject" /> +</menu_item_call> + <menu_item_call + enabled="false" + label="Buy" + name="Buy..."> + <menu_item_call.on_click + function="Object.Buy" /> + <menu_item_call.on_enable + function="Object.EnableBuy" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml index 5ab327a182..449202aaaa 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -16,7 +16,7 @@ <menu_item_call.on_click function="Avatar.AddFriend" /> <menu_item_call.on_enable - function="Avatar.EnableItem" + function="ParticipantList.EnableItem" parameter="can_add" /> </menu_item_call> <menu_item_call @@ -30,11 +30,14 @@ label="Call" layout="topleft" name="Call"> - <menu_item_call.on_click + <menu_item_call.on_click function="Avatar.Call" /> + <menu_item_call.on_enable + function="ParticipantList.EnableItem" + parameter="can_call" /> </menu_item_call> <menu_item_call - enabled="false" + enabled="true" label="Share" layout="topleft" name="Share"> @@ -49,22 +52,22 @@ function="Avatar.Pay" /> </menu_item_call> <menu_item_check - label="Block/Unblock" + label="Block Voice" layout="topleft" name="Block/Unblock"> <menu_item_check.on_click function="Avatar.BlockUnblock" /> <menu_item_check.on_check - function="Avatar.CheckItem" + function="ParticipantList.CheckItem" parameter="is_blocked" /> <menu_item_check.on_enable - function="Avatar.EnableItem" + function="ParticipantList.EnableItem" parameter="can_block" /> </menu_item_check> <menu_item_separator layout="topleft" /> <menu_item_check - label="Mute Text" + label="Block Text" layout="topleft" name="MuteText"> <on_check @@ -76,6 +79,10 @@ function="ParticipantList.EnableItem" parameter="can_mute_text" /> </menu_item_check> + <context_menu + label="Moderator Options >" + layout="topleft" + name="Moderator Options" > <menu_item_check label="Allow text chat" layout="topleft" @@ -89,4 +96,52 @@ function="ParticipantList.EnableItem" parameter="can_allow_text_chat" /> </menu_item_check> + <menu_item_separator + layout="topleft" + name="moderate_voice_separator" /> + <menu_item_call + label="Mute this participant" + layout="topleft" + name="ModerateVoiceMuteSelected"> + <on_click + function="ParticipantList.ModerateVoice" + parameter="selected" /> + <on_enable + function="ParticipantList.EnableItem" + parameter="can_moderate_voice" /> + </menu_item_call> + <menu_item_call + label="Mute everyone else" + layout="topleft" + name="ModerateVoiceMuteOthers"> + <on_click + function="ParticipantList.ModerateVoice" + parameter="others" /> + <on_enable + function="ParticipantList.EnableItem" + parameter="can_moderate_voice" /> + </menu_item_call> + <menu_item_call + label="Unmute this participant" + layout="topleft" + name="ModerateVoiceUnMuteSelected"> + <on_click + function="ParticipantList.ModerateVoice" + parameter="selected" /> + <on_enable + function="ParticipantList.EnableItem" + parameter="can_moderate_voice" /> + </menu_item_call> + <menu_item_call + label="Unmute everyone else" + layout="topleft" + name="ModerateVoiceUnMuteOthers"> + <on_click + function="ParticipantList.ModerateVoice" + parameter="others" /> + <on_enable + function="ParticipantList.EnableItem" + parameter="can_moderate_voice" /> + </menu_item_call> + </context_menu> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml index 304492bedb..df3cb26b04 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml @@ -19,5 +19,7 @@ name="Leave Selected Group"> <menu_item_call.on_click function="People.Group.Minus.Action"/> + <menu_item_call.on_enable + function="People.Group.Minus.Enable"/> </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index c3a2540b2e..5f2e6e0f6c 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -32,9 +32,11 @@ name="Call"> <menu_item_call.on_click function="Avatar.Call" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_call" /> </menu_item_call> <menu_item_call - enabled="false" label="Share" layout="topleft" name="Share"> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml index df74d2dcd4..0d3dd3366d 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml @@ -27,6 +27,9 @@ name="Call"> <on_click function="Avatar.Call" /> + <on_enable + function="Avatar.EnableItem" + parameter="can_call" /> </menu_item_call> <menu_item_call enabled="false" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 861b0de2cf..0891afaf76 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1064,7 +1064,8 @@ name="Second Life Help" shortcut="F1"> <menu_item_call.on_click - function="ShowHelp" /> + function="ShowHelp" + parameter="f1_help" /> </menu_item_call> <menu_item_call label="Tutorial" @@ -1200,15 +1201,6 @@ function="ToggleControl" parameter="CompressSnapshotsToDisk" /> </menu_item_check> - <menu_item_call - label="Save Texture As" - layout="topleft" - name="Save Texture As"> - <menu_item_call.on_click - function="File.SaveTexture" /> - <menu_item_call.on_enable - function="File.EnableSaveAs" /> - </menu_item_call> <menu_item_separator layout="topleft" /> <menu diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml new file mode 100644 index 0000000000..05cd850725 --- /dev/null +++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml @@ -0,0 +1,442 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<mimetypes name="default"> + <defaultlabel> + (Unknown) + </defaultlabel> + <defaultwidget> + none + </defaultwidget> + <defaultimpl> + media_plugin_webkit + </defaultimpl> + <widgetset name="web"> + <label name="web_label"> + Web Content + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + text/html + </default_type> + <tooltip name="web_tooltip"> + This location has Web content + </tooltip> + <playtip name="web_playtip"> + Show Web content + </playtip> + <allow_resize> + true + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="movie"> + <label name="movie_label"> + Movie + </label> + <default_type> + video/* + </default_type> + <icon> + icn_media_movie.tga + </icon> + <tooltip name="movie_tooltip"> + There is a movie to play here + </tooltip> + <playtip name="movie_playtip"> + Play movie + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <widgetset name="image"> + <label name="image_label"> + Image + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + image/* + </default_type> + <tooltip name="image_tooltip"> + There is an image at this location + </tooltip> + <playtip name="image_playtip"> + View this location's image + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="audio"> + <label name="audio_label"> + Audio + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + audio/* + </default_type> + <tooltip name="audio_tooltip"> + There is audio at this location + </tooltip> + <playtip name="audio_playtip"> + Play this location's audio + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <scheme name="rtsp"> + <label name="rtsp_label"> + Real Time Streaming + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </scheme> + <mimetype name="blank"> + <label name="blank_label"> + - None - + </label> + <widgettype> + none + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="none/none"> + <label name="none/none_label"> + - None - + </label> + <widgettype> + none + </widgettype> + </mimetype> + <mimetype name="audio/*"> + <label name="audio2_label"> + Audio + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="video/*"> + <label name="video2_label"> + Video + </label> + <widgettype> + movie + </widgettype> + </mimetype> + <mimetype name="image/*"> + <label name="image2_label"> + Image + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> + <label name="vnd.secondlife.qt.legacy_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="application/javascript"> + <label name="application/javascript_label"> + Javascript + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/ogg"> + <label name="application/ogg_label"> + Ogg Audio/Video + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="application/pdf"> + <label name="application/pdf_label"> + PDF Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/postscript"> + <label name="application/postscript_label"> + Postscript Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/rtf"> + <label name="application/rtf_label"> + Rich Text (RTF) + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/smil"> + <label name="application/smil_label"> + Synchronized Multimedia Integration Language (SMIL) + </label> + <widgettype> + movie + </widgettype> + </mimetype> + <mimetype name="application/xhtml+xml"> + <label name="application/xhtml+xml_label"> + Web Page (XHTML) + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/x-director"> + <label name="application/x-director_label"> + Macromedia Director + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="audio/mid"> + <label name="audio/mid_label"> + Audio (MIDI) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="audio/mpeg"> + <label name="audio/mpeg_label"> + Audio (MP3) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="audio/x-aiff"> + <label name="audio/x-aiff_label"> + Audio (AIFF) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="audio/x-wav"> + <label name="audio/x-wav_label"> + Audio (WAV) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype menu="1" name="image/bmp"> + <label name="image/bmp_label"> + Image (BMP) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/gif"> + <label name="image/gif_label"> + Image (GIF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/jpeg"> + <label name="image/jpeg_label"> + Image (JPEG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/png"> + <label name="image/png_label"> + Image (PNG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="image/svg+xml"> + <label name="image/svg+xml_label"> + Image (SVG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/tiff"> + <label name="image/tiff_label"> + Image (TIFF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/html"> + <label name="text/html_label"> + Web Page + </label> + <widgettype> + web + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/plain"> + <label name="text/plain_label"> + Text + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="text/xml"> + <label name="text/xml_label"> + XML + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="video/mpeg"> + <label name="video/mpeg_label"> + Movie (MPEG) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="video/mp4"> + <label name="video/mp4_label"> + Movie (MP4) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype menu="1" name="video/quicktime"> + <label name="video/quicktime_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="video/x-ms-asf"> + <label name="video/x-ms-asf_label"> + Movie (Windows Media ASF) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="video/x-ms-wmv"> + <label name="video/x-ms-wmv_label"> + Movie (Windows Media WMV) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype menu="1" name="video/x-msvideo"> + <label name="video/x-msvideo_label"> + Movie (AVI) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> +</mimetypes> diff --git a/indra/newview/skins/default/xui/en/mime_types_mac.xml b/indra/newview/skins/default/xui/en/mime_types_mac.xml new file mode 100644 index 0000000000..76c0d027f3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/mime_types_mac.xml @@ -0,0 +1,442 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<mimetypes name="default"> + <defaultlabel> + (Unknown) + </defaultlabel> + <defaultwidget> + none + </defaultwidget> + <defaultimpl> + media_plugin_webkit + </defaultimpl> + <widgetset name="web"> + <label name="web_label"> + Web Content + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + text/html + </default_type> + <tooltip name="web_tooltip"> + This location has Web content + </tooltip> + <playtip name="web_playtip"> + Show Web content + </playtip> + <allow_resize> + true + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="movie"> + <label name="movie_label"> + Movie + </label> + <default_type> + video/* + </default_type> + <icon> + icn_media_movie.tga + </icon> + <tooltip name="movie_tooltip"> + There is a movie to play here + </tooltip> + <playtip name="movie_playtip"> + Play movie + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <widgetset name="image"> + <label name="image_label"> + Image + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + image/* + </default_type> + <tooltip name="image_tooltip"> + There is an image at this location + </tooltip> + <playtip name="image_playtip"> + View this location's image + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="audio"> + <label name="audio_label"> + Audio + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + audio/* + </default_type> + <tooltip name="audio_tooltip"> + There is audio at this location + </tooltip> + <playtip name="audio_playtip"> + Play this location's audio + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <scheme name="rtsp"> + <label name="rtsp_label"> + Real Time Streaming + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </scheme> + <mimetype name="blank"> + <label name="blank_label"> + - None - + </label> + <widgettype> + none + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="none/none"> + <label name="none/none_label"> + - None - + </label> + <widgettype> + none + </widgettype> + </mimetype> + <mimetype name="audio/*"> + <label name="audio2_label"> + Audio + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="video/*"> + <label name="video2_label"> + Video + </label> + <widgettype> + movie + </widgettype> + </mimetype> + <mimetype name="image/*"> + <label name="image2_label"> + Image + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> + <label name="vnd.secondlife.qt.legacy_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="application/javascript"> + <label name="application/javascript_label"> + Javascript + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/ogg"> + <label name="application/ogg_label"> + Ogg Audio/Video + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="application/pdf"> + <label name="application/pdf_label"> + PDF Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/postscript"> + <label name="application/postscript_label"> + Postscript Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/rtf"> + <label name="application/rtf_label"> + Rich Text (RTF) + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/smil"> + <label name="application/smil_label"> + Synchronized Multimedia Integration Language (SMIL) + </label> + <widgettype> + movie + </widgettype> + </mimetype> + <mimetype name="application/xhtml+xml"> + <label name="application/xhtml+xml_label"> + Web Page (XHTML) + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/x-director"> + <label name="application/x-director_label"> + Macromedia Director + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="audio/mid"> + <label name="audio/mid_label"> + Audio (MIDI) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/mpeg"> + <label name="audio/mpeg_label"> + Audio (MP3) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/x-aiff"> + <label name="audio/x-aiff_label"> + Audio (AIFF) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/x-wav"> + <label name="audio/x-wav_label"> + Audio (WAV) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="image/bmp"> + <label name="image/bmp_label"> + Image (BMP) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/gif"> + <label name="image/gif_label"> + Image (GIF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/jpeg"> + <label name="image/jpeg_label"> + Image (JPEG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/png"> + <label name="image/png_label"> + Image (PNG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="image/svg+xml"> + <label name="image/svg+xml_label"> + Image (SVG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/tiff"> + <label name="image/tiff_label"> + Image (TIFF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/html"> + <label name="text/html_label"> + Web Page + </label> + <widgettype> + web + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/plain"> + <label name="text/plain_label"> + Text + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="text/xml"> + <label name="text/xml_label"> + XML + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="video/mpeg"> + <label name="video/mpeg_label"> + Movie (MPEG) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/mp4"> + <label name="video/mp4_label"> + Movie (MP4) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="video/quicktime"> + <label name="video/quicktime_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/x-ms-asf"> + <label name="video/x-ms-asf_label"> + Movie (Windows Media ASF) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/x-ms-wmv"> + <label name="video/x-ms-wmv_label"> + Movie (Windows Media WMV) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="video/x-msvideo"> + <label name="video/x-msvideo_label"> + Movie (AVI) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> +</mimetypes> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 416b1b6973..bcf006f1a0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -579,7 +579,7 @@ Scripts must be allowed to run for weapons to work. type="alertmodal"> Multiple faces are currently selected. If you continue this action, separate instances of media will be set on multiple faces of the object. -To place the media on only one face, choose Select Texture and click on the desired face of that object then click Add. +To place the media on only one face, choose Select Face and click on the desired face of that object then click Add. <usetemplate ignoretext="Media will be set on multiple selected faces" name="okcancelignore" @@ -3539,6 +3539,8 @@ Type a short announcement which will be sent to everyone in this region. type="alertmodal"> The maturity rating for this region has been updated. It may take some time for the change to be reflected on the map. + +To enter Adult regions, residents must be Account Verified, either by age-verification or payment-verification. </notification> <notification @@ -3799,21 +3801,6 @@ All reported abuses are investigated and resolved. You can view the resolution b <notification icon="alertmodal.tga" - name="HelpReportAbuseEmailEO" - type="alertmodal"> -IMPORTANT: This report will go to the owner of the region you are currently in and not to Linden Lab. - -As a service to residents and visitors, the owner of the region you are in has elected to receive and resolve all reports originating in this region. Linden Lab will not investigate reports you file from this location. - -The region owner will resolve reports based on the local rules of this region as outlined in the estate Covenant. -(View covenants by going to the World menu and selecting About Land.) - -The resolution of this report applies only to this Region. Residents' access to other areas of [SECOND_LIFE] will not be affected by the outcome of this report. Only Linden Lab can restrict access to the entirety of [SECOND_LIFE]. - <unique/> - </notification> - - <notification - icon="alertmodal.tga" name="HelpReportAbuseSelectCategory" type="alertmodal"> Please select a category for this abuse report. @@ -4719,10 +4706,6 @@ The objects on the selected parcel that are NOT owned by you have been returned type="notify"> Message from [NAME]: [MSG] - <usetemplate - name="okcancelbuttons" - notext="OK" - yestext="Inspect"/> </notification> <notification @@ -5031,13 +5014,13 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O name="Keep" text="Keep"/> <button - index="4" - name="Show" - text="Show"/> - <button index="1" name="Discard" text="Discard"/> + <button + index="2" + name="Mute" + text="Block"/> </form> </notification> diff --git a/indra/newview/skins/default/xui/en/panel_active_object_row.xml b/indra/newview/skins/default/xui/en/panel_active_object_row.xml new file mode 100644 index 0000000000..7657fb8055 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_active_object_row.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_activeim_row" + layout="topleft" + follows="left|right" + top="0" + left="0" + height="35" + width="318" + background_opaque="false" + background_visible="true" + bg_alpha_color="0.0 0.0 0.0 0.0" > + <string + name="unknown_obj"> + Unknown Object + </string> + <chiclet_script + name="object_chiclet" + layout="topleft" + follows="left" + top="3" + left="5" + height="25" + width="25" + visible="false" + speaker.name="speaker_p2p" + speaker.width="20" + speaker.height="25" + speaker.left="25" + speaker.top="25" + speaker.auto_update="true" + speaker.draw_border="false" + speaker.visible="false"> + </chiclet_script> + <chiclet_offer + name="inv_offer_chiclet" + layout="topleft" + follows="left" + top="3" + left="5" + height="25" + width="25" + visible="false" + speaker.name="speaker_p2p" + speaker.width="20" + speaker.height="25" + speaker.left="25" + speaker.top="25" + speaker.auto_update="true" + speaker.draw_border="false" + speaker.visible="false"> + </chiclet_offer> + <text + type="string" + name="object_name" + layout="topleft" + top="10" + left_pad="20" + height="14" + width="245" + length="1" + follows="right|left" + use_ellipses="true" + font="SansSerifBold"> + Unnamed Object + </text> + <button + top="10" + right="-5" + width="17" + height="17" + layout="topleft" + follows="right" + name="hide_btn" + mouse_opaque="true" + label="" + tab_stop="false" + image_unselected="Toast_CloseBtn" + image_selected="Toast_CloseBtn" + /> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 7f847237ce..034f685ee9 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -114,7 +114,7 @@ width="82" tool_tip="Shows/hides gestures"> <gesture_combo_box.drop_down_button - pad_right="10" + pad_right="10" use_ellipses="true" /> </gesture_combo_box> </layout_panel> @@ -126,7 +126,7 @@ image_name="spacer24.tga" layout="topleft" left="0" - min_width="4" + min_width="4" name="DUMMY" top="0" width="4"/> @@ -168,7 +168,7 @@ image_name="spacer24.tga" layout="topleft" left="0" - min_width="4" + min_width="4" name="DUMMY" top="0" width="4"/> @@ -211,7 +211,7 @@ image_name="spacer24.tga" layout="topleft" left="0" - min_width="4" + min_width="4" name="DUMMY" top="0" width="4"/> @@ -243,7 +243,7 @@ <layout_panel mouse_opaque="false" follows="left|right" - height="28" + height="29" layout="topleft" top="0" name="chiclet_list_panel" @@ -251,24 +251,24 @@ min_width="180" user_resize="false" auto_resize="true"> -<!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same +<!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. EXT-991--> <chiclet_panel mouse_opaque="false" follows="left|right" height="23" layout="topleft" - left="0" + left="1" min_width="180" name="chiclet_list" - top="4" + top="6" chiclet_padding="4" scrolling_offset="40" width="189"> <button auto_resize="true" follows="right" - height="23" + height="29" image_selected="SegmentedBtn_Left_Off" image_unselected="SegmentedBtn_Left_Off" image_hover_selected="SegmentedBtn_Left_Over" @@ -278,14 +278,16 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. image_overlay="Arrow_Small_Left" layout="topleft" name="chicklet_left_scroll_button" + scale_image="true" tab_stop="false" - top="0" + top="-2" + right_pad="2" visible="false" - width="20" /> + width="7" /> <button auto_resize="true" follows="right" - height="23" + height="29" image_selected="SegmentedBtn_Right_Off" image_unselected="SegmentedBtn_Right_Off" image_hover_selected="SegmentedBtn_Right_Over" @@ -295,10 +297,11 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. image_overlay="Arrow_Small_Right" layout="topleft" name="chicklet_right_scroll_button" + scale_image="true" tab_stop="false" - top="0" + top="-2" visible="false" - width="20" /> + width="7" /> </chiclet_panel> </layout_panel> <icon @@ -309,7 +312,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. image_name="spacer24.tga" layout="topleft" left="0" - min_width="4" + min_width="4" top="0" width="5"/> <layout_panel @@ -320,33 +323,44 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. min_height="28" top="0" name="im_well_panel" - width="34" - min_width="34" + width="35" + min_width="35" user_resize="false"> <chiclet_im_well + flash_period="0.3" follows="right" height="23" layout="topleft" left="0" name="im_well" top="4" - width="34"> + width="35"> + <!-- +Emulate 4 states of button by background images, see detains in EXT-3147. The same should be for notification_well button +xml attribute Description +image_unselected "Unlit" - there are no new messages +image_selected "Unlit" + "Selected" - there are no new messages and the Well is open +image_pressed "Lit" - there are new messages +image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open + --> <button auto_resize="true" - flash_color="EmphasisColor" + flash_color="Yellow" follows="right" halign="center" height="23" - image_overlay="Notices_Unread" - image_overlay_alignment="center" - image_pressed="PushButton_Press" - image_pressed_selected="PushButton_Selected_Press" - image_selected="PushButton_Selected_Press" + image_overlay="Unread_IM" + image_overlay_alignment="center" + image_pressed="WellButton_Lit_Selected" + image_pressed_selected="WellButton_Lit" + image_selected="WellButton_Lit" + label_color="Black" left="0" + max_displayed_count="99" name="Unread IM messages" pad_left="0" pad_right="0" - width="34" > + width="35" > <button.init_callback function="Button.SetDockableFloaterToggle" parameter="im_well_window" /> @@ -360,34 +374,38 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. layout="topleft" min_height="28" top="0" + left_pad="4" name="notification_well_panel" - width="34" - min_width="34" + width="35" + min_width="35" user_resize="false"> <chiclet_notification + flash_period="0.25" follows="right" height="23" layout="topleft" left="0" + max_displayed_count="99" name="notification_well" top="4" - width="34"> + width="35"> <button - image_selected="PushButton_Selected_Press" - image_pressed="PushButton_Press" - image_pressed_selected="PushButton_Selected_Press" + bottom_pad="3" + image_selected="WellButton_Lit" + image_pressed="WellButton_Lit_Selected" + image_pressed_selected="WellButton_Lit " auto_resize="true" halign="center" height="23" follows="right" - flash_color="EmphasisColor" - left="0" + flash_color="Yellow" + label_color="Black" + left="5" name="Unread" image_overlay="Notices_Unread" - image_overlay_alignment="center" - pad_right="0" - pad_left="0" - width="34" > + image_overlay_alignment="center" + pad_right="5" + width="35" > <button.init_callback function="Button.SetDockableFloaterToggle" parameter="notification_well_window" /> @@ -401,7 +419,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. height="10" image_name="spacer24.tga" layout="topleft" - min_width="4" + min_width="4" right="-1" top="0" width="4"/> diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index e5dc4df0f8..af73faf9a1 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -23,7 +23,7 @@ Hover your mouse over the options for more help. </panel.string> <text_editor type="string" - follows="left|top" + follows="left|top|right" left="5" height="60" layout="topleft" @@ -37,7 +37,7 @@ Hover your mouse over the options for more help. <name_list column_padding="0" draw_heading="true" - follows="left|top" + follows="left|top|right" heading_height="20" height="156" layout="topleft" @@ -55,10 +55,10 @@ Hover your mouse over the options for more help. relative_width="0.4" /> </name_list> <text - follows="left|top" + follows="left|top|right" type="string" height="12" - layout="topleft" + layout="left|top|right" left="5" name="active_title_label" top_pad="5" @@ -66,7 +66,7 @@ Hover your mouse over the options for more help. My Title </text> <combo_box - follows="left|top" + follows="left|top|right" height="20" layout="topleft" left="5" @@ -98,7 +98,7 @@ Hover your mouse over the options for more help. bevel_style="in" border="true" bg_alpha_color="FloaterUnfocusBorderColor" - follows="left|top" + follows="left|top|right" height="88" layout="topleft" left="2" @@ -106,7 +106,7 @@ Hover your mouse over the options for more help. name="preferences_container" top_pad="2"> <check_box - follows="right|top" + follows="right|top|left" height="16" label="Open enrollment" layout="topleft" @@ -126,21 +126,21 @@ Hover your mouse over the options for more help. width="300" /> <spinner decimal_digits="0" - follows="left|top" + follows="left|top|right" halign="left" height="16" increment="1" label_width="15" label="L$" layout="topleft" - right="-10" + right="-30" max_val="99999" left_pad="0" name="spin_enrollment_fee" tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked." - width="100" /> + width="80" /> <combo_box - follows="left|top" + follows="left|top|right" height="20" layout="topleft" left="10" @@ -158,7 +158,7 @@ Hover your mouse over the options for more help. value="Mature" /> </combo_box> <check_box - follows="left|top" + follows="left|top|right" height="16" initial_value="true" label="Show in search" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index c9db75b5d8..6187b8f1e2 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -33,21 +33,31 @@ name="login_html" start_url="" top="0" height="600" - width="996" /> -<panel + width="980" /> +<layout_stack follows="left|bottom|right" name="login_widgets" layout="topleft" +orientation="horizontal" top="519" width="996" - height="80"> +height="80"> +<layout_panel +auto_resize="false" +follows="left|bottom" +name="login" +layout="topleft" +width="695" +min_width="695" +user_resize="false" +height="80"> <text follows="left|bottom" font="SansSerifSmall" height="16" -left="20" name="first_name_text" top="20" +left="20" width="150"> First name: </text> @@ -145,7 +155,7 @@ name="Typeregionname" value="" /> <combo_box allow_text_entry="true" font="SansSerifSmall" - follows="left|bottom" + follows="left|right|bottom" height="23" layout="topleft" top_pad="2" @@ -164,14 +174,20 @@ width="135" name="connect_btn" top="35" width="90" /> - <text +</layout_panel> +<layout_panel +follows="right|bottom" +name="links" +width="200" +min_width="200" +user_resize="false" +height="80"> + <text follows="right|bottom" font="SansSerifSmall" -text_color="EmphasisColor" halign="right" height="16" top="12" -left_pad="5" right="-10" name="create_new_account_text" width="180"> @@ -183,7 +199,9 @@ font="SansSerifSmall" text_color="EmphasisColor" halign="right" height="16" -name="forgot_password_text" top_pad="12" +name="forgot_password_text" +top_pad="12" +right="-10" width="180"> Forgot your name or password? </text> @@ -195,6 +213,7 @@ halign="right" height="16" name="login_help" top_pad="2" +right="-10" width="180"> Need help logging in? </text> <!-- <text @@ -208,5 +227,6 @@ top_pad="2" word_wrap="true"> [VERSION] </text>--> -</panel> + </layout_panel> +</layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 9990215dfd..4353b306cd 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -17,7 +17,7 @@ text_pad_left="14" follows="left|top|right" height="23" - label="Filter" + label="Filter Inventory" layout="topleft" left="15" max_length="300" diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml index b82a435b41..5217ab3571 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml @@ -17,7 +17,7 @@ height="15" left="10" name="home_label"> - Home URL: + Home Page: </text> <text visible="false" @@ -27,7 +27,7 @@ left_delta="64" text_color="red" name="home_fails_whitelist_label"> - (This URL does not pass the specified whitelist) + (This page does not pass the specified whitelist) </text> <line_editor bottom_delta="-24" @@ -37,7 +37,7 @@ height="20" left="10" name="home_url" - tool_tip="The home URL for this media source" + tool_tip="The home page for this media source" width="340"> <!-- <line_editor.commit_callback function="Media.CommitHomeURL"/> --> @@ -69,9 +69,9 @@ height="15" left="10" name="current_url_label"> - Current URL: + Current Page: </text> - <line_editor + <text bottom_delta="-20" enabled="false" follows="left|top" @@ -79,7 +79,7 @@ height="20" left="10" name="current_url" - tool_tip="The current URL for this media source" + tool_tip="The current page for this media source" value="" width="340" /> <button @@ -93,35 +93,6 @@ <button.commit_callback function="Media.ResetCurrentUrl"/> </button> - <text - bottom_delta="-5" - follows="top|left" - height="15" - left="10" - name="controls_label"> - Controls: - </text> - <combo_box - allow_text_entry="false" - bottom_delta="-20" - follows="left|top" - height="18" - left="10" - max_chars="20" - name="controls" - width="120"> - <combo_item - name="Standard" - value="Standard"> - Standard - </combo_item> - <combo_item - name="Mini" - value="Mini"> - Mini - </combo_item> - </combo_box> - <check_box bottom_delta="-25" enabled="true" @@ -135,7 +106,6 @@ name="auto_loop" radio_style="false" width="150" /> - <check_box bottom_delta="-25" visible="false" diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml index 85f534c4a3..b5c2371510 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml @@ -4,13 +4,42 @@ enabled="true" follows="left|top|right|bottom" height="500" - label="Controls" + label="Customize" left="102" mouse_opaque="true" name="Media settings for controls" help_topic = "media_settings_controls" width="365"> + <text + bottom_delta="-50" + follows="top|left" + height="15" + left="10" + name="controls_label"> + Controls: + </text> + <combo_box + allow_text_entry="false" + bottom_delta="0" + follows="left|top" + height="18" + left="100" + max_chars="20" + name="controls" + width="120"> + <combo_item + name="Standard" + value="Standard"> + Standard + </combo_item> + <combo_item + name="Mini" + value="Mini"> + Mini + </combo_item> + </combo_box> + <text bottom_delta="-50" follows="top|left" @@ -27,7 +56,7 @@ font="SansSerifSmall" height="16" initial_value="false" - label="Disable Navigation & Interactivity" + label="Allow Navigation & Interactivity" left="30" mouse_opaque="true" name="perms_owner_interact" @@ -41,7 +70,7 @@ font="SansSerifSmall" height="16" initial_value="false" - label="Hide Control Bar" + label="Show Control Bar" left="30" mouse_opaque="true" name="perms_owner_control" @@ -74,7 +103,7 @@ font="SansSerifSmall" height="16" initial_value="false" - label="Disable Navigation & Interactivity" + label="Allow Navigation & Interactivity" left="30" mouse_opaque="true" name="perms_group_interact" @@ -88,7 +117,7 @@ font="SansSerifSmall" height="16" initial_value="false" - label="Hide Control Bar" + label="Show Control Bar" left="30" mouse_opaque="true" name="perms_group_control" @@ -111,7 +140,7 @@ font="SansSerifSmall" height="16" initial_value="false" - label="Disable Navigation & Interactivity" + label="Allow Navigation & Interactivity" left="30" mouse_opaque="true" name="perms_anyone_interact" @@ -125,7 +154,7 @@ font="SansSerifSmall" height="16" initial_value="false" - label="Hide Control Bar" + label="Show Control Bar" left="30" mouse_opaque="true" name="perms_anyone_control" diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml index 6e82713f06..1f41a0d284 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml @@ -48,7 +48,7 @@ bottom_delta="0" text_color="0.4 0.4 0.4 1.0" name="home_url_fails_some_items_in_whitelist"> - Entries that the home URL fails against are marked: + Entries that the home page fails against are marked: </text> <button bottom_delta="-36" @@ -82,7 +82,7 @@ left="30" text_color="0.6 0.0 0.0 1.0" name="home_url_fails_whitelist"> -Warning: the home URL specified in the General tab +Warning: the home page specified in the General tab fails to pass this whitelist. It has been disabled until a valid entry has been added. </text> diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml index c02dabed2c..9e7c9477d4 100644 --- a/indra/newview/skins/default/xui/en/panel_notes.xml +++ b/indra/newview/skins/default/xui/en/panel_notes.xml @@ -120,6 +120,7 @@ left="0" mouse_opaque="false" name="add_friend" + tool_tip="Offer friendship to the resident" top="5" width="55" /> <button @@ -128,6 +129,7 @@ label="IM" layout="topleft" name="im" + tool_tip="Open instant message session" top="5" left_pad="5" width="40" /> @@ -137,6 +139,7 @@ label="Call" layout="topleft" name="call" + tool_tip="Call this resident" left_pad="5" top="5" width="55" /> @@ -147,6 +150,7 @@ label="Map" layout="topleft" name="show_on_map_btn" + tool_tip="Show the resident on the map" top="5" left_pad="5" width="50" /> @@ -156,6 +160,7 @@ label="Teleport" layout="topleft" name="teleport" + tool_tip="Offer teleport" left_pad="5" top="5" width="90" /> diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index db95d01b43..ab73f135b9 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -1,61 +1,104 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel name="Outfits" - height="510" - width="333" - follows="top|left" - left="0" - top_pad="0"> - <accordion - single_expansion="true" - height="510" - layout="topleft" - left="0" - follows="top|left" - name="outfits_accordion" - top_pad="0" - width="333"> - <accordion_tab - expanded="false" - layout="topleft" - name="tab_cof" - title="Current Outfit"> - <inventory_panel + + <panel name="Outfits" + background_visible="true" + follows="all" + height="550" + label="Things" + layout="topleft" + min_height="350" + min_width="240" + width="330" + border="false"> + <tab_container + follows="all" + height="500" + layout="topleft" + left="10" + name="appearance_tabs" + tab_min_width="100" + tab_height="30" + tab_position="top" + halign="center" + width="313"> + <inventory_panel + label="MY OUTFITS" + help_topic="my_outfits_tab" allow_multi_select="true" + follows="all" border="false" - height="460" - left="0" - top="0" - mouse_opaque="true" - name="cof_accordionpanel" - start_folder="Current Outfit" /> - </accordion_tab> - <accordion_tab - expanded="true" - layout="topleft" - name="tab_outfits" - title="My Outfits"> - <inventory_panel - allow_multi_select="true" - border="false" - follows="all" - left="0" - top="0" - height="460" - mouse_opaque="true" - name="outfitslist_accordionpanel" - start_folder="My Outfits" /> - </accordion_tab> - </accordion> - <!--<button bottom="0" - halign="center" - height="23" - label=">" - enabled="false" - mouse_opaque="false" - name="selector" - width="20" - left="0" - visible="false" - follows="right|bottom" - tool_tip="View outfit properties" />--> + left="0" + top="0" + height="500" + width="290" + mouse_opaque="true" + name="outfitslist_accordionpanel" + start_folder="My Outfits" /> + <inventory_panel + label="WEARING" + help_topic="now_wearing_tab" + allow_multi_select="true" + border="false" + height="500" + width="290" + left="0" + top="0" + mouse_opaque="true" + name="cof_accordionpanel" + start_folder="Current Outfit" /> + </tab_container> + <panel + background_visible="true" + follows="bottom|left" + height="50" + layout="topleft" + left="0" + visible="true" + name="bottom_panel" + top_pad="10" + width="313"> + <button + follows="bottom|left" + tool_tip="Show additional options" + height="18" + image_disabled="OptionsMenu_Disabled" + image_selected="OptionsMenu_Press" + image_unselected="OptionsMenu_Off" + layout="topleft" + left="10" + name="options_gear_btn" + top="6" + width="18" /> + <button + follows="bottom|left" + height="18" + image_selected="AddItem_Press" + image_unselected="AddItem_Off" + image_disabled="AddItem_Disabled" + layout="topleft" + left_pad="5" + name="add_btn" + tool_tip="Add new item" + width="18" /> + <dnd_button + follows="bottom|left" + height="18" + image_selected="TrashItem_Press" + image_unselected="TrashItem_Off" + layout="topleft" + right="-5" + name="trash_btn" + tool_tip="Remove selected item" + top="6" + width="18" /> + <button + follows="top|left" + height="23" + label="Wear" + layout="topleft" + name="wear_btn" + right="-5" + top_pad="0" + width="90" /> + </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 88df529ec1..d4a6c7f3b3 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -22,7 +22,7 @@ background_visible="true" height="23" layout="topleft" left="15" - label="Filter" + label="Filter Places" max_length="300" name="Filter" top="3" @@ -77,6 +77,7 @@ background_visible="true" layout="topleft" left="5" name="teleport_btn" + tool_tip="Teleport to the selected area" top="0" width="100" /> <button @@ -86,6 +87,7 @@ background_visible="true" layout="topleft" left_pad="5" name="map_btn" + tool_tip="Show selected area on the map" top="0" width="70" /> <button diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 78b90eefcc..405ff02836 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -284,7 +284,7 @@ Avatars: enabled_control="EnableVoiceChat" control_name="PushToTalkToggle" height="20" - label="Toggle mode for microphone when I press the speak trigger key:" + label="Toggle mode for microphone when I press the Speak trigger key:" layout="topleft" left="30" name="push_to_talk_toggle_check" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 8aba8b9dd1..b5c6b637e5 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -92,11 +92,7 @@ name="(Japanese)" value="ja" /> - <combo_box.item - enabled="true" - label="Test Language" - name="TestLanguage" - value="test" /> + </combo_box> <text type="string" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index a7def5306e..a65f7d3a54 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -3,7 +3,7 @@ border="true" follows="left|top|right|bottom" height="408" - label="Input & Camera" + label="Setup" layout="topleft" left="102" name="Input panel" @@ -223,7 +223,7 @@ follows="left|top" height="23" label="Reset" - label_selected="Set" + label_selected="Reset" layout="topleft" left_pad="3" name="reset_cache" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index 102a53ad90..d8e3f4ccfb 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -348,23 +348,24 @@ label="Input/Output devices" layout="topleft" left="30" - top="270" + top="262" name="device_settings_btn" width="190"> </button> <panel - background_visible="true" + background_visible="false" bg_alpha_color="DkGray" visiblity_control="ShowDeviceSettings" border="false" follows="top|left" - height="145" + height="120" label="Device Settings" layout="topleft" left="0" name="device_settings_panel" class="panel_voice_device_settings" - width="501"> + width="501" + top="285"> <panel.string name="default_text"> Default @@ -397,7 +398,7 @@ left="165" max_chars="128" name="voice_input_device" - top_pad="0" + top_pad="-2" width="200" /> <text type="string" @@ -407,7 +408,7 @@ layout="topleft" left="165" name="My volume label" - top_pad="10" + top_pad="5" width="200"> My volume: </text> @@ -422,7 +423,7 @@ max_val="2" name="mic_volume_slider" tool_tip="Change the volume using this slider" - top_pad="0" + top_pad="-2" width="220" /> <text type="string" @@ -442,7 +443,7 @@ layout="topleft" left_delta="0" name="bar0" - top_delta="5" + top_delta="0" width="20" /> <locate height="20" @@ -472,16 +473,6 @@ name="bar4" top_delta="0" width="20" /> - <!-- <text - type="string" - height="37" - left="30" - name="voice_intro_text1" - top_pad="-4" - width="410" - word_wrap="true"> - Adjust the slider to control how loud you sound to other people. To test your volume, simply speak into your microphone - </text>--> <icon height="18" image_name="Parcel_Voice_Light" @@ -510,7 +501,7 @@ left="165" max_chars="128" name="voice_output_device" - top_pad="0" + top_pad="-2" width="200" /> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index e21de31498..bffb28d16e 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -9,7 +9,7 @@ width="800"> <string name="control_background_image_name">Inspector_Background</string> <string name="skip_step">0.2</string> - <string name="min_width">400</string> + <string name="min_width">300</string> <string name="min_height">120</string> <string name="zoom_near_padding">1.0</string> <string name="zoom_medium_padding">1.25</string> @@ -190,7 +190,7 @@ layout="topleft" top="14" min_width="22" - width="22"> + width="24"> <button image_overlay="Play_Off" image_disabled="PushButton_Disabled" @@ -200,6 +200,8 @@ hover_glow_amount="0.15" layout="topleft" tool_tip = "Play media" + left_delta="2" + top="4" height="22" min_width="22" width="22"> @@ -214,7 +216,7 @@ layout="topleft" top="18" min_width="22" - width="22"> + width="24"> <button image_overlay="Pause_Off" image_disabled="PushButton_Disabled" @@ -224,6 +226,9 @@ hover_glow_amount="0.15" layout="topleft" height="22" + width="22" + left_delta="-1" + top="4" tool_tip = "Pause media"> <button.commit_callback function="MediaCtrl.Pause" /> @@ -380,7 +385,7 @@ image_selected="AudioMute_Off" image_unselected="Audio_Off" hover_glow_amount="0.15" - name="media_volume_button" + name="media_mute_button" height="22" is_toggle="true" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 6be203ef9c..638bc3cabd 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -286,6 +286,7 @@ left="0" mouse_opaque="false" name="add_friend" + tool_tip="Offer friendship to the resident" top="5" width="77" /> <button @@ -294,6 +295,7 @@ label="IM" layout="topleft" name="im" + tool_tip="Open instant message session" top="5" left_pad="5" width="33" /> @@ -303,6 +305,7 @@ label="Call" layout="topleft" name="call" + tool_tip="Call this resident" left_pad="5" top="5" width="40" /> @@ -313,6 +316,7 @@ label="Map" layout="topleft" name="show_on_map_btn" + tool_tip="Show the resident on the map" top="5" left_pad="5" width="44" /> @@ -322,6 +326,7 @@ label="Teleport" layout="topleft" name="teleport" + tool_tip="Offer teleport" left_pad="5" top="5" width="67" /> @@ -331,6 +336,7 @@ label="▼" layout="topleft" name="overflow_btn" + tool_tip="Pay money to or share inventory with the resident" right="-1" top="5" width="21" /> diff --git a/indra/newview/skins/default/xui/en/panel_region_covenant.xml b/indra/newview/skins/default/xui/en/panel_region_covenant.xml index 75d7d85505..ff55090f16 100644 --- a/indra/newview/skins/default/xui/en/panel_region_covenant.xml +++ b/indra/newview/skins/default/xui/en/panel_region_covenant.xml @@ -3,6 +3,7 @@ border="true" follows="top|left" height="320" + help_topic="panel_region_covenant_tab" label="Covenant" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_debug.xml b/indra/newview/skins/default/xui/en/panel_region_debug.xml index e07585d285..a6b4ddd01e 100644 --- a/indra/newview/skins/default/xui/en/panel_region_debug.xml +++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml @@ -3,6 +3,7 @@ border="true" follows="top|left" height="320" + help_topic="panel_region_debug_tab" label="Debug" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml index e25ff0d548..ba39e88024 100644 --- a/indra/newview/skins/default/xui/en/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml @@ -3,16 +3,13 @@ border="false" follows="top|left" height="320" + help_topic="panel_region_estate_tab" label="Estate" layout="topleft" left="0" name="Estate" top="320" width="480"> - <panel.string - name="email_unsupported"> - Feature unsupported - </panel.string> <text type="string" length="1" @@ -81,7 +78,7 @@ regions in the estate. <view_border bevel_style="in" follows="top|left" - height="310" + height="270" layout="topleft" left_delta="-4" top_pad="5" @@ -141,12 +138,12 @@ regions in the estate. name="Only Allow" top="250" width="278"> - Restrict Access To: + Restrict Access to Accounts Verified by: </text> <check_box follows="top|left" height="16" - label="Residents with payment info on file" + label="Payment Information on File" layout="topleft" left_delta="0" name="limit_payment" @@ -156,7 +153,7 @@ regions in the estate. <check_box follows="top|left" height="16" - label="Age-verified adults" + label="Age Verification" layout="topleft" left_delta="0" name="limit_age_verified" @@ -179,26 +176,6 @@ regions in the estate. name="allow_direct_teleport" top_pad="4" width="80" /> - <text - type="string" - length="1" - follows="left|top" - height="20" - layout="topleft" - left="15" - name="abuse_email_text" - top_pad="10" - width="180"> - Abuse email address: - </text> - <line_editor - follows="top|left" - height="23" - layout="topleft" - left="15" - name="abuse_email_address" - top_pad="-5" - width="230" /> <button enabled="false" follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml index 79d8f3a0ee..26568c2a28 100644 --- a/indra/newview/skins/default/xui/en/panel_region_general.xml +++ b/indra/newview/skins/default/xui/en/panel_region_general.xml @@ -3,6 +3,7 @@ border="true" follows="top|left" height="320" + help_topic="panel_region_general_tab" label="Region" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index ffd51bf510..5093c52129 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -3,6 +3,7 @@ border="true" follows="top|left" height="320" + help_topic="panel_region_terrain_tab" label="Terrain" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_texture.xml b/indra/newview/skins/default/xui/en/panel_region_texture.xml index 5089064c07..a4d24cb0fc 100644 --- a/indra/newview/skins/default/xui/en/panel_region_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_region_texture.xml @@ -3,6 +3,7 @@ border="true" follows="top|left" height="320" + help_topic="panel_region_texture_tab" label="Ground Textures" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml index 32fc9fce01..06da64533b 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml @@ -151,7 +151,7 @@ <button follows="bottom|left" font="SansSerifBigBold" - tool_tip="" + tool_tip="Show additional optioins" height="18" image_disabled="OptionsMenu_Disabled" image_selected="OptionsMenu_Press" diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index 3dac1a9614..27f19d44fa 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -85,72 +85,21 @@ left="0" class="panel_outfits_inventory" filename="panel_outfits_inventory.xml" name="panel_outfits_inventory" - height="510" + height="550" min_height="510" width="333" top_pad="0" - follows="top|left" + follows="all" /> - <panel - visible="true" - name="bottom_panel" - height="50" - left="0" - top_pad="3" - follows="bottom|left" - width="333"> - <button - follows="bottom|left" - tool_tip="Show additional options" - height="18" - image_disabled="OptionsMenu_Disabled" - image_selected="OptionsMenu_Press" - image_unselected="OptionsMenu_Off" - layout="topleft" - left="10" - name="options_gear_btn" - top="6" - width="18" /> - <button - follows="bottom|left" - height="18" - image_selected="AddItem_Press" - image_unselected="AddItem_Off" - image_disabled="AddItem_Disabled" - layout="topleft" - left_pad="5" - name="newlook_btn" - tool_tip="Add new outfit" - width="18" /> - <dnd_button - follows="bottom|left" - height="18" - image_selected="TrashItem_Press" - image_unselected="TrashItem_Off" - layout="topleft" - right="-5" - name="trash_btn" - tool_tip="Remove selected item" - top="6" - width="18" /> - <button - follows="bottom|left" - height="23" - label="Wear" - layout="topleft" - name="wear_btn" - right="-5" - top_pad="0" - width="90" /> - </panel> - <!-- <button - follows="bottom|left" - height="23" - label="New outfit" - layout="topleft" - left_pad="5" - right="-10" - width="100" />--> + <!-- <button + follows="bottom|left" + height="23" + label="New outfit" + layout="topleft" + left_pad="5" + right="-10" + name="newlook_btn" + width="100" />--> <panel class="panel_look_info" filename="panel_look_info.xml" @@ -167,4 +116,5 @@ left="0" left="0" name="panel_edit_wearable" visible="false" /> -</panel>
\ No newline at end of file +</panel> + diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index db8a844eb0..e04af2bad6 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -39,26 +39,38 @@ top="4" width="18" /> <button - follows="top|right" - height="25" - image_overlay="BackArrow_Off" - layout="topleft" - name="back_btn" - picture_style="true" - right="-5" - tab_stop="false" - top="0" - width="25" /> + follows="top|right" + height="23" + image_overlay="BackArrow_Off" + layout="topleft" + left="10" + name="back_btn" + tab_stop="false" + top="0" + width="23" /> + <text + follows="top|left|right" + font="SansSerifHugeBold" + height="26" + layout="topleft" + left_pad="10" + name="title" + text_color="white" + top="0" + use_ellipses="true" + value="Item Properties" + width="275" /> <panel follows="all" height="500" label="" layout="topleft" - left="5" + left="10" help_topic="" top="30" - border="1" - width="313"> + width="313" + background_visible="true" + bg_alpha_color="DkGray2"> <text type="string" length="1" @@ -98,7 +110,7 @@ border_style="line" border_thickness="1" follows="left|top|right" - height="16" + height="23" layout="topleft" left_delta="78" max_length="127" @@ -109,7 +121,7 @@ type="string" length="1" follows="left|top" - height="16" + height="23" layout="topleft" left="10" name="LabelCreatorTitle" @@ -121,7 +133,7 @@ type="string" length="1" follows="left|top" - height="16" + height="23" layout="topleft" left_delta="78" name="LabelCreatorName" @@ -131,7 +143,7 @@ </text> <button follows="top|right" - height="16" + height="23" label="Profile..." layout="topleft" left_delta="144" @@ -142,7 +154,7 @@ type="string" length="1" follows="left|top" - height="16" + height="23" layout="topleft" left="10" name="LabelOwnerTitle" @@ -154,7 +166,7 @@ type="string" length="1" follows="left|top" - height="16" + height="23" layout="topleft" left_delta="78" name="LabelOwnerName" @@ -164,7 +176,7 @@ </text> <button follows="top|right" - height="16" + height="23" label="Profile..." layout="topleft" left_delta="144" @@ -175,7 +187,7 @@ type="string" length="1" follows="left|top" - height="16" + height="23" layout="topleft" left="10" name="LabelAcquiredTitle" @@ -187,7 +199,7 @@ type="string" length="1" follows="left|top" - height="16" + height="23" layout="topleft" left_delta="78" name="LabelAcquiredDate" @@ -199,7 +211,7 @@ type="string" length="1" follows="left|top" - height="10" + height="23" layout="topleft" left="10" name="OwnerLabel" @@ -208,7 +220,7 @@ You: </text> <check_box - height="16" + height="23" label="Edit" layout="topleft" left_pad="5" @@ -216,7 +228,7 @@ top_delta="0" width="78" /> <check_box - height="16" + height="23" label="Copy" layout="topleft" left_delta="0" @@ -224,7 +236,7 @@ top_pad="5" width="88" /> <check_box - height="16" + height="23" label="Resell" layout="topleft" left_delta="0" @@ -480,40 +492,4 @@ Price: L$ </text--> </panel> - <panel - height="25" - layout="bottomright" - help_topic="button_tab" - name="button_panel" - left="5" - bottom="5" - width="313"> - <button - follows="bottom|left" - height="25" - label="Edit" - layout="topleft" - left="0" - name="edit_btn" - top="0" - width="50" /> - <button - follows="bottom|right" - height="25" - label="Cancel" - layout="topleft" - name="cancel_btn" - right="-1" - top="0" - width="70" /> - <button - follows="bottom|right" - height="25" - label="Save" - layout="topleft" - name="save_btn" - left_pad="-135" - top="0" - width="60" /> - </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 348f0dfc09..5b379b54e3 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -482,21 +482,12 @@ left="5" bottom="5" width="313"> - <button - follows="bottom|left" - height="25" - label="Edit" - layout="topleft" - left="0" - name="edit_btn" - top="0" - width="50" /> - <button + <button follows="bottom|left" height="25" label="Open" layout="topleft" - left_pad="5" + left="5" name="open_btn" top="0" width="60" /> @@ -518,23 +509,5 @@ name="buy_btn" top="0" width="60" /> - <button - follows="bottom|right" - height="25" - label="Cancel" - layout="topleft" - name="cancel_btn" - right="-1" - top="0" - width="70" /> - <button - follows="bottom|right" - height="25" - label="Save" - layout="topleft" - name="save_btn" - left_pad="-135" - top="0" - width="60" /> </panel> </panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d5022de089..2f50c5ee6c 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -812,7 +812,7 @@ Preloads a sound on viewers within range </string> <string name="LSLTipText_llRotLookAt" translate="false"> llRotLookAt(rotation target, float strength, float damping) -Causes object name to point its forward axis towards target +Causes object to point its forward axis towards target </string> <string name="LSLTipText_llStringLength" translate="false"> integer llStringLength(string str) @@ -1471,7 +1471,7 @@ Returns the requested permission mask for the root object the task is attached t </string> <string name="LSLTipText_llSetObjectPermMask" translate="false"> llSetObjectPermMask(integer mask, integer value) -Sets the given permission mask to the new value on the root object the task is attached to +Sets the given permission mask to the new value on the root object the task is attached to (requires God Mode) </string> <string name="LSLTipText_llGetInventoryPermMask" translate="false"> integer llGetInventoryPermMask(string item, integer mask) @@ -1479,7 +1479,7 @@ Returns the requested permission mask for the inventory item </string> <string name="LSLTipText_llSetInventoryPermMask" translate="false"> llSetInventoryPermMask(string item, integer mask, integer value) -Sets the given permission mask to the new value on the inventory item +Sets the given permission mask to the new value on the inventory item (requires God Mode) </string> <string name="LSLTipText_llGetInventoryCreator" translate="false"> key llGetInventoryCreator(string item) @@ -2112,6 +2112,10 @@ this texture in your inventory Unknown file extension .%s Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh </string> + <string name="MuteObject">Block</string> + <string name="MuteAvatar">Block</string> + <string name="UnmuteObject">Unblock</string> + <string name="UnmuteAvatar">Unblock</string> <string name="AddLandmarkNavBarMenu">Add to My Landmarks...</string> <string name="EditLandmarkNavBarMenu">Edit my Landmark...</string> @@ -2856,6 +2860,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="inventory_item_offered-im"> Inventory item offered </string> + <string name="share_alert"> + Drag items from inventory here + </string> + <string name="only_user_message"> You are the only user in this session. @@ -2869,6 +2877,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="muted_message"> You have blocked this resident. Sending a message will automatically unblock them. </string> + <!--Some times string name is getting from the body of server response. + For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post. + In case of the EXT-3115 issue 'generic' is passed into the gIMMgr::showSessionStartError as a string name. + Also there are some other places where "generic" is used. + So, let add string with name="generic" with the same value as "generic_request_error" --> + <string name="generic"> + Error making request, please try again later. + </string> <string name="generic_request_error"> Error making request, please try again later. </string> @@ -2896,6 +2912,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="message_session_event"> Unable to send your message to the chat session with [RECIPIENT]. </string> + <string name="mute"> + Error while moderating. + </string> <string name="removed_from_group"> You have been removed from the group. </string> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml index 9990324d03..102dc0c16d 100644 --- a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml @@ -8,7 +8,7 @@ header_image="Accordion_Off" header_image_over="Accordion_Over" header_image_pressed="Accordion_Press" - header_image_expanded="Accordion_Selected" + header_image_focused="Accordion_Selected" header_text_color="LtGray" font="SansSerif" /> diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml index 28ed560543..d7aa71a441 100644 --- a/indra/newview/skins/default/xui/en/widgets/button.xml +++ b/indra/newview/skins/default/xui/en/widgets/button.xml @@ -18,5 +18,6 @@ font="SansSerifSmall" hover_glow_amount="0.15" halign="center" + pad_bottom="2" scale_image="true"> </button> diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index 19fb520b44..85d0c633af 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -9,8 +9,6 @@ background_visible="true" background_opaque="false" header_height="25" - top="0" - left="0" close_image="Icon_Close_Foreground" restore_image="Icon_Restore_Foreground" minimize_image="Icon_Minimize_Foreground" diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp index 4759c7dc91..ca7d02fc68 100644 --- a/indra/newview/tests/llcapabilitylistener_test.cpp +++ b/indra/newview/tests/llcapabilitylistener_test.cpp @@ -50,6 +50,7 @@ #include "tests/networkio.h" #include "tests/commtest.h" #include "tests/wrapllerrs.h" +#include "message.h" #include "stringize.h" #if defined(LL_WINDOWS) diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp index 6ff2c9446e..33d413bd21 100644 --- a/indra/newview/tests/llmediadataclient_test.cpp +++ b/indra/newview/tests/llmediadataclient_test.cpp @@ -75,15 +75,13 @@ <string>baz</string> \ </array>" -#define _DATA_URLS(ID,DIST,INT,URL1,URL2) " \ +#define _DATA_URLS(ID,INTEREST,NEW,URL1,URL2) " \ <llsd> \ <map> \ <key>uuid</key> \ <string>" ID "</string> \ - <key>distance</key> \ - <real>" DIST "</real> \ <key>interest</key> \ - <real>" INT "</real> \ + <real>" INTEREST "</real> \ <key>cap_urls</key> \ <map> \ <key>ObjectMedia</key> \ @@ -93,21 +91,26 @@ </map> \ <key>media_data</key> \ " MEDIA_DATA " \ + <key>is_dead</key> \ + <boolean>false</boolean> \ + <key>is_new</key> \ + <boolean>" NEW "</boolean> \ </map> \ </llsd>" -#define _DATA(ID,DIST,INT) _DATA_URLS(ID,DIST,INT,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL) +#define _DATA(ID,INTEREST,NEW) _DATA_URLS(ID,INTEREST,NEW,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL) -const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","1.0"); +const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true"); #define STR(I) boost::lexical_cast<std::string>(I) #define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" << \ "================================================================================\n" << \ -"===================================== TEST " #N " ===================================\n" << \ +"==================================== TEST " #N " ===================================\n" << \ "================================================================================\n" << LL_ENDL; LLSD *gPostRecords = NULL; +F64 gMinimumInterestLevel = (F64)0.0; // stubs: void LLHTTPClient::post( @@ -125,21 +128,20 @@ void LLHTTPClient::post( gPostRecords->append(record); // Magic URL that triggers a 503: + LLSD result; + result[LLTextureEntry::OBJECT_ID_KEY] = body[LLTextureEntry::OBJECT_ID_KEY]; if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 ) { responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason"); + return; } else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) { - LLSD result; LLSD error; error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE; result["error"] = error; - responder->result(result); - } - else { - responder->result(LLSD()); - } + } + responder->result(result); } const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; @@ -152,13 +154,12 @@ public: std::istringstream d(data); LLSDSerialize::fromXML(mRep, d); mNumBounceBacks = 0; - mDead = false; // std::cout << ll_pretty_print_sd(mRep) << std::endl; // std::cout << "ID: " << getID() << std::endl; } LLMediaDataClientObjectTest(const LLSD &rep) - : mRep(rep), mNumBounceBacks(0), mDead(false) {} + : mRep(rep), mNumBounceBacks(0) {} ~LLMediaDataClientObjectTest() { LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; } @@ -169,43 +170,47 @@ public: virtual LLUUID getID() const { return mRep["uuid"]; } virtual void mediaNavigateBounceBack(U8 index) - { - mNumBounceBacks++; - } + { mNumBounceBacks++; } virtual bool hasMedia() const { return mRep.has("media_data"); } - virtual void updateObjectMediaData(LLSD const &media_data_array) - { mRep["media_data"] = media_data_array; } + virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &media_version) + { mRep["media_data"] = media_data_array; mRep["media_version"] = media_version; } + + virtual F64 getMediaInterest() const + { return (LLSD::Real)mRep["interest"]; } - virtual F64 getDistanceFromAvatar() const - { return (LLSD::Real)mRep["distance"]; } + virtual bool isInterestingEnough() const + { return getMediaInterest() > gMinimumInterestLevel; } - virtual F64 getTotalMediaInterest() const - { return (LLSD::Real)mRep["interest"]; } - virtual std::string getCapabilityUrl(const std::string &name) const { return mRep["cap_urls"][name]; } virtual bool isDead() const - { return mDead; } - - void setDistanceFromAvatar(F64 val) - { mRep["distance"] = val; } + { return mRep["is_dead"]; } + + virtual U32 getMediaVersion() const + { return (LLSD::Integer)mRep["media_version"]; } + + virtual bool isNew() const + { return mRep["is_new"]; } - void setTotalMediaInterest(F64 val) + void setMediaInterest(F64 val) { mRep["interest"] = val; } int getNumBounceBacks() const { return mNumBounceBacks; } void markDead() - { mDead = true; } + { mRep["is_dead"] = true; } + + void markOld() + { mRep["is_new"] = false; } + private: LLSD mRep; int mNumBounceBacks; - bool mDead; }; // This special timer delay should ensure that the timer will fire on the very @@ -224,10 +229,11 @@ namespace tut { mediadataclient() { gPostRecords = &mLLSD; + gMinimumInterestLevel = (F64)0.0; - //LLError::setDefaultLevel(LLError::LEVEL_DEBUG); - //LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG); - //LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG); +// LLError::setDefaultLevel(LLError::LEVEL_DEBUG); +// LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG); +// LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG); } LLSD mLLSD; }; @@ -378,11 +384,11 @@ namespace tut LOG_TEST(4); LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest( - _DATA(VALID_OBJECT_ID_1,"3.0","1.0")); + _DATA(VALID_OBJECT_ID_1,"1.0","true")); LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest( - _DATA(VALID_OBJECT_ID_2,"1.0","1.0")); + _DATA(VALID_OBJECT_ID_2,"3.0","true")); LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest( - _DATA(VALID_OBJECT_ID_3,"2.0","1.0")); + _DATA(VALID_OBJECT_ID_3,"2.0","true")); { LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 }; @@ -428,8 +434,7 @@ namespace tut LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest( _DATA_URLS(VALID_OBJECT_ID, - "1.0", - "1.0", + "1.0","true", FAKE_OBJECT_MEDIA_CAP_URL_503, FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)); int num_refs_start = o->getNumRefs(); @@ -484,8 +489,7 @@ namespace tut LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest( _DATA_URLS(VALID_OBJECT_ID, - "1.0", - "1.0", + "1.0","true", FAKE_OBJECT_MEDIA_CAP_URL, FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)); { @@ -517,9 +521,9 @@ namespace tut LOG_TEST(7); LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest( - _DATA(VALID_OBJECT_ID_1,"3.0","1.0")); + _DATA(VALID_OBJECT_ID_1,"3.0","true")); LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest( - _DATA(VALID_OBJECT_ID_2,"1.0","1.0")); + _DATA(VALID_OBJECT_ID_2,"1.0","true")); int num_refs_start = o1->getNumRefs(); { LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); @@ -551,10 +555,10 @@ namespace tut // Test queue handling of objects that are marked dead. LOG_TEST(8); - LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","1.0")); - LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","1.0")); - LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","1.0")); - LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","1.0")); + LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"4.0","true")); + LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"3.0","true")); + LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"2.0","true")); + LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"1.0","true")); { LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); @@ -616,10 +620,11 @@ namespace tut // LOG_TEST(9); - LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"10.0","1.0")); - LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"20.0","1.0")); - LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"30.0","1.0")); - LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"40.0","1.0")); + LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"40.0","true")); + LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"30.0","true")); + LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"20.0","true")); + LLMediaDataClientObjectTest *object4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"10.0","true")); + LLMediaDataClientObject::ptr_t o4 = object4; { LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); @@ -630,53 +635,52 @@ namespace tut mdc->fetchMedia(o3); mdc->fetchMedia(o4); - int test_num = 0; + int tick_num = 0; - ensure(STR(test_num) + ". is in queue 1", mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 0); + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); ::pump_timers(); - ++test_num; + ++tick_num; // The first tick should remove the first one - ensure(STR(test_num) + ". is not in queue 1", !mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 1); + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); // Now, pretend that object 4 moved relative to the avatar such // that it is now closest - static_cast<LLMediaDataClientObjectTest*>( - static_cast<LLMediaDataClientObject*>(o4))->setDistanceFromAvatar(5.0); + object4->setMediaInterest(50.0); ::pump_timers(); - ++test_num; + ++tick_num; // The second tick should still pick off item 2, but then re-sort // have picked off object 4 - ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is not in queue 4", !mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 2); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); ::pump_timers(); - ++test_num; + ++tick_num; // The third tick should pick off object 2 - ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 3); + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); // The fourth tick should pick off object 3 ::pump_timers(); - ++test_num; + ++tick_num; - ensure(STR(test_num) + ". is not in queue 3", !mdc->isInQueue(o3)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 4); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); ensure("queue empty", mdc->isEmpty()); } @@ -686,4 +690,249 @@ namespace tut ensure("refcount of o4", o4->getNumRefs(), 1); } + + template<> template<> + void mediadataclient_object_t::test<10>() + { + // + // Test using the "round-robin" queue + // + LOG_TEST(10); + + LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true")); + LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true")); + LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","false")); + LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","false")); + { + LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); + + // queue up all 4 objects. The first two should be in the sorted + // queue [2 1], the second in the round-robin queue. The queues + // are serviced interleaved, so we should expect: + // 2, 4, 1, 3 + mdc->fetchMedia(o1); + mdc->fetchMedia(o2); + mdc->fetchMedia(o3); + mdc->fetchMedia(o4); + + int tick_num = 0; + + // 0 + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); + + ::pump_timers(); + ++tick_num; + + // 1 The first tick should remove object 2 + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2)); + + ::pump_timers(); + ++tick_num; + + // 2 The second tick should send object 4, but it will still be + // "in the queue" + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); + + ::pump_timers(); + ++tick_num; + + // 3 The third tick should remove object 1 + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); + + ::pump_timers(); + ++tick_num; + + // 4 The fourth tick should send object 3, but it will still be + // "in the queue" + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); + + ::pump_timers(); + ++tick_num; + + // 5 The fifth tick should now identify objects 3 and 4 as no longer + // needing "updating", and remove them from the queue + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); + + ::pump_timers(); + + // Whew....better be empty + ensure("queue empty", mdc->isEmpty()); + } + ensure("refcount of o1", o1->getNumRefs(), 1); + ensure("refcount of o2", o2->getNumRefs(), 1); + ensure("refcount of o3", o3->getNumRefs(), 1); + ensure("refcount of o4", o4->getNumRefs(), 1); + } + + + template<> template<> + void mediadataclient_object_t::test<11>() + { + // + // Test LLMediaDataClient's destructor + // + LOG_TEST(11); + + LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); + int num_refs_start = o->getNumRefs(); + { + LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); + mdc->fetchMedia(o); + // must tick enough times to clear refcount of mdc + ::pump_timers(); + } + // Make sure everyone's destroyed properly + ensure("REF COUNT", o->getNumRefs(), num_refs_start); + } + + template<> template<> + void mediadataclient_object_t::test<12>() + { + // + // Test the "not interesting enough" call + // + LOG_TEST(12); + + LLMediaDataClientObjectTest *object1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true")); + LLMediaDataClientObject::ptr_t o1 = object1; + LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true")); + LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","true")); + LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","true")); + { + LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); + + // queue up all 4 objects. The first two are "interesting enough". + // Firing the timer 4 times should therefore leave them. + // Note that they should be sorted 4,3,2,1 + // Then, we'll make one "interesting enough", fire the timer a few + // times, and make sure only it gets pulled off the queue + gMinimumInterestLevel = 2.5; + mdc->fetchMedia(o1); + mdc->fetchMedia(o2); + mdc->fetchMedia(o3); + mdc->fetchMedia(o4); + + int tick_num = 0; + + // 0 + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); + + ::pump_timers(); + ++tick_num; + + // 1 The first tick should remove object 4 + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); + + ::pump_timers(); + ++tick_num; + + // 2 The second tick should send object 3 + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); + + ::pump_timers(); + ++tick_num; + + // 3 The third tick should not pull off anything + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + + ::pump_timers(); + ++tick_num; + + // 4 The fourth tick (for good measure) should not pull off anything + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + + // Okay, now futz with object 1's interest, such that it is now + // "interesting enough" + object1->setMediaInterest((F64)5.0); + + // This should sort so that the queue is now [1 2] + ::pump_timers(); + ++tick_num; + + // 5 The fifth tick should now identify objects 3 and 4 as no longer + // needing "updating", and remove them from the queue + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); + + ::pump_timers(); + ++tick_num; + + // 6 The sixth tick should not pull off anything + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); + + ::pump_timers(); + ++tick_num; + + // Whew....better NOT be empty ... o2 should still be there + ensure("queue not empty", !mdc->isEmpty()); + + // But, we need to clear the queue, or else we won't destroy MDC... + // this is a strange interplay between the queue timer and the MDC + ensure("o2 couldn't be removed from queue", mdc->removeFromQueue(o2)); + // tick + ::pump_timers(); + } + ensure("refcount of o1", o1->getNumRefs(), 1); + ensure("refcount of o2", o2->getNumRefs(), 1); + ensure("refcount of o3", o3->getNumRefs(), 1); + ensure("refcount of o4", o4->getNumRefs(), 1); + } } diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp index 68743357a6..ec612c4606 100644 --- a/indra/newview/tests/llviewerhelputil_test.cpp +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -36,54 +36,59 @@ #include "../test/lltut.h" #include "../llviewerhelputil.h" -#include "../llversioninfo.h" +#include "../llweb.h" #include "llcontrol.h" -#include "llsys.h" #include <iostream> -//---------------------------------------------------------------------------- -// Implementation of enough of LLControlGroup to support the tests: +// values for all of the supported substitutions parameters +static std::string gHelpURL; +static std::string gVersion; +static std::string gChannel; +static std::string gLanguage; +static std::string gGrid; +static std::string gOS; -static std::map<std::string,std::string> test_stringvec; +//---------------------------------------------------------------------------- +// Mock objects for the dependencies of the code we're testing LLControlGroup::LLControlGroup(const std::string& name) - : LLInstanceTracker<LLControlGroup, std::string>(name) -{ -} - -LLControlGroup::~LLControlGroup() -{ -} - -// Implementation of just the LLControlGroup methods we requre + : LLInstanceTracker<LLControlGroup, std::string>(name) {} +LLControlGroup::~LLControlGroup() {} BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, - BOOL persist) -{ - test_stringvec[name] = initial_val; - return true; -} - -void LLControlGroup::setString(const std::string& name, const std::string& val) + BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} +std::string LLControlGroup::getString(const std::string& name) { - test_stringvec[name] = val; + if (name == "HelpURLFormat") + return gHelpURL; + return ""; } +LLControlGroup gSavedSettings("test"); -std::string LLControlGroup::getString(const std::string& name) +static void substitute_string(std::string &input, const std::string &search, const std::string &replace) { - return test_stringvec[name]; + size_t pos = input.find(search); + while (pos != std::string::npos) + { + input = input.replace(pos, search.size(), replace); + pos = input.find(search); + } } -S32 LLVersionInfo::getMajor() { return 2; } -S32 LLVersionInfo::getMinor() { return 0; } -S32 LLVersionInfo::getPatch() { return 0; } -S32 LLVersionInfo::getBuild() { return 200099; } -const std::string &LLVersionInfo::getVersion() +std::string LLWeb::expandURLSubstitutions(const std::string &url, + const LLSD &default_subs) { - static std::string version = "2.0.0.200099"; - return version; + std::string new_url = url; + substitute_string(new_url, "[TOPIC]", default_subs["TOPIC"].asString()); + substitute_string(new_url, "[VERSION]", gVersion); + substitute_string(new_url, "[CHANNEL]", gChannel); + substitute_string(new_url, "[LANGUAGE]", gLanguage); + substitute_string(new_url, "[GRID]", gGrid); + substitute_string(new_url, "[OS]", gOS); + return new_url; } //---------------------------------------------------------------------------- @@ -101,41 +106,52 @@ namespace tut template<> template<> void viewerhelputil_object_t::test<1>() { - LLOSInfo osinfo; - LLControlGroup cgr("test"); - cgr.declareString("HelpURLFormat", "fooformat", "declared_for_test", FALSE); - cgr.declareString("VersionChannelName", "foochannelname", "declared_for_test", FALSE); - cgr.declareString("Language", "foolanguage", "declared_for_test", FALSE); std::string topic("test_topic"); - std::string subresult; - cgr.setString("HelpURLFormat", "fooformat"); - subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + gHelpURL = "fooformat"; + subresult = LLViewerHelpUtil::buildHelpURL(topic); ensure_equals("no substitution tags", subresult, "fooformat"); - cgr.setString("HelpURLFormat", ""); - subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + gHelpURL = ""; + subresult = LLViewerHelpUtil::buildHelpURL(topic); ensure_equals("blank substitution format", subresult, ""); - cgr.setString("HelpURLFormat", "[LANGUAGE]"); - cgr.setString("Language", ""); - subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + gHelpURL = "[TOPIC]"; + subresult = LLViewerHelpUtil::buildHelpURL(topic); + ensure_equals("topic name", subresult, "test_topic"); + + gHelpURL = "[LANGUAGE]"; + gLanguage = ""; + subresult = LLViewerHelpUtil::buildHelpURL(topic); ensure_equals("simple substitution with blank", subresult, ""); - cgr.setString("HelpURLFormat", "[LANGUAGE]"); - cgr.setString("Language", "Esperanto"); - subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + gHelpURL = "[LANGUAGE]"; + gLanguage = "Esperanto"; + subresult = LLViewerHelpUtil::buildHelpURL(topic); ensure_equals("simple substitution", subresult, "Esperanto"); - cgr.setString("HelpURLFormat", "[XXX]"); - subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + gHelpURL = "http://secondlife.com/[LANGUAGE]"; + gLanguage = "Gaelic"; + subresult = LLViewerHelpUtil::buildHelpURL(topic); + ensure_equals("simple substitution with url", subresult, "http://secondlife.com/Gaelic"); + + gHelpURL = "[XXX]"; + subresult = LLViewerHelpUtil::buildHelpURL(topic); ensure_equals("unknown substitution", subresult, "[XXX]"); - cgr.setString("HelpURLFormat", "[LANGUAGE]/[LANGUAGE]"); - cgr.setString("Language", "Esperanto"); - subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + gHelpURL = "[LANGUAGE]/[LANGUAGE]"; + gLanguage = "Esperanto"; + subresult = LLViewerHelpUtil::buildHelpURL(topic); ensure_equals("multiple substitution", subresult, "Esperanto/Esperanto"); + + gHelpURL = "http://[CHANNEL]/[VERSION]/[LANGUAGE]/[OS]/[GRID]/[XXX]"; + gChannel = "Second Life Test"; + gVersion = "2.0"; + gLanguage = "gaelic"; + gOS = "AmigaOS 2.1"; + gGrid = "mysim"; + subresult = LLViewerHelpUtil::buildHelpURL(topic); + ensure_equals("complex substitution", subresult, "http://Second Life Test/2.0/gaelic/AmigaOS 2.1/mysim/[XXX]"); } - } diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 24d92c37ad..59b674b1b8 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -363,6 +363,7 @@ class WindowsManifest(ViewerManifest): self.path("qtnetwork4.dll") self.path("qtopengl4.dll") self.path("qtwebkit4.dll") + self.path("qtxmlpatterns4.dll") self.path("ssleay32.dll") # For WebKit/Qt plugin runtimes (image format plugins) @@ -846,7 +847,7 @@ class Linux_i686Manifest(LinuxManifest): # plugins if self.prefix(src="", dst="bin/llplugin"): self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") - self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_quicktime.so") + self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") self.end_prefix("bin/llplugin") self.path("featuretable_linux.txt") diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt index 0011daaec6..89e2d8582d 100644 --- a/indra/test_apps/llplugintest/CMakeLists.txt +++ b/indra/test_apps/llplugintest/CMakeLists.txt @@ -338,6 +338,13 @@ add_custom_command(TARGET llmediaplugintest POST_BUILD DEPENDS ${BUILT_SLPLUGIN} ) +get_target_property(BUILT_LLCOMMON llcommon LOCATION) +add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON} ${PLUGINS_DESTINATION_DIR} + DEPENDS ${BUILT_LLCOMMON} +) + + if (DARWIN OR WINDOWS) get_target_property(BUILT_WEBKIT_PLUGIN media_plugin_webkit LOCATION) add_custom_command(TARGET llmediaplugintest POST_BUILD @@ -435,6 +442,7 @@ if(WINDOWS) qtnetwork4.dll qtopengl4.dll qtwebkit4.dll + qtxmlpatterns4.dll ssleay32.dll ) copy_if_different( diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index 30d338292e..d183aac208 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -1537,7 +1537,7 @@ void LLMediaPluginTest::addMediaPanel( std::string url ) char cwd[ FILENAME_MAX ]; if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) { - std::cerr << "Couldn't get cwd - probably too long - failing to init." << llendl; + std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl; return; } std::string user_data_path = std::string( cwd ) + "/"; @@ -1774,7 +1774,7 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url ) char cwd[ FILENAME_MAX ]; if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) { - std::cerr << "Couldn't get cwd - probably too long - failing to init." << llendl; + std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl; return; } std::string user_data_path = std::string( cwd ) + "/"; diff --git a/install.xml b/install.xml index 2d60f07c11..2e317755da 100644 --- a/install.xml +++ b/install.xml @@ -948,9 +948,9 @@ anguage Infrstructure (CLI) international standard</string> <key>darwin</key> <map> <key>md5sum</key> - <string>7f818f13faf7c02838fe66f7d27e1913</string> + <string>44fe5bca65db2951ce91b5b6c8596ee0</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-darwin-20091124.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20091215.tar.bz2</uri> </map> <key>linux</key> <map> @@ -962,9 +962,9 @@ anguage Infrstructure (CLI) international standard</string> <key>windows</key> <map> <key>md5sum</key> - <string>92cff05661b5547caae7cc6c66d09870</string> + <string>3846354e2e20a98c0401317eb114ff5e</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-20091123.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20091215.tar.bz2</uri> </map> </map> </map> |